Added few more stubs so that control reaches to DestroyDevice().
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_texture.c
1 /*
2 * Copyright (C) 2009 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27 #include "nouveau_driver.h"
28 #include "nouveau_context.h"
29 #include "nouveau_texture.h"
30 #include "nouveau_fbo.h"
31 #include "nouveau_util.h"
32
33 #include "main/pbo.h"
34 #include "main/texobj.h"
35 #include "main/texstore.h"
36 #include "main/texformat.h"
37 #include "main/texcompress.h"
38 #include "main/texgetimage.h"
39 #include "main/mipmap.h"
40 #include "main/teximage.h"
41 #include "util/u_memory.h"
42 #include "drivers/common/meta.h"
43 #include "swrast/s_texfetch.h"
44 #include "util/macros.h"
45
46
47 static struct gl_texture_object *
48 nouveau_texture_new(struct gl_context *ctx, GLuint name, GLenum target)
49 {
50 struct nouveau_texture *nt = CALLOC_STRUCT(nouveau_texture);
51
52 _mesa_initialize_texture_object(ctx, &nt->base, name, target);
53
54 return &nt->base;
55 }
56
57 static void
58 nouveau_texture_free(struct gl_context *ctx, struct gl_texture_object *t)
59 {
60 struct nouveau_texture *nt = to_nouveau_texture(t);
61 int i;
62
63 for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
64 nouveau_surface_ref(NULL, &nt->surfaces[i]);
65
66 _mesa_delete_texture_object(ctx, t);
67 }
68
69 static struct gl_texture_image *
70 nouveau_teximage_new(struct gl_context *ctx)
71 {
72 struct nouveau_teximage *nti = CALLOC_STRUCT(nouveau_teximage);
73
74 return &nti->base.Base;
75 }
76
77 static void
78 nouveau_teximage_free(struct gl_context *ctx, struct gl_texture_image *ti)
79 {
80 struct nouveau_teximage *nti = to_nouveau_teximage(ti);
81
82 nouveau_surface_ref(NULL, &nti->surface);
83 }
84
85 static void
86 nouveau_map_texture_image(struct gl_context *ctx,
87 struct gl_texture_image *ti,
88 GLuint slice,
89 GLuint x, GLuint y, GLuint w, GLuint h,
90 GLbitfield mode,
91 GLubyte **map,
92 GLint *stride)
93 {
94 struct nouveau_teximage *nti = to_nouveau_teximage(ti);
95 struct nouveau_surface *s = &nti->surface;
96 struct nouveau_surface *st = &nti->transfer.surface;
97 struct nouveau_client *client = context_client(ctx);
98
99 /* Nouveau has no support for 3D or cubemap textures. */
100 assert(slice == 0);
101
102 if (s->bo) {
103 if (!(mode & GL_MAP_READ_BIT) &&
104 nouveau_pushbuf_refd(context_push(ctx), s->bo)) {
105 unsigned size;
106 /*
107 * Heuristic: use a bounce buffer to pipeline
108 * teximage transfers.
109 */
110 st->layout = LINEAR;
111 st->format = s->format;
112 st->cpp = s->cpp;
113 st->width = w;
114 st->height = h;
115 st->pitch = s->pitch;
116 nti->transfer.x = x;
117 nti->transfer.y = y;
118
119 size = get_format_blocksy(st->format, h) * st->pitch;
120 *map = nouveau_get_scratch(ctx, size,
121 &st->bo, &st->offset);
122 *stride = st->pitch;
123 } else {
124 int ret, flags = 0;
125
126 if (mode & GL_MAP_READ_BIT)
127 flags |= NOUVEAU_BO_RD;
128 if (mode & GL_MAP_WRITE_BIT)
129 flags |= NOUVEAU_BO_WR;
130
131 if (!s->bo->map) {
132 ret = nouveau_bo_map(s->bo, flags, client);
133 assert(!ret);
134 }
135
136 *map = s->bo->map +
137 get_format_blocksy(s->format, y) * s->pitch +
138 get_format_blocksx(s->format, x) * s->cpp;
139 *stride = s->pitch;
140 }
141 } else {
142 *map = nti->base.Buffer +
143 get_format_blocksy(s->format, y) * s->pitch +
144 get_format_blocksx(s->format, x) * s->cpp;
145 *stride = s->pitch;
146 }
147 }
148
149 static void
150 nouveau_unmap_texture_image(struct gl_context *ctx, struct gl_texture_image *ti,
151 GLuint slice)
152 {
153 struct nouveau_teximage *nti = to_nouveau_teximage(ti);
154 struct nouveau_surface *s = &nti->surface;
155 struct nouveau_surface *st = &nti->transfer.surface;
156
157 if (st->bo) {
158 context_drv(ctx)->surface_copy(ctx, s, st, nti->transfer.x,
159 nti->transfer.y, 0, 0,
160 st->width, st->height);
161 nouveau_surface_ref(NULL, st);
162
163 }
164 }
165
166 static mesa_format
167 nouveau_choose_tex_format(struct gl_context *ctx, GLenum target,
168 GLint internalFormat,
169 GLenum srcFormat, GLenum srcType)
170 {
171 switch (internalFormat) {
172 case 4:
173 case GL_RGBA:
174 case GL_RGBA2:
175 case GL_RGBA4:
176 case GL_RGBA8:
177 case GL_RGBA12:
178 case GL_RGBA16:
179 case GL_RGB10_A2:
180 case GL_COMPRESSED_RGBA:
181 return MESA_FORMAT_B8G8R8A8_UNORM;
182 case GL_RGB5_A1:
183 return MESA_FORMAT_B5G5R5A1_UNORM;
184
185 case GL_RGB:
186 case GL_RGB8:
187 case GL_RGB10:
188 case GL_RGB12:
189 case GL_RGB16:
190 case GL_COMPRESSED_RGB:
191 return MESA_FORMAT_B8G8R8X8_UNORM;
192 case 3:
193 case GL_R3_G3_B2:
194 case GL_RGB4:
195 case GL_RGB5:
196 return MESA_FORMAT_B5G6R5_UNORM;
197
198 case 2:
199 case GL_LUMINANCE_ALPHA:
200 case GL_LUMINANCE4_ALPHA4:
201 case GL_LUMINANCE6_ALPHA2:
202 case GL_LUMINANCE12_ALPHA4:
203 case GL_LUMINANCE12_ALPHA12:
204 case GL_LUMINANCE16_ALPHA16:
205 case GL_LUMINANCE8_ALPHA8:
206 case GL_COMPRESSED_LUMINANCE_ALPHA:
207 return MESA_FORMAT_B8G8R8A8_UNORM;
208
209 case 1:
210 case GL_LUMINANCE:
211 case GL_LUMINANCE4:
212 case GL_LUMINANCE12:
213 case GL_LUMINANCE16:
214 case GL_LUMINANCE8:
215 case GL_COMPRESSED_LUMINANCE:
216 return MESA_FORMAT_L_UNORM8;
217
218 case GL_ALPHA:
219 case GL_ALPHA4:
220 case GL_ALPHA12:
221 case GL_ALPHA16:
222 case GL_ALPHA8:
223 case GL_COMPRESSED_ALPHA:
224 return MESA_FORMAT_A_UNORM8;
225
226 case GL_INTENSITY:
227 case GL_INTENSITY4:
228 case GL_INTENSITY12:
229 case GL_INTENSITY16:
230 case GL_INTENSITY8:
231 case GL_COMPRESSED_INTENSITY:
232 return MESA_FORMAT_I_UNORM8;
233
234 case GL_RGB_S3TC:
235 case GL_RGB4_S3TC:
236 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
237 return MESA_FORMAT_RGB_DXT1;
238
239 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
240 return MESA_FORMAT_RGBA_DXT1;
241
242 case GL_RGBA_S3TC:
243 case GL_RGBA4_S3TC:
244 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
245 return MESA_FORMAT_RGBA_DXT3;
246
247 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
248 return MESA_FORMAT_RGBA_DXT5;
249
250 default:
251 unreachable("Unknown format");
252 }
253 }
254
255 static GLboolean
256 teximage_fits(struct gl_texture_object *t, int level)
257 {
258 struct nouveau_surface *s = &to_nouveau_texture(t)->surfaces[level];
259 struct gl_texture_image *ti = t->Image[0][level];
260
261 if (!ti || !to_nouveau_teximage(ti)->surface.bo)
262 return GL_FALSE;
263
264 if (level == t->BaseLevel && (s->offset & 0x7f))
265 return GL_FALSE;
266
267 return t->Target == GL_TEXTURE_RECTANGLE ||
268 (s->bo && s->format == ti->TexFormat &&
269 s->width == ti->Width && s->height == ti->Height);
270 }
271
272 static GLboolean
273 validate_teximage(struct gl_context *ctx, struct gl_texture_object *t,
274 int level, int x, int y, int z,
275 int width, int height, int depth)
276 {
277 struct gl_texture_image *ti = t->Image[0][level];
278
279 if (teximage_fits(t, level)) {
280 struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
281 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
282
283 if (t->Target == GL_TEXTURE_RECTANGLE)
284 nouveau_surface_ref(s, &ss[level]);
285 else
286 context_drv(ctx)->surface_copy(ctx, &ss[level], s,
287 x, y, x, y,
288 width, height);
289
290 return GL_TRUE;
291 }
292
293 return GL_FALSE;
294 }
295
296 static int
297 get_last_level(struct gl_texture_object *t)
298 {
299 struct gl_texture_image *base = t->Image[0][t->BaseLevel];
300
301 if (t->Sampler.MinFilter == GL_NEAREST ||
302 t->Sampler.MinFilter == GL_LINEAR || !base)
303 return t->BaseLevel;
304 else
305 return MIN2(t->BaseLevel + base->MaxNumLevels - 1, t->MaxLevel);
306 }
307
308 static void
309 relayout_texture(struct gl_context *ctx, struct gl_texture_object *t)
310 {
311 struct gl_texture_image *base = t->Image[0][t->BaseLevel];
312
313 if (base && t->Target != GL_TEXTURE_RECTANGLE) {
314 struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
315 struct nouveau_surface *s = &to_nouveau_teximage(base)->surface;
316 int i, ret, last = get_last_level(t);
317 enum nouveau_surface_layout layout =
318 (_mesa_is_format_compressed(s->format) ? LINEAR : SWIZZLED);
319 unsigned size, pitch, offset = 0,
320 width = s->width,
321 height = s->height;
322
323 /* Deallocate the old storage. */
324 for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
325 nouveau_bo_ref(NULL, &ss[i].bo);
326
327 /* Relayout the mipmap tree. */
328 for (i = t->BaseLevel; i <= last; i++) {
329 pitch = _mesa_format_row_stride(s->format, width);
330 size = get_format_blocksy(s->format, height) * pitch;
331
332 /* Images larger than 16B have to be aligned. */
333 if (size > 16)
334 offset = align(offset, 64);
335
336 ss[i] = (struct nouveau_surface) {
337 .offset = offset,
338 .layout = layout,
339 .format = s->format,
340 .width = width,
341 .height = height,
342 .cpp = s->cpp,
343 .pitch = pitch,
344 };
345
346 offset += size;
347 width = minify(width, 1);
348 height = minify(height, 1);
349 }
350
351 if (t->BaseLevel <= last) {
352 /* Get new storage. */
353 size = align(offset, 64);
354 assert(size);
355
356 ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_MAP |
357 NOUVEAU_BO_GART | NOUVEAU_BO_VRAM,
358 0, size, NULL, &ss[last].bo);
359 assert(!ret);
360
361 for (i = t->BaseLevel; i < last; i++)
362 nouveau_bo_ref(ss[last].bo, &ss[i].bo);
363 }
364 }
365 }
366
367 GLboolean
368 nouveau_texture_validate(struct gl_context *ctx, struct gl_texture_object *t)
369 {
370 struct nouveau_texture *nt = to_nouveau_texture(t);
371 int i, last = get_last_level(t);
372
373 if (!teximage_fits(t, t->BaseLevel) ||
374 !teximage_fits(t, last))
375 return GL_FALSE;
376
377 if (nt->dirty) {
378 nt->dirty = GL_FALSE;
379
380 /* Copy the teximages to the actual miptree. */
381 for (i = t->BaseLevel; i <= last; i++) {
382 struct nouveau_surface *s = &nt->surfaces[i];
383
384 validate_teximage(ctx, t, i, 0, 0, 0,
385 s->width, s->height, 1);
386 }
387
388 PUSH_KICK(context_push(ctx));
389 }
390
391 return GL_TRUE;
392 }
393
394 void
395 nouveau_texture_reallocate(struct gl_context *ctx, struct gl_texture_object *t)
396 {
397 if (!teximage_fits(t, t->BaseLevel) ||
398 !teximage_fits(t, get_last_level(t))) {
399 texture_dirty(t);
400 relayout_texture(ctx, t);
401 nouveau_texture_validate(ctx, t);
402 }
403 }
404
405 static unsigned
406 get_teximage_placement(struct gl_texture_image *ti)
407 {
408 if (ti->TexFormat == MESA_FORMAT_A_UNORM8 ||
409 ti->TexFormat == MESA_FORMAT_L_UNORM8 ||
410 ti->TexFormat == MESA_FORMAT_I_UNORM8)
411 /* 1 cpp formats will have to be swizzled by the CPU,
412 * so leave them in system RAM for now. */
413 return NOUVEAU_BO_MAP;
414 else
415 return NOUVEAU_BO_GART | NOUVEAU_BO_MAP;
416 }
417
418 static void
419 nouveau_compressed_copy(struct gl_context *ctx, GLint dims,
420 struct gl_texture_image *ti,
421 GLsizei width, GLsizei height, GLsizei depth,
422 const GLvoid *src, GLvoid *dst, int row_stride)
423 {
424 struct compressed_pixelstore store;
425 int i;
426
427 _mesa_compute_compressed_pixelstore(dims, ti->TexFormat,
428 width, height, depth,
429 &ctx->Unpack, &store);
430
431 src += store.SkipBytes;
432
433 assert(store.CopySlices == 1);
434
435 /* copy rows of blocks */
436 for (i = 0; i < store.CopyRowsPerSlice; i++) {
437 memcpy(dst, src, store.CopyBytesPerRow);
438 dst += row_stride;
439 src += store.TotalBytesPerRow;
440 }
441 }
442
443 static void
444 nouveau_teximage(struct gl_context *ctx, GLint dims,
445 struct gl_texture_image *ti,
446 GLsizei imageSize,
447 GLenum format, GLenum type, const GLvoid *pixels,
448 const struct gl_pixelstore_attrib *packing,
449 GLboolean compressed)
450 {
451 struct gl_texture_object *t = ti->TexObject;
452 const GLuint level = ti->Level;
453 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
454 struct nouveau_teximage *nti = to_nouveau_teximage(ti);
455 int ret;
456 GLuint depth = compressed ? 1 : ti->Depth;
457
458 /* Allocate a new bo for the image. */
459 nouveau_surface_alloc(ctx, s, LINEAR, get_teximage_placement(ti),
460 ti->TexFormat, ti->Width, ti->Height);
461 nti->base.RowStride = s->pitch / s->cpp;
462
463 if (compressed)
464 pixels = _mesa_validate_pbo_compressed_teximage(ctx,
465 dims, imageSize,
466 pixels, packing, "glCompressedTexImage");
467 else
468 pixels = _mesa_validate_pbo_teximage(ctx,
469 dims, ti->Width, ti->Height, depth, format, type,
470 pixels, packing, "glTexImage");
471
472 if (pixels) {
473 GLubyte *map;
474 int row_stride;
475
476 /* Store the pixel data. */
477 nouveau_map_texture_image(ctx, ti, 0,
478 0, 0, ti->Width, ti->Height,
479 GL_MAP_WRITE_BIT,
480 &map, &row_stride);
481
482 if (compressed) {
483 nouveau_compressed_copy(ctx, dims, ti,
484 ti->Width, ti->Height, depth,
485 pixels, map, row_stride);
486 } else {
487 ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
488 ti->TexFormat,
489 row_stride,
490 &map,
491 ti->Width, ti->Height, depth,
492 format, type, pixels, packing);
493 assert(ret);
494 }
495
496 nouveau_unmap_texture_image(ctx, ti, 0);
497 _mesa_unmap_teximage_pbo(ctx, packing);
498
499 if (!validate_teximage(ctx, t, level, 0, 0, 0,
500 ti->Width, ti->Height, depth))
501 /* It doesn't fit, mark it as dirty. */
502 texture_dirty(t);
503 }
504
505 if (level == t->BaseLevel) {
506 if (!teximage_fits(t, level))
507 relayout_texture(ctx, t);
508 nouveau_texture_validate(ctx, t);
509 }
510
511 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
512 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
513 }
514
515
516 static void
517 nouveau_teximage_123d(struct gl_context *ctx, GLuint dims,
518 struct gl_texture_image *ti,
519 GLenum format, GLenum type, const GLvoid *pixels,
520 const struct gl_pixelstore_attrib *packing)
521 {
522 nouveau_teximage(ctx, dims, ti, 0, format, type, pixels,
523 packing, GL_FALSE);
524 }
525
526 static void
527 nouveau_compressed_teximage(struct gl_context *ctx, GLuint dims,
528 struct gl_texture_image *ti,
529 GLsizei imageSize, const GLvoid *data)
530 {
531 nouveau_teximage(ctx, 2, ti, imageSize, 0, 0, data,
532 &ctx->Unpack, GL_TRUE);
533 }
534
535 static GLboolean
536 nouveau_teximage_alloc(struct gl_context *ctx, struct gl_texture_image *ti)
537 {
538 nouveau_teximage(ctx, 3, ti, 0, 0, 0, NULL,
539 &ctx->DefaultPacking,
540 _mesa_is_format_compressed(ti->TexFormat));
541 return GL_TRUE;
542 }
543
544 static void
545 nouveau_texsubimage(struct gl_context *ctx, GLint dims,
546 struct gl_texture_image *ti,
547 GLint xoffset, GLint yoffset, GLint zoffset,
548 GLint width, GLint height, GLint depth,
549 GLsizei imageSize,
550 GLenum format, GLenum type, const void *pixels,
551 const struct gl_pixelstore_attrib *packing,
552 GLboolean compressed)
553 {
554 int ret;
555
556 if (compressed)
557 pixels = _mesa_validate_pbo_compressed_teximage(ctx,
558 dims, imageSize,
559 pixels, packing, "glCompressedTexSubImage");
560 else
561 pixels = _mesa_validate_pbo_teximage(ctx,
562 dims, width, height, depth, format, type,
563 pixels, packing, "glTexSubImage");
564
565 if (pixels) {
566 GLubyte *map;
567 int row_stride;
568
569 nouveau_map_texture_image(ctx, ti, 0,
570 xoffset, yoffset, width, height,
571 GL_MAP_WRITE_BIT, &map, &row_stride);
572
573 if (compressed) {
574 nouveau_compressed_copy(ctx, dims, ti,
575 width, height, depth,
576 pixels, map, row_stride);
577 } else {
578 ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
579 ti->TexFormat,
580 row_stride, &map,
581 width, height, depth,
582 format, type, pixels, packing);
583 assert(ret);
584 }
585
586 nouveau_unmap_texture_image(ctx, ti, 0);
587 _mesa_unmap_teximage_pbo(ctx, packing);
588 }
589
590 if (!to_nouveau_texture(ti->TexObject)->dirty)
591 validate_teximage(ctx, ti->TexObject, ti->Level,
592 xoffset, yoffset, zoffset,
593 width, height, depth);
594 }
595
596 static void
597 nouveau_texsubimage_123d(struct gl_context *ctx, GLuint dims,
598 struct gl_texture_image *ti,
599 GLint xoffset, GLint yoffset, GLint zoffset,
600 GLint width, GLint height, GLint depth,
601 GLenum format, GLenum type, const void *pixels,
602 const struct gl_pixelstore_attrib *packing)
603 {
604 nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset,
605 width, height, depth, 0, format, type, pixels,
606 packing, GL_FALSE);
607 }
608
609 static void
610 nouveau_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
611 struct gl_texture_image *ti,
612 GLint xoffset, GLint yoffset, GLint zoffset,
613 GLsizei width, GLint height, GLint depth,
614 GLenum format,
615 GLint imageSize, const void *data)
616 {
617 nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset,
618 width, height, depth, imageSize, format, 0, data,
619 &ctx->Unpack, GL_TRUE);
620 }
621
622 static void
623 nouveau_bind_texture(struct gl_context *ctx, GLuint texUnit,
624 GLenum target, struct gl_texture_object *t)
625 {
626 context_dirty_i(ctx, TEX_OBJ, texUnit);
627 context_dirty_i(ctx, TEX_ENV, texUnit);
628 }
629
630 static mesa_format
631 get_texbuffer_format(struct gl_renderbuffer *rb, GLint format)
632 {
633 struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
634
635 if (s->cpp < 4)
636 return s->format;
637 else if (format == __DRI_TEXTURE_FORMAT_RGBA)
638 return MESA_FORMAT_B8G8R8A8_UNORM;
639 else
640 return MESA_FORMAT_B8G8R8X8_UNORM;
641 }
642
643 void
644 nouveau_set_texbuffer(__DRIcontext *dri_ctx,
645 GLint target, GLint format,
646 __DRIdrawable *draw)
647 {
648 struct nouveau_context *nctx = dri_ctx->driverPrivate;
649 struct gl_context *ctx = &nctx->base;
650 struct gl_framebuffer *fb = draw->driverPrivate;
651 struct gl_renderbuffer *rb =
652 fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
653 struct gl_texture_object *t = _mesa_get_current_tex_object(ctx, target);
654 struct gl_texture_image *ti;
655 struct nouveau_teximage *nti;
656 struct nouveau_surface *s;
657
658 _mesa_lock_texture(ctx, t);
659 ti = _mesa_get_tex_image(ctx, t, target, 0);
660 nti = to_nouveau_teximage(ti);
661 s = &to_nouveau_teximage(ti)->surface;
662
663 /* Update the texture surface with the given drawable. */
664 nouveau_update_renderbuffers(dri_ctx, draw);
665 nouveau_surface_ref(&to_nouveau_renderbuffer(rb)->surface, s);
666
667 s->format = get_texbuffer_format(rb, format);
668
669 /* Update the image fields. */
670 _mesa_init_teximage_fields(ctx, ti, s->width, s->height,
671 1, 0, s->cpp, s->format);
672 nti->base.RowStride = s->pitch / s->cpp;
673
674 /* Try to validate it. */
675 if (!validate_teximage(ctx, t, 0, 0, 0, 0, s->width, s->height, 1))
676 nouveau_texture_reallocate(ctx, t);
677
678 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
679 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
680
681 _mesa_unlock_texture(ctx, t);
682 }
683
684 void
685 nouveau_texture_functions_init(struct dd_function_table *functions)
686 {
687 functions->NewTextureObject = nouveau_texture_new;
688 functions->DeleteTexture = nouveau_texture_free;
689 functions->NewTextureImage = nouveau_teximage_new;
690 functions->FreeTextureImageBuffer = nouveau_teximage_free;
691 functions->AllocTextureImageBuffer = nouveau_teximage_alloc;
692 functions->ChooseTextureFormat = nouveau_choose_tex_format;
693 functions->TexImage = nouveau_teximage_123d;
694 functions->TexSubImage = nouveau_texsubimage_123d;
695 functions->CompressedTexImage = nouveau_compressed_teximage;
696 functions->CompressedTexSubImage = nouveau_compressed_texsubimage;
697 functions->BindTexture = nouveau_bind_texture;
698 functions->MapTextureImage = nouveau_map_texture_image;
699 functions->UnmapTextureImage = nouveau_unmap_texture_image;
700 }