1 /**************************************************************************
3 Copyright 2001 2d3d Inc., Delray Beach, FL
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 /* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_tex.c,v 1.5 2003/05/07 21:56:31 dawes Exp $ */
32 * Jeff Hartmann <jhartmann@2d3d.com>
34 * Heavily based on the I810 driver, which was written by:
35 * Keith Whitwell <keithw@tungstengraphics.com>
41 #include "simple_list.h"
45 #include "texformat.h"
48 #include "swrast/swrast.h"
52 #include "i830_screen.h"
54 #include "i830_context.h"
56 #include "i830_state.h"
57 #include "i830_ioctl.h"
60 * Compute the 'S2.4' lod bias factor from the floating point OpenGL bias.
62 static void i830ComputeLodBias( i830ContextPtr imesa
, unsigned unit
,
67 b
= (int) (bias
* 16.0);
69 else if (b
< -64) b
= -64;
70 imesa
->LodBias
[ unit
] = ((b
<< TM0S3_LOD_BIAS_SHIFT
) &
76 * Set the texture wrap modes.
78 * The i830M (and related graphics cores) do not support GL_CLAMP. The Intel
79 * drivers for "other operating systems" implement GL_CLAMP as
80 * GL_CLAMP_TO_EDGE, so the same is done here.
82 * \param t Texture object whose wrap modes are to be set
83 * \param swrap Wrap mode for the \a s texture coordinate
84 * \param twrap Wrap mode for the \a t texture coordinate
87 static void i830SetTexWrapping(i830TextureObjectPtr tex
,
88 GLenum swrap
, GLenum twrap
)
90 tex
->Setup
[I830_TEXREG_MCS
] &= ~(TEXCOORD_ADDR_U_MASK
|TEXCOORD_ADDR_V_MASK
);
94 tex
->Setup
[I830_TEXREG_MCS
] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP
);
97 case GL_CLAMP_TO_EDGE
:
98 tex
->Setup
[I830_TEXREG_MCS
] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP
);
100 case GL_CLAMP_TO_BORDER
:
101 tex
->Setup
[I830_TEXREG_MCS
] |=
102 TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP_BORDER
);
104 case GL_MIRRORED_REPEAT
:
105 tex
->Setup
[I830_TEXREG_MCS
] |=
106 TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_MIRROR
);
109 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
114 tex
->Setup
[I830_TEXREG_MCS
] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP
);
117 case GL_CLAMP_TO_EDGE
:
118 tex
->Setup
[I830_TEXREG_MCS
] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP
);
120 case GL_CLAMP_TO_BORDER
:
121 tex
->Setup
[I830_TEXREG_MCS
] |=
122 TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP_BORDER
);
124 case GL_MIRRORED_REPEAT
:
125 tex
->Setup
[I830_TEXREG_MCS
] |=
126 TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_MIRROR
);
129 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
133 static void i830SetTexMaxAnisotropy( i830TextureObjectPtr t
, GLfloat max
)
135 t
->max_anisotropy
= max
;
140 * Set the texture magnification and minification modes.
142 * \param t Texture whose filter modes are to be set
143 * \param minf Texture minification mode
144 * \param magf Texture magnification mode
145 * \param bias LOD bias for this texture unit.
148 static void i830SetTexFilter( i830TextureObjectPtr t
,
149 GLenum minf
, GLenum magf
)
151 int minFilt
= 0, mipFilt
= 0, magFilt
= 0;
153 if(I830_DEBUG
&DEBUG_DRI
)
154 fprintf(stderr
, "%s\n", __FUNCTION__
);
156 if ( t
->max_anisotropy
> 1.0 ) {
157 minFilt
= FILTER_ANISOTROPIC
;
158 magFilt
= FILTER_ANISOTROPIC
;
163 minFilt
= FILTER_NEAREST
;
164 mipFilt
= MIPFILTER_NONE
;
167 minFilt
= FILTER_LINEAR
;
168 mipFilt
= MIPFILTER_NONE
;
170 case GL_NEAREST_MIPMAP_NEAREST
:
171 minFilt
= FILTER_NEAREST
;
172 mipFilt
= MIPFILTER_NEAREST
;
174 case GL_LINEAR_MIPMAP_NEAREST
:
175 minFilt
= FILTER_LINEAR
;
176 mipFilt
= MIPFILTER_NEAREST
;
178 case GL_NEAREST_MIPMAP_LINEAR
:
179 minFilt
= FILTER_NEAREST
;
180 mipFilt
= MIPFILTER_LINEAR
;
182 case GL_LINEAR_MIPMAP_LINEAR
:
183 minFilt
= FILTER_LINEAR
;
184 mipFilt
= MIPFILTER_LINEAR
;
187 _mesa_problem(NULL
, "%s: Unsupported min. filter %d", __FUNCTION__
,
194 magFilt
= FILTER_NEAREST
;
197 magFilt
= FILTER_LINEAR
;
200 _mesa_problem(NULL
, "%s: Unsupported mag. filter %d", __FUNCTION__
,
206 t
->Setup
[I830_TEXREG_TM0S3
] &= ~TM0S3_MIN_FILTER_MASK
;
207 t
->Setup
[I830_TEXREG_TM0S3
] &= ~TM0S3_MIP_FILTER_MASK
;
208 t
->Setup
[I830_TEXREG_TM0S3
] &= ~TM0S3_MAG_FILTER_MASK
;
209 t
->Setup
[I830_TEXREG_TM0S3
] |= ((minFilt
<< TM0S3_MIN_FILTER_SHIFT
) |
210 (mipFilt
<< TM0S3_MIP_FILTER_SHIFT
) |
211 (magFilt
<< TM0S3_MAG_FILTER_SHIFT
));
214 static void i830SetTexBorderColor(i830TextureObjectPtr t
, GLubyte color
[4])
216 if(I830_DEBUG
&DEBUG_DRI
)
217 fprintf(stderr
, "%s\n", __FUNCTION__
);
219 t
->Setup
[I830_TEXREG_TM0S4
] =
220 I830PACKCOLOR8888(color
[0],color
[1],color
[2],color
[3]);
225 * Allocate space for and load the mesa images into the texture memory block.
226 * This will happen before drawing with a new texture, or drawing with a
227 * texture after it was swapped out or teximaged again.
230 static i830TextureObjectPtr
i830AllocTexObj( struct gl_texture_object
*texObj
)
232 i830TextureObjectPtr t
;
234 t
= CALLOC_STRUCT( i830_texture_object_t
);
235 texObj
->DriverData
= t
;
237 /* Initialize non-image-dependent parts of the state:
239 t
->base
.tObj
= texObj
;
241 t
->Setup
[I830_TEXREG_TM0LI
] = STATE3D_LOAD_STATE_IMMEDIATE_2
;
242 t
->Setup
[I830_TEXREG_TM0S0
] = TM0S0_USE_FENCE
;
243 t
->Setup
[I830_TEXREG_TM0S1
] = 0;
244 t
->Setup
[I830_TEXREG_TM0S2
] = 0;
245 t
->Setup
[I830_TEXREG_TM0S3
] = 0;
247 t
->Setup
[I830_TEXREG_NOP0
] = 0;
248 t
->Setup
[I830_TEXREG_NOP1
] = 0;
249 t
->Setup
[I830_TEXREG_NOP2
] = 0;
251 t
->Setup
[I830_TEXREG_MCS
] = (STATE3D_MAP_COORD_SET_CMD
|
253 ENABLE_TEXCOORD_PARAMS
|
254 TEXCOORDS_ARE_NORMAL
|
255 TEXCOORDTYPE_CARTESIAN
|
257 TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP
) |
259 TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP
));
261 make_empty_list( & t
->base
);
263 i830SetTexWrapping( t
, texObj
->WrapS
, texObj
->WrapT
);
264 i830SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
265 i830SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
266 i830SetTexBorderColor( t
, texObj
->_BorderChan
);
273 static void i830TexParameter( GLcontext
*ctx
, GLenum target
,
274 struct gl_texture_object
*tObj
,
275 GLenum pname
, const GLfloat
*params
)
277 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
278 i830TextureObjectPtr t
= (i830TextureObjectPtr
) tObj
->DriverData
;
279 GLuint unit
= ctx
->Texture
.CurrentUnit
;
284 if ( target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_RECTANGLE_NV
)
287 /* Can't do the update now as we don't know whether to flush
288 * vertices or not. Setting imesa->NewGLState means that
289 * i830UpdateTextureState() will be called before any triangles are
290 * rendered. If a statechange has occurred, it will be detected at
291 * that point, and buffered vertices flushed.
294 case GL_TEXTURE_MIN_FILTER
:
295 case GL_TEXTURE_MAG_FILTER
:
296 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
297 i830SetTexMaxAnisotropy( t
, tObj
->MaxAnisotropy
);
298 i830SetTexFilter( t
, tObj
->MinFilter
, tObj
->MagFilter
);
301 case GL_TEXTURE_WRAP_S
:
302 case GL_TEXTURE_WRAP_T
:
303 i830SetTexWrapping( t
, tObj
->WrapS
, tObj
->WrapT
);
306 case GL_TEXTURE_BORDER_COLOR
:
307 i830SetTexBorderColor( t
, tObj
->_BorderChan
);
310 case GL_TEXTURE_BASE_LEVEL
:
311 case GL_TEXTURE_MAX_LEVEL
:
312 case GL_TEXTURE_MIN_LOD
:
313 case GL_TEXTURE_MAX_LOD
:
314 /* The i830 and its successors can do a lot of this without
315 * reloading the textures. A project for someone?
317 I830_FIREVERTICES( I830_CONTEXT(ctx
) );
318 driSwapOutTextureObject( (driTextureObject
*) t
);
325 if (t
== imesa
->CurrentTexObj
[unit
]) {
326 I830_STATECHANGE( imesa
, I830_UPLOAD_TEX0
);
331 static void i830TexEnv( GLcontext
*ctx
, GLenum target
,
332 GLenum pname
, const GLfloat
*param
)
334 i830ContextPtr imesa
= I830_CONTEXT( ctx
);
335 GLuint unit
= ctx
->Texture
.CurrentUnit
;
337 /* Only one env color. Need a fallback if env colors are different
338 * and texture setup references env color in both units.
341 case GL_TEXTURE_ENV_COLOR
:
342 case GL_TEXTURE_ENV_MODE
:
343 case GL_COMBINE_RGB_EXT
:
344 case GL_COMBINE_ALPHA_EXT
:
345 case GL_SOURCE0_RGB_EXT
:
346 case GL_SOURCE1_RGB_EXT
:
347 case GL_SOURCE2_RGB_EXT
:
348 case GL_SOURCE0_ALPHA_EXT
:
349 case GL_SOURCE1_ALPHA_EXT
:
350 case GL_SOURCE2_ALPHA_EXT
:
351 case GL_OPERAND0_RGB_EXT
:
352 case GL_OPERAND1_RGB_EXT
:
353 case GL_OPERAND2_RGB_EXT
:
354 case GL_OPERAND0_ALPHA_EXT
:
355 case GL_OPERAND1_ALPHA_EXT
:
356 case GL_OPERAND2_ALPHA_EXT
:
357 case GL_RGB_SCALE_EXT
:
359 imesa
->TexEnvImageFmt
[unit
] = 0; /* force recalc of env state */
362 case GL_TEXTURE_LOD_BIAS_EXT
:
363 i830ComputeLodBias( imesa
, unit
, *param
);
364 I830_STATECHANGE( imesa
, I830_UPLOAD_TEX_N(unit
) );
372 static void i830TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
373 GLint internalFormat
,
374 GLint width
, GLint height
, GLint border
,
375 GLenum format
, GLenum type
, const GLvoid
*pixels
,
376 const struct gl_pixelstore_attrib
*packing
,
377 struct gl_texture_object
*texObj
,
378 struct gl_texture_image
*texImage
)
380 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
382 I830_FIREVERTICES( I830_CONTEXT(ctx
) );
383 driSwapOutTextureObject( t
);
386 t
= (driTextureObject
*) i830AllocTexObj( texObj
);
388 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
393 _mesa_store_teximage2d( ctx
, target
, level
, internalFormat
,
394 width
, height
, border
, format
, type
,
395 pixels
, packing
, texObj
, texImage
);
398 static void i830TexSubImage2D( GLcontext
*ctx
,
401 GLint xoffset
, GLint yoffset
,
402 GLsizei width
, GLsizei height
,
403 GLenum format
, GLenum type
,
404 const GLvoid
*pixels
,
405 const struct gl_pixelstore_attrib
*packing
,
406 struct gl_texture_object
*texObj
,
407 struct gl_texture_image
*texImage
)
409 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
411 I830_FIREVERTICES( I830_CONTEXT(ctx
) );
412 driSwapOutTextureObject( t
);
414 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
415 height
, format
, type
, pixels
, packing
, texObj
,
422 static void i830CompressedTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
423 GLint internalFormat
,
424 GLint width
, GLint height
, GLint border
,
425 GLsizei imageSize
, const GLvoid
*data
,
426 struct gl_texture_object
*texObj
,
427 struct gl_texture_image
*texImage
)
429 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
432 /* which cube face or ordinary 2D image */
434 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
435 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
436 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
437 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
438 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
439 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
440 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
448 driSwapOutTextureObject( t
);
451 t
= (driTextureObject
*) i830AllocTexObj( texObj
);
453 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
458 texImage
->IsClientData
= GL_FALSE
;
460 if (I830_DEBUG
& DEBUG_TEXTURE
)
461 fprintf(stderr
, "%s: Using normal storage\n", __FUNCTION__
);
463 _mesa_store_compressed_teximage2d(ctx
, target
, level
, internalFormat
, width
,
464 height
, border
, imageSize
, data
, texObj
, texImage
);
466 t
->dirty_images
[face
] |= (1 << level
);
470 static void i830CompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
471 GLint xoffset
, GLint yoffset
,
472 GLsizei width
, GLsizei height
,
474 GLsizei imageSize
, const GLvoid
*data
,
475 struct gl_texture_object
*texObj
,
476 struct gl_texture_image
*texImage
)
478 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
482 /* which cube face or ordinary 2D image */
484 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
485 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
486 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
487 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
488 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
489 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
490 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
497 assert( t
); /* this _should_ be true */
499 driSwapOutTextureObject( t
);
502 t
= (driTextureObject
*) i830AllocTexObj( texObj
);
504 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexSubImage2D");
509 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
510 height
, format
, imageSize
, data
, texObj
, texImage
);
512 t
->dirty_images
[face
] |= (1 << level
);
516 static void i830BindTexture( GLcontext
*ctx
, GLenum target
,
517 struct gl_texture_object
*tObj
)
519 assert( (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_RECTANGLE_NV
) ||
520 (tObj
->DriverData
!= NULL
) );
524 static void i830DeleteTexture( GLcontext
*ctx
, struct gl_texture_object
*tObj
)
526 driTextureObject
* t
= (driTextureObject
*) tObj
->DriverData
;
528 i830ContextPtr imesa
= I830_CONTEXT( ctx
);
531 I830_FIREVERTICES( imesa
);
534 driDestroyTextureObject( t
);
536 /* Free mipmap images and the texture object itself */
537 _mesa_delete_texture_object(ctx
, tObj
);
541 static const struct gl_texture_format
*
542 i830ChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
543 GLenum format
, GLenum type
)
545 i830ContextPtr imesa
= I830_CONTEXT( ctx
);
546 const GLboolean do32bpt
= ( imesa
->i830Screen
->cpp
== 4 &&
547 imesa
->i830Screen
->textureSize
> 4*1024*1024);
549 switch ( internalFormat
) {
552 case GL_COMPRESSED_RGBA
:
553 if ( format
== GL_BGRA
) {
554 if ( type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
555 return &_mesa_texformat_argb8888
;
557 else if ( type
== GL_UNSIGNED_SHORT_4_4_4_4_REV
) {
558 return &_mesa_texformat_argb4444
;
560 else if ( type
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) {
561 return &_mesa_texformat_argb1555
;
564 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
568 case GL_COMPRESSED_RGB
:
569 if ( format
== GL_RGB
&& type
== GL_UNSIGNED_SHORT_5_6_5
) {
570 return &_mesa_texformat_rgb565
;
572 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
578 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_argb4444
;
582 return &_mesa_texformat_argb4444
;
585 return &_mesa_texformat_argb1555
;
591 return do32bpt
? &_mesa_texformat_argb8888
: &_mesa_texformat_rgb565
;
596 return &_mesa_texformat_rgb565
;
603 case GL_COMPRESSED_ALPHA
:
604 return &_mesa_texformat_al88
;
612 case GL_COMPRESSED_LUMINANCE
:
613 return &_mesa_texformat_l8
;
616 case GL_LUMINANCE_ALPHA
:
617 case GL_LUMINANCE4_ALPHA4
:
618 case GL_LUMINANCE6_ALPHA2
:
619 case GL_LUMINANCE8_ALPHA8
:
620 case GL_LUMINANCE12_ALPHA4
:
621 case GL_LUMINANCE12_ALPHA12
:
622 case GL_LUMINANCE16_ALPHA16
:
623 case GL_COMPRESSED_LUMINANCE_ALPHA
:
624 return &_mesa_texformat_al88
;
631 case GL_COMPRESSED_INTENSITY
:
632 return &_mesa_texformat_i8
;
635 if (type
== GL_UNSIGNED_SHORT_8_8_MESA
||
636 type
== GL_UNSIGNED_BYTE
)
637 return &_mesa_texformat_ycbcr
;
639 return &_mesa_texformat_ycbcr_rev
;
641 case GL_COMPRESSED_RGB_FXT1_3DFX
:
642 return &_mesa_texformat_rgb_fxt1
;
643 case GL_COMPRESSED_RGBA_FXT1_3DFX
:
644 return &_mesa_texformat_rgba_fxt1
;
648 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
649 return &_mesa_texformat_rgb_dxt1
;
651 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
652 return &_mesa_texformat_rgba_dxt1
;
656 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
657 return &_mesa_texformat_rgba_dxt3
;
659 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
660 return &_mesa_texformat_rgba_dxt5
;
663 fprintf(stderr
, "unexpected texture format in %s\n", __FUNCTION__
);
667 return NULL
; /* never get here */
671 * Allocate a new texture object.
672 * Called via ctx->Driver.NewTextureObject.
673 * Note: this function will be called during context creation to
674 * allocate the default texture objects.
675 * Note: we could use containment here to 'derive' the driver-specific
676 * texture object from the core mesa gl_texture_object. Not done at this time.
678 static struct gl_texture_object
*
679 i830NewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
681 struct gl_texture_object
*obj
;
682 obj
= _mesa_new_texture_object(ctx
, name
, target
);
683 i830AllocTexObj( obj
);
687 void i830InitTextureFuncs( struct dd_function_table
*functions
)
689 functions
->NewTextureObject
= i830NewTextureObject
;
690 functions
->DeleteTexture
= i830DeleteTexture
;
691 functions
->ChooseTextureFormat
= i830ChooseTextureFormat
;
692 functions
->TexImage2D
= i830TexImage2D
;
693 functions
->TexSubImage2D
= i830TexSubImage2D
;
694 functions
->BindTexture
= i830BindTexture
;
695 functions
->TexParameter
= i830TexParameter
;
696 functions
->TexEnv
= i830TexEnv
;
697 functions
->IsTextureResident
= driIsTextureResident
;
698 functions
->CompressedTexImage2D
= i830CompressedTexImage2D
;
699 functions
->CompressedTexSubImage2D
= i830CompressedTexSubImage2D
;