Merge branch 'master' into pipe-video
[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/texobj.h"
34 #include "main/texstore.h"
35 #include "main/texformat.h"
36 #include "main/texcompress.h"
37 #include "main/texgetimage.h"
38 #include "main/mipmap.h"
39 #include "main/texfetch.h"
40 #include "main/teximage.h"
41 #include "drivers/common/meta.h"
42
43 static struct gl_texture_object *
44 nouveau_texture_new(GLcontext *ctx, GLuint name, GLenum target)
45 {
46 struct nouveau_texture *nt = CALLOC_STRUCT(nouveau_texture);
47
48 _mesa_initialize_texture_object(&nt->base, name, target);
49
50 return &nt->base;
51 }
52
53 static void
54 nouveau_texture_free(GLcontext *ctx, struct gl_texture_object *t)
55 {
56 struct nouveau_texture *nt = to_nouveau_texture(t);
57 int i;
58
59 for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
60 nouveau_surface_ref(NULL, &nt->surfaces[i]);
61
62 _mesa_delete_texture_object(ctx, t);
63 }
64
65 static struct gl_texture_image *
66 nouveau_teximage_new(GLcontext *ctx)
67 {
68 struct nouveau_teximage *nti = CALLOC_STRUCT(nouveau_teximage);
69
70 return &nti->base;
71 }
72
73 static void
74 nouveau_teximage_free(GLcontext *ctx, struct gl_texture_image *ti)
75 {
76 struct nouveau_teximage *nti = to_nouveau_teximage(ti);
77
78 nouveau_surface_ref(NULL, &nti->surface);
79 }
80
81 static void
82 nouveau_teximage_map(GLcontext *ctx, struct gl_texture_image *ti)
83 {
84 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
85 int ret;
86
87 if (s->bo) {
88 ret = nouveau_bo_map(s->bo, NOUVEAU_BO_RDWR);
89 assert(!ret);
90
91 ti->Data = s->bo->map;
92 }
93 }
94
95 static void
96 nouveau_teximage_unmap(GLcontext *ctx, struct gl_texture_image *ti)
97 {
98 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
99
100 if (s->bo)
101 nouveau_bo_unmap(s->bo);
102 ti->Data = NULL;
103 }
104
105 static gl_format
106 nouveau_choose_tex_format(GLcontext *ctx, GLint internalFormat,
107 GLenum srcFormat, GLenum srcType)
108 {
109 switch (internalFormat) {
110 case 4:
111 case GL_RGBA:
112 case GL_RGBA2:
113 case GL_RGBA4:
114 case GL_RGBA8:
115 case GL_RGBA12:
116 case GL_RGBA16:
117 case GL_RGB10_A2:
118 return MESA_FORMAT_ARGB8888;
119 case GL_RGB5_A1:
120 return MESA_FORMAT_ARGB1555;
121
122 case GL_RGB:
123 case GL_RGB8:
124 case GL_RGB10:
125 case GL_RGB12:
126 case GL_RGB16:
127 return MESA_FORMAT_XRGB8888;
128 case 3:
129 case GL_R3_G3_B2:
130 case GL_RGB4:
131 case GL_RGB5:
132 return MESA_FORMAT_RGB565;
133
134 case 2:
135 case GL_LUMINANCE_ALPHA:
136 case GL_LUMINANCE4_ALPHA4:
137 case GL_LUMINANCE6_ALPHA2:
138 case GL_LUMINANCE12_ALPHA4:
139 case GL_LUMINANCE12_ALPHA12:
140 case GL_LUMINANCE16_ALPHA16:
141 case GL_LUMINANCE8_ALPHA8:
142 return MESA_FORMAT_ARGB8888;
143
144 case 1:
145 case GL_LUMINANCE:
146 case GL_LUMINANCE4:
147 case GL_LUMINANCE12:
148 case GL_LUMINANCE16:
149 case GL_LUMINANCE8:
150 return MESA_FORMAT_L8;
151
152 case GL_ALPHA:
153 case GL_ALPHA4:
154 case GL_ALPHA12:
155 case GL_ALPHA16:
156 case GL_ALPHA8:
157 return MESA_FORMAT_A8;
158
159 case GL_INTENSITY:
160 case GL_INTENSITY4:
161 case GL_INTENSITY12:
162 case GL_INTENSITY16:
163 case GL_INTENSITY8:
164 return MESA_FORMAT_I8;
165
166 case GL_COLOR_INDEX:
167 case GL_COLOR_INDEX1_EXT:
168 case GL_COLOR_INDEX2_EXT:
169 case GL_COLOR_INDEX4_EXT:
170 case GL_COLOR_INDEX12_EXT:
171 case GL_COLOR_INDEX16_EXT:
172 case GL_COLOR_INDEX8_EXT:
173 return MESA_FORMAT_CI8;
174
175 default:
176 assert(0);
177 }
178 }
179
180 static GLboolean
181 teximage_fits(struct gl_texture_object *t, int level)
182 {
183 struct nouveau_surface *s = &to_nouveau_texture(t)->surfaces[level];
184 struct gl_texture_image *ti = t->Image[0][level];
185
186 if (!ti || !to_nouveau_teximage(ti)->surface.bo)
187 return GL_FALSE;
188
189 if (level == t->BaseLevel && (s->offset & 0x7f))
190 return GL_FALSE;
191
192 return t->Target == GL_TEXTURE_RECTANGLE ||
193 (s->bo && s->format == ti->TexFormat &&
194 s->width == ti->Width && s->height == ti->Height);
195 }
196
197 static GLboolean
198 validate_teximage(GLcontext *ctx, struct gl_texture_object *t,
199 int level, int x, int y, int z,
200 int width, int height, int depth)
201 {
202 struct gl_texture_image *ti = t->Image[0][level];
203
204 if (teximage_fits(t, level)) {
205 struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
206 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
207
208 if (t->Target == GL_TEXTURE_RECTANGLE)
209 nouveau_surface_ref(s, &ss[level]);
210 else
211 context_drv(ctx)->surface_copy(ctx, &ss[level], s,
212 x, y, x, y,
213 width, height);
214
215 return GL_TRUE;
216 }
217
218 return GL_FALSE;
219 }
220
221 static int
222 get_last_level(struct gl_texture_object *t)
223 {
224 struct gl_texture_image *base = t->Image[0][t->BaseLevel];
225
226 if (t->MinFilter == GL_NEAREST ||
227 t->MinFilter == GL_LINEAR || !base)
228 return t->BaseLevel;
229 else
230 return MIN2(t->BaseLevel + base->MaxLog2, t->MaxLevel);
231 }
232
233 static void
234 relayout_texture(GLcontext *ctx, struct gl_texture_object *t)
235 {
236 struct gl_texture_image *base = t->Image[0][t->BaseLevel];
237
238 if (base && t->Target != GL_TEXTURE_RECTANGLE) {
239 struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces;
240 struct nouveau_surface *s = &to_nouveau_teximage(base)->surface;
241 int i, ret, last = get_last_level(t);
242 unsigned size, offset = 0,
243 width = s->width,
244 height = s->height;
245
246 /* Deallocate the old storage. */
247 for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
248 nouveau_bo_ref(NULL, &ss[i].bo);
249
250 /* Relayout the mipmap tree. */
251 for (i = t->BaseLevel; i <= last; i++) {
252 size = width * height * s->cpp;
253
254 /* Images larger than 16B have to be aligned. */
255 if (size > 16)
256 offset = align(offset, 64);
257
258 ss[i] = (struct nouveau_surface) {
259 .offset = offset,
260 .layout = SWIZZLED,
261 .format = s->format,
262 .width = width,
263 .height = height,
264 .cpp = s->cpp,
265 .pitch = width * s->cpp,
266 };
267
268 offset += size;
269 width = MAX2(1, width / 2);
270 height = MAX2(1, height / 2);
271 }
272
273 /* Get new storage. */
274 size = align(offset, 64);
275
276 ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_MAP |
277 NOUVEAU_BO_GART | NOUVEAU_BO_VRAM,
278 0, size, &ss[last].bo);
279 assert(!ret);
280
281 for (i = t->BaseLevel; i < last; i++)
282 nouveau_bo_ref(ss[last].bo, &ss[i].bo);
283 }
284 }
285
286 GLboolean
287 nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t)
288 {
289 struct nouveau_texture *nt = to_nouveau_texture(t);
290 int i, last = get_last_level(t);
291
292 if (!teximage_fits(t, t->BaseLevel) ||
293 !teximage_fits(t, last))
294 return GL_FALSE;
295
296 if (nt->dirty) {
297 nt->dirty = GL_FALSE;
298
299 /* Copy the teximages to the actual miptree. */
300 for (i = t->BaseLevel; i <= last; i++) {
301 struct nouveau_surface *s = &nt->surfaces[i];
302
303 validate_teximage(ctx, t, i, 0, 0, 0,
304 s->width, s->height, 1);
305 }
306
307 FIRE_RING(context_chan(ctx));
308 }
309
310 return GL_TRUE;
311 }
312
313 void
314 nouveau_texture_reallocate(GLcontext *ctx, struct gl_texture_object *t)
315 {
316 if (!teximage_fits(t, t->BaseLevel) ||
317 !teximage_fits(t, get_last_level(t))) {
318 texture_dirty(t);
319 relayout_texture(ctx, t);
320 nouveau_texture_validate(ctx, t);
321 }
322 }
323
324 static unsigned
325 get_teximage_placement(struct gl_texture_image *ti)
326 {
327 if (ti->TexFormat == MESA_FORMAT_A8 ||
328 ti->TexFormat == MESA_FORMAT_L8 ||
329 ti->TexFormat == MESA_FORMAT_I8)
330 /* 1 cpp formats will have to be swizzled by the CPU,
331 * so leave them in system RAM for now. */
332 return NOUVEAU_BO_MAP;
333 else
334 return NOUVEAU_BO_GART | NOUVEAU_BO_MAP;
335 }
336
337 static void
338 nouveau_teximage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
339 GLint internalFormat,
340 GLint width, GLint height, GLint depth, GLint border,
341 GLenum format, GLenum type, const GLvoid *pixels,
342 const struct gl_pixelstore_attrib *packing,
343 struct gl_texture_object *t,
344 struct gl_texture_image *ti)
345 {
346 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
347 int ret;
348
349 /* Allocate a new bo for the image. */
350 nouveau_surface_alloc(ctx, s, LINEAR, get_teximage_placement(ti),
351 ti->TexFormat, width, height);
352 ti->RowStride = s->pitch / s->cpp;
353
354 pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
355 format, type, pixels, packing,
356 "glTexImage");
357 if (pixels) {
358 /* Store the pixel data. */
359 nouveau_teximage_map(ctx, ti);
360
361 ret = _mesa_texstore(ctx, dims, ti->_BaseFormat,
362 ti->TexFormat, ti->Data,
363 0, 0, 0, s->pitch,
364 ti->ImageOffsets,
365 width, height, depth,
366 format, type, pixels, packing);
367 assert(ret);
368
369 nouveau_teximage_unmap(ctx, ti);
370 _mesa_unmap_teximage_pbo(ctx, packing);
371
372 if (!validate_teximage(ctx, t, level, 0, 0, 0,
373 width, height, depth))
374 /* It doesn't fit, mark it as dirty. */
375 texture_dirty(t);
376 }
377
378 if (level == t->BaseLevel) {
379 if (!teximage_fits(t, level))
380 relayout_texture(ctx, t);
381 nouveau_texture_validate(ctx, t);
382 }
383
384 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
385 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
386 }
387
388 static void
389 nouveau_teximage_1d(GLcontext *ctx, GLenum target, GLint level,
390 GLint internalFormat,
391 GLint width, GLint border,
392 GLenum format, GLenum type, const GLvoid *pixels,
393 const struct gl_pixelstore_attrib *packing,
394 struct gl_texture_object *t,
395 struct gl_texture_image *ti)
396 {
397 nouveau_teximage(ctx, 1, target, level, internalFormat,
398 width, 1, 1, border, format, type, pixels,
399 packing, t, ti);
400 }
401
402 static void
403 nouveau_teximage_2d(GLcontext *ctx, GLenum target, GLint level,
404 GLint internalFormat,
405 GLint width, GLint height, GLint border,
406 GLenum format, GLenum type, const GLvoid *pixels,
407 const struct gl_pixelstore_attrib *packing,
408 struct gl_texture_object *t,
409 struct gl_texture_image *ti)
410 {
411 nouveau_teximage(ctx, 2, target, level, internalFormat,
412 width, height, 1, border, format, type, pixels,
413 packing, t, ti);
414 }
415
416 static void
417 nouveau_teximage_3d(GLcontext *ctx, GLenum target, GLint level,
418 GLint internalFormat,
419 GLint width, GLint height, GLint depth, GLint border,
420 GLenum format, GLenum type, const GLvoid *pixels,
421 const struct gl_pixelstore_attrib *packing,
422 struct gl_texture_object *t,
423 struct gl_texture_image *ti)
424 {
425 nouveau_teximage(ctx, 3, target, level, internalFormat,
426 width, height, depth, border, format, type, pixels,
427 packing, t, ti);
428 }
429
430 static void
431 nouveau_texsubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
432 GLint xoffset, GLint yoffset, GLint zoffset,
433 GLint width, GLint height, GLint depth,
434 GLenum format, GLenum type, const void *pixels,
435 const struct gl_pixelstore_attrib *packing,
436 struct gl_texture_object *t,
437 struct gl_texture_image *ti)
438 {
439 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface;
440 int ret;
441
442 pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
443 format, type, pixels, packing,
444 "glTexSubImage");
445 if (pixels) {
446 nouveau_teximage_map(ctx, ti);
447
448 ret = _mesa_texstore(ctx, 3, ti->_BaseFormat, ti->TexFormat,
449 ti->Data, xoffset, yoffset, zoffset,
450 s->pitch, ti->ImageOffsets,
451 width, height, depth, format, type,
452 pixels, packing);
453 assert(ret);
454
455 nouveau_teximage_unmap(ctx, ti);
456 _mesa_unmap_teximage_pbo(ctx, packing);
457 }
458
459 if (!to_nouveau_texture(t)->dirty)
460 validate_teximage(ctx, t, level, xoffset, yoffset, zoffset,
461 width, height, depth);
462 }
463
464 static void
465 nouveau_texsubimage_3d(GLcontext *ctx, GLenum target, GLint level,
466 GLint xoffset, GLint yoffset, GLint zoffset,
467 GLint width, GLint height, GLint depth,
468 GLenum format, GLenum type, const void *pixels,
469 const struct gl_pixelstore_attrib *packing,
470 struct gl_texture_object *t,
471 struct gl_texture_image *ti)
472 {
473 nouveau_texsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset,
474 width, height, depth, format, type, pixels,
475 packing, t, ti);
476 }
477
478 static void
479 nouveau_texsubimage_2d(GLcontext *ctx, GLenum target, GLint level,
480 GLint xoffset, GLint yoffset,
481 GLint width, GLint height,
482 GLenum format, GLenum type, const void *pixels,
483 const struct gl_pixelstore_attrib *packing,
484 struct gl_texture_object *t,
485 struct gl_texture_image *ti)
486 {
487 nouveau_texsubimage(ctx, 2, target, level, xoffset, yoffset, 0,
488 width, height, 1, format, type, pixels,
489 packing, t, ti);
490 }
491
492 static void
493 nouveau_texsubimage_1d(GLcontext *ctx, GLenum target, GLint level,
494 GLint xoffset, GLint width,
495 GLenum format, GLenum type, const void *pixels,
496 const struct gl_pixelstore_attrib *packing,
497 struct gl_texture_object *t,
498 struct gl_texture_image *ti)
499 {
500 nouveau_texsubimage(ctx, 1, target, level, xoffset, 0, 0,
501 width, 1, 1, format, type, pixels,
502 packing, t, ti);
503 }
504
505 static void
506 nouveau_get_teximage(GLcontext *ctx, GLenum target, GLint level,
507 GLenum format, GLenum type, GLvoid *pixels,
508 struct gl_texture_object *t,
509 struct gl_texture_image *ti)
510 {
511 nouveau_teximage_map(ctx, ti);
512 _mesa_get_teximage(ctx, target, level, format, type, pixels,
513 t, ti);
514 nouveau_teximage_unmap(ctx, ti);
515 }
516
517 static void
518 nouveau_bind_texture(GLcontext *ctx, GLenum target,
519 struct gl_texture_object *t)
520 {
521 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
522 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
523 }
524
525 static gl_format
526 get_texbuffer_format(struct gl_renderbuffer *rb, GLint format)
527 {
528 struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface;
529
530 if (s->cpp < 4)
531 return s->format;
532 else if (format == __DRI_TEXTURE_FORMAT_RGBA)
533 return MESA_FORMAT_ARGB8888;
534 else
535 return MESA_FORMAT_XRGB8888;
536 }
537
538 void
539 nouveau_set_texbuffer(__DRIcontext *dri_ctx,
540 GLint target, GLint format,
541 __DRIdrawable *draw)
542 {
543 struct nouveau_context *nctx = dri_ctx->driverPrivate;
544 GLcontext *ctx = &nctx->base;
545 struct gl_framebuffer *fb = draw->driverPrivate;
546 struct gl_renderbuffer *rb =
547 fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
548 struct gl_texture_object *t = _mesa_get_current_tex_object(ctx, target);
549 struct gl_texture_image *ti;
550 struct nouveau_surface *s;
551
552 _mesa_lock_texture(ctx, t);
553 ti = _mesa_get_tex_image(ctx, t, target, 0);
554 s = &to_nouveau_teximage(ti)->surface;
555
556 /* Update the texture surface with the given drawable. */
557 nouveau_update_renderbuffers(dri_ctx, draw);
558 nouveau_surface_ref(&to_nouveau_renderbuffer(rb)->surface, s);
559
560 /* Update the image fields. */
561 _mesa_init_teximage_fields(ctx, target, ti, s->width, s->height,
562 1, 0, s->cpp);
563 ti->RowStride = s->pitch / s->cpp;
564 ti->TexFormat = s->format = get_texbuffer_format(rb, format);
565
566 /* Try to validate it. */
567 if (!validate_teximage(ctx, t, 0, 0, 0, 0, s->width, s->height, 1))
568 nouveau_texture_reallocate(ctx, t);
569
570 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit);
571 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit);
572
573 _mesa_unlock_texture(ctx, t);
574 }
575
576 static void
577 nouveau_texture_map(GLcontext *ctx, struct gl_texture_object *t)
578 {
579 int i;
580
581 for (i = t->BaseLevel; i < t->_MaxLevel; i++) {
582 if (t->Image[0][i])
583 nouveau_teximage_map(ctx, t->Image[0][i]);
584 }
585 }
586
587 static void
588 nouveau_texture_unmap(GLcontext *ctx, struct gl_texture_object *t)
589 {
590 int i;
591
592 for (i = t->BaseLevel; i < t->_MaxLevel; i++) {
593 if (t->Image[0][i])
594 nouveau_teximage_unmap(ctx, t->Image[0][i]);
595 }
596 }
597
598 static void
599 store_mipmap(GLcontext *ctx, GLenum target, int first, int last,
600 struct gl_texture_object *t)
601 {
602 struct gl_pixelstore_attrib packing = {
603 .BufferObj = ctx->Shared->NullBufferObj,
604 .Alignment = 1
605 };
606 GLenum format = t->Image[0][t->BaseLevel]->TexFormat;
607 unsigned base_format, type, comps;
608 int i;
609
610 base_format = _mesa_get_format_base_format(format);
611 _mesa_format_to_type_and_comps(format, &type, &comps);
612
613 for (i = first; i <= last; i++) {
614 struct gl_texture_image *ti = t->Image[0][i];
615 void *data = ti->Data;
616
617 nouveau_teximage(ctx, 3, target, i, ti->InternalFormat,
618 ti->Width, ti->Height, ti->Depth,
619 ti->Border, base_format, type, data,
620 &packing, t, ti);
621
622 _mesa_free_texmemory(data);
623 }
624 }
625
626 static void
627 nouveau_generate_mipmap(GLcontext *ctx, GLenum target,
628 struct gl_texture_object *t)
629 {
630 if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, t)) {
631 struct gl_texture_image *base = t->Image[0][t->BaseLevel];
632
633 nouveau_teximage_map(ctx, base);
634 _mesa_generate_mipmap(ctx, target, t);
635 nouveau_teximage_unmap(ctx, base);
636
637 store_mipmap(ctx, target, t->BaseLevel + 1,
638 get_last_level(t), t);
639
640 } else {
641 _mesa_meta_GenerateMipmap(ctx, target, t);
642 }
643 }
644
645 void
646 nouveau_texture_functions_init(struct dd_function_table *functions)
647 {
648 functions->NewTextureObject = nouveau_texture_new;
649 functions->DeleteTexture = nouveau_texture_free;
650 functions->NewTextureImage = nouveau_teximage_new;
651 functions->FreeTexImageData = nouveau_teximage_free;
652 functions->ChooseTextureFormat = nouveau_choose_tex_format;
653 functions->TexImage1D = nouveau_teximage_1d;
654 functions->TexImage2D = nouveau_teximage_2d;
655 functions->TexImage3D = nouveau_teximage_3d;
656 functions->TexSubImage1D = nouveau_texsubimage_1d;
657 functions->TexSubImage2D = nouveau_texsubimage_2d;
658 functions->TexSubImage3D = nouveau_texsubimage_3d;
659 functions->GetTexImage = nouveau_get_teximage;
660 functions->BindTexture = nouveau_bind_texture;
661 functions->MapTexture = nouveau_texture_map;
662 functions->UnmapTexture = nouveau_texture_unmap;
663 functions->GenerateMipmap = nouveau_generate_mipmap;
664 }