add missing license texts
[mesa.git] / src / mesa / drivers / dri / i915 / intel_tex.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "glheader.h"
29 #include "mtypes.h"
30 #include "imports.h"
31 #include "simple_list.h"
32 #include "enums.h"
33 #include "image.h"
34 #include "texstore.h"
35 #include "texformat.h"
36 #include "teximage.h"
37 #include "texmem.h"
38 #include "texobj.h"
39 #include "swrast/swrast.h"
40
41 #include "mm.h"
42
43 #include "intel_screen.h"
44 #include "intel_batchbuffer.h"
45 #include "intel_context.h"
46 #include "intel_tex.h"
47 #include "intel_ioctl.h"
48
49
50
51 static GLboolean
52 intelValidateClientStorage( intelContextPtr intel, GLenum target,
53 GLint internalFormat,
54 GLint srcWidth, GLint srcHeight,
55 GLenum format, GLenum type, const void *pixels,
56 const struct gl_pixelstore_attrib *packing,
57 struct gl_texture_object *texObj,
58 struct gl_texture_image *texImage)
59
60 {
61 GLcontext *ctx = &intel->ctx;
62 int texelBytes;
63
64 if (0)
65 fprintf(stderr, "intformat %s format %s type %s\n",
66 _mesa_lookup_enum_by_nr( internalFormat ),
67 _mesa_lookup_enum_by_nr( format ),
68 _mesa_lookup_enum_by_nr( type ));
69
70 if (!ctx->Unpack.ClientStorage)
71 return 0;
72
73 if (ctx->_ImageTransferState ||
74 texImage->IsCompressed ||
75 texObj->GenerateMipmap)
76 return 0;
77
78
79 /* This list is incomplete
80 */
81 switch ( internalFormat ) {
82 case GL_RGBA:
83 if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
84 texImage->TexFormat = &_mesa_texformat_argb8888;
85 texelBytes = 4;
86 }
87 else
88 return 0;
89 break;
90
91 case GL_RGB:
92 if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
93 texImage->TexFormat = &_mesa_texformat_rgb565;
94 texelBytes = 2;
95 }
96 else
97 return 0;
98 break;
99
100 case GL_YCBCR_MESA:
101 if ( format == GL_YCBCR_MESA &&
102 type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
103 texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
104 texelBytes = 2;
105 }
106 else if ( format == GL_YCBCR_MESA &&
107 (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
108 type == GL_UNSIGNED_BYTE)) {
109 texImage->TexFormat = &_mesa_texformat_ycbcr;
110 texelBytes = 2;
111 }
112 else
113 return 0;
114 break;
115
116
117 default:
118 return 0;
119 }
120
121 /* Could deal with these packing issues, but currently don't:
122 */
123 if (packing->SkipPixels ||
124 packing->SkipRows ||
125 packing->SwapBytes ||
126 packing->LsbFirst) {
127 return 0;
128 }
129
130 {
131 GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
132 format, type);
133
134
135 if (0)
136 fprintf(stderr, "%s: srcRowStride %d/%x\n",
137 __FUNCTION__, srcRowStride, srcRowStride);
138
139 /* Could check this later in upload, pitch restrictions could be
140 * relaxed, but would need to store the image pitch somewhere,
141 * as packing details might change before image is uploaded:
142 */
143 if (!intelIsAgpMemory( intel, pixels, srcHeight * srcRowStride ) ||
144 (srcRowStride & 63))
145 return 0;
146
147
148 /* Have validated that _mesa_transfer_teximage would be a straight
149 * memcpy at this point. NOTE: future calls to TexSubImage will
150 * overwrite the client data. This is explicitly mentioned in the
151 * extension spec.
152 */
153 texImage->Data = (void *)pixels;
154 texImage->IsClientData = GL_TRUE;
155 texImage->RowStride = srcRowStride / texelBytes;
156 return 1;
157 }
158 }
159
160
161
162 static void intelTexImage1D( GLcontext *ctx, GLenum target, GLint level,
163 GLint internalFormat,
164 GLint width, GLint border,
165 GLenum format, GLenum type, const GLvoid *pixels,
166 const struct gl_pixelstore_attrib *packing,
167 struct gl_texture_object *texObj,
168 struct gl_texture_image *texImage )
169 {
170 driTextureObject * t = (driTextureObject *) texObj->DriverData;
171
172 assert(t);
173 intelFlush( ctx );
174 driSwapOutTextureObject( t );
175
176 texImage->IsClientData = GL_FALSE;
177
178 _mesa_store_teximage1d( ctx, target, level, internalFormat,
179 width, border, format, type,
180 pixels, packing, texObj, texImage );
181
182 t->dirty_images[0] |= (1 << level);
183 }
184
185 static void intelTexSubImage1D( GLcontext *ctx,
186 GLenum target,
187 GLint level,
188 GLint xoffset,
189 GLsizei width,
190 GLenum format, GLenum type,
191 const GLvoid *pixels,
192 const struct gl_pixelstore_attrib *packing,
193 struct gl_texture_object *texObj,
194 struct gl_texture_image *texImage )
195 {
196 driTextureObject * t = (driTextureObject *) texObj->DriverData;
197
198 assert(t);
199 intelFlush( ctx );
200 driSwapOutTextureObject( t );
201
202 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
203 format, type, pixels, packing, texObj,
204 texImage);
205 }
206
207
208 /* Handles 2D, CUBE, RECT:
209 */
210 static void intelTexImage2D( GLcontext *ctx, GLenum target, GLint level,
211 GLint internalFormat,
212 GLint width, GLint height, GLint border,
213 GLenum format, GLenum type, const GLvoid *pixels,
214 const struct gl_pixelstore_attrib *packing,
215 struct gl_texture_object *texObj,
216 struct gl_texture_image *texImage )
217 {
218 driTextureObject * t = (driTextureObject *) texObj->DriverData;
219 GLuint face;
220
221 /* which cube face or ordinary 2D image */
222 switch (target) {
223 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
224 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
225 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
226 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
227 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
228 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
229 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
230 ASSERT(face < 6);
231 break;
232 default:
233 face = 0;
234 }
235
236 assert(t);
237 intelFlush( ctx );
238 driSwapOutTextureObject( t );
239 texImage->IsClientData = GL_FALSE;
240
241 if (intelValidateClientStorage( INTEL_CONTEXT(ctx), target,
242 internalFormat,
243 width, height,
244 format, type, pixels,
245 packing, texObj, texImage)) {
246 if (INTEL_DEBUG & DEBUG_TEXTURE)
247 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
248 }
249 else {
250 _mesa_store_teximage2d( ctx, target, level, internalFormat,
251 width, height, border, format, type,
252 pixels, packing, texObj, texImage );
253
254 t->dirty_images[face] |= (1 << level);
255 }
256 }
257
258 static void intelTexSubImage2D( GLcontext *ctx,
259 GLenum target,
260 GLint level,
261 GLint xoffset, GLint yoffset,
262 GLsizei width, GLsizei height,
263 GLenum format, GLenum type,
264 const GLvoid *pixels,
265 const struct gl_pixelstore_attrib *packing,
266 struct gl_texture_object *texObj,
267 struct gl_texture_image *texImage )
268 {
269 driTextureObject * t = (driTextureObject *) texObj->DriverData;
270 GLuint face;
271
272 /* which cube face or ordinary 2D image */
273 switch (target) {
274 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
275 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
276 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
277 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
278 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
279 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
280 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
281 ASSERT(face < 6);
282 break;
283 default:
284 face = 0;
285 }
286
287 if (texImage->IsClientData &&
288 (char *)pixels == (char *)texImage->Data +
289 ((xoffset + yoffset * texImage->RowStride) *
290 texImage->TexFormat->TexelBytes)) {
291
292 /* Notification only - no upload required */
293 }
294 else {
295 assert( t ); /* this _should_ be true */
296 intelFlush( ctx );
297 driSwapOutTextureObject( t );
298
299 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
300 height, format, type, pixels, packing, texObj,
301 texImage);
302
303 t->dirty_images[face] |= (1 << level);
304 }
305 }
306
307
308
309 static void intelTexImage3D( GLcontext *ctx, GLenum target, GLint level,
310 GLint internalFormat,
311 GLint width, GLint height, GLint depth,
312 GLint border,
313 GLenum format, GLenum type, const GLvoid *pixels,
314 const struct gl_pixelstore_attrib *packing,
315 struct gl_texture_object *texObj,
316 struct gl_texture_image *texImage )
317 {
318 driTextureObject * t = (driTextureObject *) texObj->DriverData;
319
320 assert(t);
321 driSwapOutTextureObject( t );
322 texImage->IsClientData = GL_FALSE;
323
324 _mesa_store_teximage3d(ctx, target, level, internalFormat,
325 width, height, depth, border,
326 format, type, pixels,
327 &ctx->Unpack, texObj, texImage);
328
329 t->dirty_images[0] |= (1 << level);
330 }
331
332
333 static void
334 intelTexSubImage3D( GLcontext *ctx, GLenum target, GLint level,
335 GLint xoffset, GLint yoffset, GLint zoffset,
336 GLsizei width, GLsizei height, GLsizei depth,
337 GLenum format, GLenum type,
338 const GLvoid *pixels,
339 const struct gl_pixelstore_attrib *packing,
340 struct gl_texture_object *texObj,
341 struct gl_texture_image *texImage )
342 {
343 driTextureObject * t = (driTextureObject *) texObj->DriverData;
344
345 assert( t ); /* this _should_ be true */
346 driSwapOutTextureObject( t );
347
348 _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
349 width, height, depth,
350 format, type, pixels, packing, texObj, texImage);
351
352 t->dirty_images[0] |= (1 << level);
353 }
354
355
356
357
358 static void intelDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
359 {
360 driTextureObject * t = (driTextureObject *) tObj->DriverData;
361
362 if ( t != NULL ) {
363 intelFlush( ctx );
364 driDestroyTextureObject( t );
365 }
366
367 /* Free mipmap images and the texture object itself */
368 _mesa_delete_texture_object(ctx, tObj);
369 }
370
371
372 static const struct gl_texture_format *
373 intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
374 GLenum format, GLenum type )
375 {
376 intelContextPtr intel = INTEL_CONTEXT( ctx );
377 const GLboolean do32bpt = ( intel->intelScreen->cpp == 4 &&
378 intel->intelScreen->textureSize > 4*1024*1024);
379
380 switch ( internalFormat ) {
381 case 4:
382 case GL_RGBA:
383 case GL_COMPRESSED_RGBA:
384 if ( format == GL_BGRA ) {
385 if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
386 return &_mesa_texformat_argb8888;
387 }
388 else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
389 return &_mesa_texformat_argb4444;
390 }
391 else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
392 return &_mesa_texformat_argb1555;
393 }
394 }
395 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
396
397 case 3:
398 case GL_RGB:
399 case GL_COMPRESSED_RGB:
400 if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
401 return &_mesa_texformat_rgb565;
402 }
403 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
404
405 case GL_RGBA8:
406 case GL_RGB10_A2:
407 case GL_RGBA12:
408 case GL_RGBA16:
409 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
410
411 case GL_RGBA4:
412 case GL_RGBA2:
413 return &_mesa_texformat_argb4444;
414
415 case GL_RGB5_A1:
416 return &_mesa_texformat_argb1555;
417
418 case GL_RGB8:
419 case GL_RGB10:
420 case GL_RGB12:
421 case GL_RGB16:
422 return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
423
424 case GL_RGB5:
425 case GL_RGB4:
426 case GL_R3_G3_B2:
427 return &_mesa_texformat_rgb565;
428
429 case GL_ALPHA:
430 case GL_ALPHA4:
431 case GL_ALPHA8:
432 case GL_ALPHA12:
433 case GL_ALPHA16:
434 case GL_COMPRESSED_ALPHA:
435 /* if (1 || intel->intelScreen->deviceID == PCI_CHIP_I915_G) */
436 return &_mesa_texformat_a8;
437 /* else */
438 /* return &_mesa_texformat_al88; */
439
440 case 1:
441 case GL_LUMINANCE:
442 case GL_LUMINANCE4:
443 case GL_LUMINANCE8:
444 case GL_LUMINANCE12:
445 case GL_LUMINANCE16:
446 case GL_COMPRESSED_LUMINANCE:
447 return &_mesa_texformat_l8;
448
449 case 2:
450 case GL_LUMINANCE_ALPHA:
451 case GL_LUMINANCE4_ALPHA4:
452 case GL_LUMINANCE6_ALPHA2:
453 case GL_LUMINANCE8_ALPHA8:
454 case GL_LUMINANCE12_ALPHA4:
455 case GL_LUMINANCE12_ALPHA12:
456 case GL_LUMINANCE16_ALPHA16:
457 case GL_COMPRESSED_LUMINANCE_ALPHA:
458 return &_mesa_texformat_al88;
459
460 case GL_INTENSITY:
461 case GL_INTENSITY4:
462 case GL_INTENSITY8:
463 case GL_INTENSITY12:
464 case GL_INTENSITY16:
465 case GL_COMPRESSED_INTENSITY:
466 return &_mesa_texformat_i8;
467
468 case GL_YCBCR_MESA:
469 if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
470 type == GL_UNSIGNED_BYTE)
471 return &_mesa_texformat_ycbcr;
472 else
473 return &_mesa_texformat_ycbcr_rev;
474
475 default:
476 fprintf(stderr, "unexpected texture format in %s\n", __FUNCTION__);
477 return NULL;
478 }
479
480 return NULL; /* never get here */
481 }
482
483
484
485 void intelDestroyTexObj(intelContextPtr intel, intelTextureObjectPtr t)
486 {
487 unsigned i;
488
489 if ( intel == NULL )
490 return;
491
492 if ( t->age > intel->dirtyAge )
493 intel->dirtyAge = t->age;
494
495 for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) {
496 if ( t == intel->CurrentTexObj[ i ] )
497 intel->CurrentTexObj[ i ] = NULL;
498 }
499 }
500
501
502
503 /* Upload an image from mesa's internal copy. Image may be 1D, 2D or
504 * 3D. Cubemaps are expanded elsewhere.
505 */
506 static void intelUploadTexImage( intelContextPtr intel,
507 intelTextureObjectPtr t,
508 const struct gl_texture_image *image,
509 const GLuint offset )
510 {
511
512 if (!image || !image->Data)
513 return;
514
515 if (image->Depth == 1 && image->IsClientData) {
516 if (INTEL_DEBUG & DEBUG_TEXTURE)
517 fprintf(stderr, "Blit uploading\n");
518
519 /* Do it with a blit.
520 */
521 intelEmitCopyBlitLocked( intel,
522 image->TexFormat->TexelBytes,
523 image->RowStride, /* ? */
524 intelGetMemoryOffsetMESA( NULL, 0, image->Data ),
525 t->Pitch / image->TexFormat->TexelBytes,
526 intelGetMemoryOffsetMESA( NULL, 0, t->BufAddr + offset ),
527 0, 0,
528 0, 0,
529 image->Width,
530 image->Height);
531 }
532 else {
533 GLuint row_len = image->Width * image->TexFormat->TexelBytes;
534 GLubyte *dst = (GLubyte *)(t->BufAddr + offset);
535 GLubyte *src = (GLubyte *)image->Data;
536 GLuint d, j;
537
538 if (INTEL_DEBUG & DEBUG_TEXTURE)
539 fprintf(stderr,
540 "Upload image %dx%dx%d offset %xm row_len %x "
541 "pitch %x depth_pitch %x\n",
542 image->Width, image->Height, image->Depth, offset,
543 row_len, t->Pitch, t->depth_pitch);
544
545 if (row_len == t->Pitch) {
546 for (d = 0; d < image->Depth; d++) {
547 memcpy( dst, src, t->Pitch * image->Height );
548 dst += t->depth_pitch;
549 src += row_len * image->Height;
550 }
551 }
552 else {
553 for (d = 0 ; d < image->Depth ; d++) {
554 for (j = 0 ; j < image->Height ; j++) {
555 __memcpy(dst, src, row_len );
556 src += row_len;
557 dst += t->Pitch;
558 }
559
560 dst += t->depth_pitch - (t->Pitch * image->Height);
561 }
562 }
563 }
564 }
565
566
567
568 int intelUploadTexImages( intelContextPtr intel,
569 intelTextureObjectPtr t,
570 GLuint face)
571 {
572 const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
573 const struct gl_texture_image *firstImage = t->image[face][t->base.firstLevel].image;
574 int pitch = firstImage->RowStride * firstImage->TexFormat->TexelBytes;
575
576 /* Can we texture out of the existing client data? */
577 if ( numLevels == 1 &&
578 firstImage->IsClientData &&
579 (pitch & 3) == 0) {
580
581 if (INTEL_DEBUG & DEBUG_TEXTURE)
582 fprintf(stderr, "AGP texturing from client memory\n");
583
584 t->TextureOffset = intelAgpOffsetFromVirtual( intel, firstImage->Data );
585 t->BufAddr = 0;
586 t->dirty = ~0;
587 return GL_TRUE;
588 }
589 else {
590 if (INTEL_DEBUG & DEBUG_TEXTURE)
591 fprintf(stderr, "Uploading client data to agp\n");
592
593 INTEL_FIREVERTICES( intel );
594 LOCK_HARDWARE( intel );
595
596 if ( t->base.memBlock == NULL ) {
597 int heap;
598
599 heap = driAllocateTexture( intel->texture_heaps, intel->nr_heaps,
600 (driTextureObject *) t );
601 if ( heap == -1 ) {
602 UNLOCK_HARDWARE( intel );
603 return GL_FALSE;
604 }
605
606 /* Set the base offset of the texture image */
607 t->BufAddr = intel->intelScreen->tex.map + t->base.memBlock->ofs;
608 t->TextureOffset = intel->intelScreen->textureOffset + t->base.memBlock->ofs;
609 t->dirty = ~0;
610 }
611
612
613 /* Let the world know we've used this memory recently.
614 */
615 driUpdateTextureLRU( (driTextureObject *) t );
616
617
618 /* Upload any images that are new */
619 if (t->base.dirty_images[face]) {
620 int i;
621
622 intelWaitForIdle( intel );
623
624 for (i = 0 ; i < numLevels ; i++) {
625 int level = i + t->base.firstLevel;
626
627 if (t->base.dirty_images[face] & (1<<level)) {
628
629 const struct gl_texture_image *image = t->image[face][i].image;
630 GLuint offset = t->image[face][i].offset;
631
632 if (INTEL_DEBUG & DEBUG_TEXTURE)
633 fprintf(stderr, "upload level %d, offset %x\n",
634 level, offset);
635
636 intelUploadTexImage( intel, t, image, offset );
637 }
638 }
639 t->base.dirty_images[face] = 0;
640 intel->perf_boxes |= I830_BOX_TEXTURE_LOAD;
641 }
642
643 UNLOCK_HARDWARE( intel );
644 return GL_TRUE;
645 }
646 }
647
648 /**
649 * Allocate a new texture object.
650 * Called via ctx->Driver.NewTextureObject.
651 * Note: this function will be called during context creation to
652 * allocate the default texture objects.
653 * Note: we could use containment here to 'derive' the driver-specific
654 * texture object from the core mesa gl_texture_object. Not done at this time.
655 */
656 static struct gl_texture_object *
657 intelNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
658 {
659 struct gl_texture_object *obj = _mesa_new_texture_object(ctx, name, target);
660 INTEL_CONTEXT(ctx)->vtbl.alloc_tex_obj( obj );
661 return obj;
662 }
663
664
665 void intelInitTextureFuncs( struct dd_function_table *functions )
666 {
667 functions->NewTextureObject = intelNewTextureObject;
668 functions->ChooseTextureFormat = intelChooseTextureFormat;
669 functions->TexImage1D = intelTexImage1D;
670 functions->TexImage2D = intelTexImage2D;
671 functions->TexImage3D = intelTexImage3D;
672 functions->TexSubImage1D = intelTexSubImage1D;
673 functions->TexSubImage2D = intelTexSubImage2D;
674 functions->TexSubImage3D = intelTexSubImage3D;
675 functions->CopyTexImage1D = _swrast_copy_teximage1d;
676 functions->CopyTexImage2D = _swrast_copy_teximage2d;
677 functions->CopyTexSubImage1D = _swrast_copy_texsubimage1d;
678 functions->CopyTexSubImage2D = _swrast_copy_texsubimage2d;
679 functions->CopyTexSubImage3D = _swrast_copy_texsubimage3d;
680 functions->DeleteTexture = intelDeleteTexture;
681 functions->UpdateTexturePalette = NULL;
682 functions->IsTextureResident = driIsTextureResident;
683 functions->TestProxyTexImage = _mesa_test_proxy_teximage;
684 functions->DeleteTexture = intelDeleteTexture;
685 }