259f35a34c3638c223821e72b675b7f5035135f1
[mesa.git] / src / mesa / drivers / dri / r200 / r200_tex.c
1 /*
2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
3
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29 /*
30 * Authors:
31 * Keith Whitwell <keith@tungstengraphics.com>
32 */
33
34 #include "main/glheader.h"
35 #include "main/imports.h"
36 #include "main/colormac.h"
37 #include "main/context.h"
38 #include "main/enums.h"
39 #include "main/image.h"
40 #include "main/simple_list.h"
41 #include "main/texformat.h"
42 #include "main/texstore.h"
43 #include "main/teximage.h"
44 #include "main/texobj.h"
45
46 #include "texmem.h"
47
48 #include "r200_context.h"
49 #include "r200_state.h"
50 #include "r200_ioctl.h"
51 #include "r200_swtcl.h"
52 #include "r200_tex.h"
53
54 #include "xmlpool.h"
55
56
57
58 /**
59 * Set the texture wrap modes.
60 *
61 * \param t Texture object whose wrap modes are to be set
62 * \param swrap Wrap mode for the \a s texture coordinate
63 * \param twrap Wrap mode for the \a t texture coordinate
64 */
65
66 static void r200SetTexWrap( r200TexObjPtr t, GLenum swrap, GLenum twrap, GLenum rwrap )
67 {
68 GLboolean is_clamp = GL_FALSE;
69 GLboolean is_clamp_to_border = GL_FALSE;
70
71 t->pp_txfilter &= ~(R200_CLAMP_S_MASK | R200_CLAMP_T_MASK | R200_BORDER_MODE_D3D);
72
73 switch ( swrap ) {
74 case GL_REPEAT:
75 t->pp_txfilter |= R200_CLAMP_S_WRAP;
76 break;
77 case GL_CLAMP:
78 t->pp_txfilter |= R200_CLAMP_S_CLAMP_GL;
79 is_clamp = GL_TRUE;
80 break;
81 case GL_CLAMP_TO_EDGE:
82 t->pp_txfilter |= R200_CLAMP_S_CLAMP_LAST;
83 break;
84 case GL_CLAMP_TO_BORDER:
85 t->pp_txfilter |= R200_CLAMP_S_CLAMP_GL;
86 is_clamp_to_border = GL_TRUE;
87 break;
88 case GL_MIRRORED_REPEAT:
89 t->pp_txfilter |= R200_CLAMP_S_MIRROR;
90 break;
91 case GL_MIRROR_CLAMP_EXT:
92 t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_GL;
93 is_clamp = GL_TRUE;
94 break;
95 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
96 t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_LAST;
97 break;
98 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
99 t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_GL;
100 is_clamp_to_border = GL_TRUE;
101 break;
102 default:
103 _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
104 }
105
106 if (t->base.tObj->Target != GL_TEXTURE_1D) {
107 switch ( twrap ) {
108 case GL_REPEAT:
109 t->pp_txfilter |= R200_CLAMP_T_WRAP;
110 break;
111 case GL_CLAMP:
112 t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL;
113 is_clamp = GL_TRUE;
114 break;
115 case GL_CLAMP_TO_EDGE:
116 t->pp_txfilter |= R200_CLAMP_T_CLAMP_LAST;
117 break;
118 case GL_CLAMP_TO_BORDER:
119 t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL;
120 is_clamp_to_border = GL_TRUE;
121 break;
122 case GL_MIRRORED_REPEAT:
123 t->pp_txfilter |= R200_CLAMP_T_MIRROR;
124 break;
125 case GL_MIRROR_CLAMP_EXT:
126 t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_GL;
127 is_clamp = GL_TRUE;
128 break;
129 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
130 t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_LAST;
131 break;
132 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
133 t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_GL;
134 is_clamp_to_border = GL_TRUE;
135 break;
136 default:
137 _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
138 }
139 }
140
141 t->pp_txformat_x &= ~R200_CLAMP_Q_MASK;
142
143 switch ( rwrap ) {
144 case GL_REPEAT:
145 t->pp_txformat_x |= R200_CLAMP_Q_WRAP;
146 break;
147 case GL_CLAMP:
148 t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_GL;
149 is_clamp = GL_TRUE;
150 break;
151 case GL_CLAMP_TO_EDGE:
152 t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_LAST;
153 break;
154 case GL_CLAMP_TO_BORDER:
155 t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_GL;
156 is_clamp_to_border = GL_TRUE;
157 break;
158 case GL_MIRRORED_REPEAT:
159 t->pp_txformat_x |= R200_CLAMP_Q_MIRROR;
160 break;
161 case GL_MIRROR_CLAMP_EXT:
162 t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_GL;
163 is_clamp = GL_TRUE;
164 break;
165 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
166 t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_LAST;
167 break;
168 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
169 t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_GL;
170 is_clamp_to_border = GL_TRUE;
171 break;
172 default:
173 _mesa_problem(NULL, "bad R wrap mode in %s", __FUNCTION__);
174 }
175
176 if ( is_clamp_to_border ) {
177 t->pp_txfilter |= R200_BORDER_MODE_D3D;
178 }
179
180 t->border_fallback = (is_clamp && is_clamp_to_border);
181 }
182
183 static void r200SetTexMaxAnisotropy( r200TexObjPtr t, GLfloat max )
184 {
185 t->pp_txfilter &= ~R200_MAX_ANISO_MASK;
186
187 if ( max <= 1.0 ) {
188 t->pp_txfilter |= R200_MAX_ANISO_1_TO_1;
189 } else if ( max <= 2.0 ) {
190 t->pp_txfilter |= R200_MAX_ANISO_2_TO_1;
191 } else if ( max <= 4.0 ) {
192 t->pp_txfilter |= R200_MAX_ANISO_4_TO_1;
193 } else if ( max <= 8.0 ) {
194 t->pp_txfilter |= R200_MAX_ANISO_8_TO_1;
195 } else {
196 t->pp_txfilter |= R200_MAX_ANISO_16_TO_1;
197 }
198 }
199
200 /**
201 * Set the texture magnification and minification modes.
202 *
203 * \param t Texture whose filter modes are to be set
204 * \param minf Texture minification mode
205 * \param magf Texture magnification mode
206 */
207
208 static void r200SetTexFilter( r200TexObjPtr t, GLenum minf, GLenum magf )
209 {
210 GLuint anisotropy = (t->pp_txfilter & R200_MAX_ANISO_MASK);
211
212 t->pp_txfilter &= ~(R200_MIN_FILTER_MASK | R200_MAG_FILTER_MASK);
213 t->pp_txformat_x &= ~R200_VOLUME_FILTER_MASK;
214
215 if ( anisotropy == R200_MAX_ANISO_1_TO_1 ) {
216 switch ( minf ) {
217 case GL_NEAREST:
218 t->pp_txfilter |= R200_MIN_FILTER_NEAREST;
219 break;
220 case GL_LINEAR:
221 t->pp_txfilter |= R200_MIN_FILTER_LINEAR;
222 break;
223 case GL_NEAREST_MIPMAP_NEAREST:
224 t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_NEAREST;
225 break;
226 case GL_NEAREST_MIPMAP_LINEAR:
227 t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_NEAREST;
228 break;
229 case GL_LINEAR_MIPMAP_NEAREST:
230 t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_LINEAR;
231 break;
232 case GL_LINEAR_MIPMAP_LINEAR:
233 t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_LINEAR;
234 break;
235 }
236 } else {
237 switch ( minf ) {
238 case GL_NEAREST:
239 t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST;
240 break;
241 case GL_LINEAR:
242 t->pp_txfilter |= R200_MIN_FILTER_ANISO_LINEAR;
243 break;
244 case GL_NEAREST_MIPMAP_NEAREST:
245 case GL_LINEAR_MIPMAP_NEAREST:
246 t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST;
247 break;
248 case GL_NEAREST_MIPMAP_LINEAR:
249 case GL_LINEAR_MIPMAP_LINEAR:
250 t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR;
251 break;
252 }
253 }
254
255 /* Note we don't have 3D mipmaps so only use the mag filter setting
256 * to set the 3D texture filter mode.
257 */
258 switch ( magf ) {
259 case GL_NEAREST:
260 t->pp_txfilter |= R200_MAG_FILTER_NEAREST;
261 t->pp_txformat_x |= R200_VOLUME_FILTER_NEAREST;
262 break;
263 case GL_LINEAR:
264 t->pp_txfilter |= R200_MAG_FILTER_LINEAR;
265 t->pp_txformat_x |= R200_VOLUME_FILTER_LINEAR;
266 break;
267 }
268 }
269
270 static void r200SetTexBorderColor( r200TexObjPtr t, const GLfloat color[4] )
271 {
272 GLubyte c[4];
273 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
274 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
275 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
276 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
277 t->pp_border_color = r200PackColor( 4, c[0], c[1], c[2], c[3] );
278 }
279
280
281 /**
282 * Allocate space for and load the mesa images into the texture memory block.
283 * This will happen before drawing with a new texture, or drawing with a
284 * texture after it was swapped out or teximaged again.
285 */
286
287 static r200TexObjPtr r200AllocTexObj( struct gl_texture_object *texObj )
288 {
289 r200TexObjPtr t;
290
291 t = CALLOC_STRUCT( r200_tex_obj );
292 texObj->DriverData = t;
293 if ( t != NULL ) {
294 if ( R200_DEBUG & DEBUG_TEXTURE ) {
295 fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, (void *)texObj,
296 (void *)t );
297 }
298
299 /* Initialize non-image-dependent parts of the state:
300 */
301 t->base.tObj = texObj;
302 t->border_fallback = GL_FALSE;
303
304 make_empty_list( & t->base );
305
306 r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR );
307 r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
308 r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
309 r200SetTexBorderColor( t, texObj->BorderColor );
310 }
311
312 return t;
313 }
314
315 /* try to find a format which will only need a memcopy */
316 static const struct gl_texture_format *
317 r200Choose8888TexFormat( GLenum srcFormat, GLenum srcType )
318 {
319 const GLuint ui = 1;
320 const GLubyte littleEndian = *((const GLubyte *) &ui);
321
322 if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
323 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
324 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
325 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian)) {
326 return &_mesa_texformat_rgba8888;
327 }
328 else if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
329 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
330 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
331 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian)) {
332 return &_mesa_texformat_rgba8888_rev;
333 }
334 else return _dri_texformat_argb8888;
335 }
336
337 static const struct gl_texture_format *
338 r200ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
339 GLenum format, GLenum type )
340 {
341 r200ContextPtr rmesa = R200_CONTEXT(ctx);
342 const GLboolean do32bpt =
343 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
344 const GLboolean force16bpt =
345 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
346 (void) format;
347
348 switch ( internalFormat ) {
349 case 4:
350 case GL_RGBA:
351 case GL_COMPRESSED_RGBA:
352 switch ( type ) {
353 case GL_UNSIGNED_INT_10_10_10_2:
354 case GL_UNSIGNED_INT_2_10_10_10_REV:
355 return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_argb1555;
356 case GL_UNSIGNED_SHORT_4_4_4_4:
357 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
358 return _dri_texformat_argb4444;
359 case GL_UNSIGNED_SHORT_5_5_5_1:
360 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
361 return _dri_texformat_argb1555;
362 default:
363 return do32bpt ?
364 r200Choose8888TexFormat(format, type) : _dri_texformat_argb4444;
365 }
366
367 case 3:
368 case GL_RGB:
369 case GL_COMPRESSED_RGB:
370 switch ( type ) {
371 case GL_UNSIGNED_SHORT_4_4_4_4:
372 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
373 return _dri_texformat_argb4444;
374 case GL_UNSIGNED_SHORT_5_5_5_1:
375 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
376 return _dri_texformat_argb1555;
377 case GL_UNSIGNED_SHORT_5_6_5:
378 case GL_UNSIGNED_SHORT_5_6_5_REV:
379 return _dri_texformat_rgb565;
380 default:
381 return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_rgb565;
382 }
383
384 case GL_RGBA8:
385 case GL_RGB10_A2:
386 case GL_RGBA12:
387 case GL_RGBA16:
388 return !force16bpt ?
389 r200Choose8888TexFormat(format, type) : _dri_texformat_argb4444;
390
391 case GL_RGBA4:
392 case GL_RGBA2:
393 return _dri_texformat_argb4444;
394
395 case GL_RGB5_A1:
396 return _dri_texformat_argb1555;
397
398 case GL_RGB8:
399 case GL_RGB10:
400 case GL_RGB12:
401 case GL_RGB16:
402 return !force16bpt ? _dri_texformat_argb8888 : _dri_texformat_rgb565;
403
404 case GL_RGB5:
405 case GL_RGB4:
406 case GL_R3_G3_B2:
407 return _dri_texformat_rgb565;
408
409 case GL_ALPHA:
410 case GL_ALPHA4:
411 case GL_ALPHA8:
412 case GL_ALPHA12:
413 case GL_ALPHA16:
414 case GL_COMPRESSED_ALPHA:
415 /* can't use a8 format since interpreting hw I8 as a8 would result
416 in wrong rgb values (same as alpha value instead of 0). */
417 return _dri_texformat_al88;
418
419 case 1:
420 case GL_LUMINANCE:
421 case GL_LUMINANCE4:
422 case GL_LUMINANCE8:
423 case GL_LUMINANCE12:
424 case GL_LUMINANCE16:
425 case GL_COMPRESSED_LUMINANCE:
426 return _dri_texformat_l8;
427
428 case 2:
429 case GL_LUMINANCE_ALPHA:
430 case GL_LUMINANCE4_ALPHA4:
431 case GL_LUMINANCE6_ALPHA2:
432 case GL_LUMINANCE8_ALPHA8:
433 case GL_LUMINANCE12_ALPHA4:
434 case GL_LUMINANCE12_ALPHA12:
435 case GL_LUMINANCE16_ALPHA16:
436 case GL_COMPRESSED_LUMINANCE_ALPHA:
437 return _dri_texformat_al88;
438
439 case GL_INTENSITY:
440 case GL_INTENSITY4:
441 case GL_INTENSITY8:
442 case GL_INTENSITY12:
443 case GL_INTENSITY16:
444 case GL_COMPRESSED_INTENSITY:
445 return _dri_texformat_i8;
446
447 case GL_YCBCR_MESA:
448 if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
449 type == GL_UNSIGNED_BYTE)
450 return &_mesa_texformat_ycbcr;
451 else
452 return &_mesa_texformat_ycbcr_rev;
453
454 case GL_RGB_S3TC:
455 case GL_RGB4_S3TC:
456 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
457 return &_mesa_texformat_rgb_dxt1;
458
459 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
460 return &_mesa_texformat_rgba_dxt1;
461
462 case GL_RGBA_S3TC:
463 case GL_RGBA4_S3TC:
464 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
465 return &_mesa_texformat_rgba_dxt3;
466
467 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
468 return &_mesa_texformat_rgba_dxt5;
469
470 default:
471 _mesa_problem(ctx,
472 "unexpected internalFormat 0x%x in r200ChooseTextureFormat",
473 (int) internalFormat);
474 return NULL;
475 }
476
477 return NULL; /* never get here */
478 }
479
480
481 static GLboolean
482 r200ValidateClientStorage( GLcontext *ctx, GLenum target,
483 GLint internalFormat,
484 GLint srcWidth, GLint srcHeight,
485 GLenum format, GLenum type, const void *pixels,
486 const struct gl_pixelstore_attrib *packing,
487 struct gl_texture_object *texObj,
488 struct gl_texture_image *texImage)
489
490 {
491 r200ContextPtr rmesa = R200_CONTEXT(ctx);
492
493 if ( R200_DEBUG & DEBUG_TEXTURE )
494 fprintf(stderr, "intformat %s format %s type %s\n",
495 _mesa_lookup_enum_by_nr( internalFormat ),
496 _mesa_lookup_enum_by_nr( format ),
497 _mesa_lookup_enum_by_nr( type ));
498
499 if (!ctx->Unpack.ClientStorage)
500 return 0;
501
502 if (ctx->_ImageTransferState ||
503 texImage->IsCompressed ||
504 texObj->GenerateMipmap)
505 return 0;
506
507
508 /* This list is incomplete, may be different on ppc???
509 */
510 switch ( internalFormat ) {
511 case GL_RGBA:
512 if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
513 texImage->TexFormat = _dri_texformat_argb8888;
514 }
515 else
516 return 0;
517 break;
518
519 case GL_RGB:
520 if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
521 texImage->TexFormat = _dri_texformat_rgb565;
522 }
523 else
524 return 0;
525 break;
526
527 case GL_YCBCR_MESA:
528 if ( format == GL_YCBCR_MESA &&
529 type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
530 texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
531 }
532 else if ( format == GL_YCBCR_MESA &&
533 (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
534 type == GL_UNSIGNED_BYTE)) {
535 texImage->TexFormat = &_mesa_texformat_ycbcr;
536 }
537 else
538 return 0;
539 break;
540
541 default:
542 return 0;
543 }
544
545 /* Could deal with these packing issues, but currently don't:
546 */
547 if (packing->SkipPixels ||
548 packing->SkipRows ||
549 packing->SwapBytes ||
550 packing->LsbFirst) {
551 return 0;
552 }
553
554 {
555 GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
556 format, type);
557
558
559 if ( R200_DEBUG & DEBUG_TEXTURE )
560 fprintf(stderr, "%s: srcRowStride %d/%x\n",
561 __FUNCTION__, srcRowStride, srcRowStride);
562
563 /* Could check this later in upload, pitch restrictions could be
564 * relaxed, but would need to store the image pitch somewhere,
565 * as packing details might change before image is uploaded:
566 */
567 if (!r200IsGartMemory( rmesa, pixels, srcHeight * srcRowStride ) ||
568 (srcRowStride & 63))
569 return 0;
570
571
572 /* Have validated that _mesa_transfer_teximage would be a straight
573 * memcpy at this point. NOTE: future calls to TexSubImage will
574 * overwrite the client data. This is explicitly mentioned in the
575 * extension spec.
576 */
577 texImage->Data = (void *)pixels;
578 texImage->IsClientData = GL_TRUE;
579 texImage->RowStride = srcRowStride / texImage->TexFormat->TexelBytes;
580
581 return 1;
582 }
583 }
584
585
586 static void r200TexImage1D( GLcontext *ctx, GLenum target, GLint level,
587 GLint internalFormat,
588 GLint width, GLint border,
589 GLenum format, GLenum type, const GLvoid *pixels,
590 const struct gl_pixelstore_attrib *packing,
591 struct gl_texture_object *texObj,
592 struct gl_texture_image *texImage )
593 {
594 driTextureObject * t = (driTextureObject *) texObj->DriverData;
595
596 if ( t ) {
597 driSwapOutTextureObject( t );
598 }
599 else {
600 t = (driTextureObject *) r200AllocTexObj( texObj );
601 if (!t) {
602 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
603 return;
604 }
605 }
606
607 /* Note, this will call ChooseTextureFormat */
608 _mesa_store_teximage1d(ctx, target, level, internalFormat,
609 width, border, format, type, pixels,
610 &ctx->Unpack, texObj, texImage);
611
612 t->dirty_images[0] |= (1 << level);
613 }
614
615
616 static void r200TexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
617 GLint xoffset,
618 GLsizei width,
619 GLenum format, GLenum type,
620 const GLvoid *pixels,
621 const struct gl_pixelstore_attrib *packing,
622 struct gl_texture_object *texObj,
623 struct gl_texture_image *texImage )
624 {
625 driTextureObject * t = (driTextureObject *) texObj->DriverData;
626
627 assert( t ); /* this _should_ be true */
628 if ( t ) {
629 driSwapOutTextureObject( t );
630 }
631 else {
632 t = (driTextureObject *) r200AllocTexObj( texObj );
633 if (!t) {
634 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
635 return;
636 }
637 }
638
639 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
640 format, type, pixels, packing, texObj,
641 texImage);
642
643 t->dirty_images[0] |= (1 << level);
644 }
645
646
647 static void r200TexImage2D( GLcontext *ctx, GLenum target, GLint level,
648 GLint internalFormat,
649 GLint width, GLint height, GLint border,
650 GLenum format, GLenum type, const GLvoid *pixels,
651 const struct gl_pixelstore_attrib *packing,
652 struct gl_texture_object *texObj,
653 struct gl_texture_image *texImage )
654 {
655 driTextureObject * t = (driTextureObject *) texObj->DriverData;
656 GLuint face;
657
658 /* which cube face or ordinary 2D image */
659 switch (target) {
660 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
661 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
662 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
663 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
664 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
665 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
666 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
667 ASSERT(face < 6);
668 break;
669 default:
670 face = 0;
671 }
672
673 if ( t != NULL ) {
674 driSwapOutTextureObject( t );
675 }
676 else {
677 t = (driTextureObject *) r200AllocTexObj( texObj );
678 if (!t) {
679 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
680 return;
681 }
682 }
683
684 texImage->IsClientData = GL_FALSE;
685
686 if (r200ValidateClientStorage( ctx, target,
687 internalFormat,
688 width, height,
689 format, type, pixels,
690 packing, texObj, texImage)) {
691 if (R200_DEBUG & DEBUG_TEXTURE)
692 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
693 }
694 else {
695 if (R200_DEBUG & DEBUG_TEXTURE)
696 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
697
698 /* Normal path: copy (to cached memory) and eventually upload
699 * via another copy to GART memory and then a blit... Could
700 * eliminate one copy by going straight to (permanent) GART.
701 *
702 * Note, this will call r200ChooseTextureFormat.
703 */
704 _mesa_store_teximage2d(ctx, target, level, internalFormat,
705 width, height, border, format, type, pixels,
706 &ctx->Unpack, texObj, texImage);
707
708 t->dirty_images[face] |= (1 << level);
709 }
710 }
711
712
713 static void r200TexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
714 GLint xoffset, GLint yoffset,
715 GLsizei width, GLsizei height,
716 GLenum format, GLenum type,
717 const GLvoid *pixels,
718 const struct gl_pixelstore_attrib *packing,
719 struct gl_texture_object *texObj,
720 struct gl_texture_image *texImage )
721 {
722 driTextureObject * t = (driTextureObject *) texObj->DriverData;
723 GLuint face;
724
725 /* which cube face or ordinary 2D image */
726 switch (target) {
727 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
728 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
729 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
730 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
731 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
732 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
733 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
734 ASSERT(face < 6);
735 break;
736 default:
737 face = 0;
738 }
739
740 assert( t ); /* this _should_ be true */
741 if ( t ) {
742 driSwapOutTextureObject( t );
743 }
744 else {
745 t = (driTextureObject *) r200AllocTexObj( texObj );
746 if (!t) {
747 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
748 return;
749 }
750 }
751
752 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
753 height, format, type, pixels, packing, texObj,
754 texImage);
755
756 t->dirty_images[face] |= (1 << level);
757 }
758
759
760 static void r200CompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
761 GLint internalFormat,
762 GLint width, GLint height, GLint border,
763 GLsizei imageSize, const GLvoid *data,
764 struct gl_texture_object *texObj,
765 struct gl_texture_image *texImage )
766 {
767 driTextureObject * t = (driTextureObject *) texObj->DriverData;
768 GLuint face;
769
770 /* which cube face or ordinary 2D image */
771 switch (target) {
772 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
773 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
774 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
775 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
776 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
777 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
778 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
779 ASSERT(face < 6);
780 break;
781 default:
782 face = 0;
783 }
784
785 if ( t != NULL ) {
786 driSwapOutTextureObject( t );
787 }
788 else {
789 t = (driTextureObject *) r200AllocTexObj( texObj );
790 if (!t) {
791 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
792 return;
793 }
794 }
795
796 texImage->IsClientData = GL_FALSE;
797 /* can't call this, different parameters. Would never evaluate to true anyway currently
798 if (r200ValidateClientStorage( ctx, target,
799 internalFormat,
800 width, height,
801 format, type, pixels,
802 packing, texObj, texImage)) {
803 if (R200_DEBUG & DEBUG_TEXTURE)
804 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
805 }
806 else */{
807 if (R200_DEBUG & DEBUG_TEXTURE)
808 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
809
810 /* Normal path: copy (to cached memory) and eventually upload
811 * via another copy to GART memory and then a blit... Could
812 * eliminate one copy by going straight to (permanent) GART.
813 *
814 * Note, this will call r200ChooseTextureFormat.
815 */
816 _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
817 height, border, imageSize, data, texObj, texImage);
818
819 t->dirty_images[face] |= (1 << level);
820 }
821 }
822
823
824 static void r200CompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
825 GLint xoffset, GLint yoffset,
826 GLsizei width, GLsizei height,
827 GLenum format,
828 GLsizei imageSize, const GLvoid *data,
829 struct gl_texture_object *texObj,
830 struct gl_texture_image *texImage )
831 {
832 driTextureObject * t = (driTextureObject *) texObj->DriverData;
833 GLuint face;
834
835
836 /* which cube face or ordinary 2D image */
837 switch (target) {
838 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
839 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
840 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
841 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
842 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
843 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
844 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
845 ASSERT(face < 6);
846 break;
847 default:
848 face = 0;
849 }
850
851 assert( t ); /* this _should_ be true */
852 if ( t ) {
853 driSwapOutTextureObject( t );
854 }
855 else {
856 t = (driTextureObject *) r200AllocTexObj( texObj );
857 if (!t) {
858 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D");
859 return;
860 }
861 }
862
863 _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
864 height, format, imageSize, data, texObj, texImage);
865
866 t->dirty_images[face] |= (1 << level);
867 }
868
869
870 #if ENABLE_HW_3D_TEXTURE
871 static void r200TexImage3D( GLcontext *ctx, GLenum target, GLint level,
872 GLint internalFormat,
873 GLint width, GLint height, GLint depth,
874 GLint border,
875 GLenum format, GLenum type, const GLvoid *pixels,
876 const struct gl_pixelstore_attrib *packing,
877 struct gl_texture_object *texObj,
878 struct gl_texture_image *texImage )
879 {
880 driTextureObject * t = (driTextureObject *) texObj->DriverData;
881
882 if ( t ) {
883 driSwapOutTextureObject( t );
884 }
885 else {
886 t = (driTextureObject *) r200AllocTexObj( texObj );
887 if (!t) {
888 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
889 return;
890 }
891 }
892
893 texImage->IsClientData = GL_FALSE;
894
895 #if 0
896 if (r200ValidateClientStorage( ctx, target,
897 internalFormat,
898 width, height,
899 format, type, pixels,
900 packing, texObj, texImage)) {
901 if (R200_DEBUG & DEBUG_TEXTURE)
902 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
903 }
904 else
905 #endif
906 {
907 if (R200_DEBUG & DEBUG_TEXTURE)
908 fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
909
910 /* Normal path: copy (to cached memory) and eventually upload
911 * via another copy to GART memory and then a blit... Could
912 * eliminate one copy by going straight to (permanent) GART.
913 *
914 * Note, this will call r200ChooseTextureFormat.
915 */
916 _mesa_store_teximage3d(ctx, target, level, internalFormat,
917 width, height, depth, border,
918 format, type, pixels,
919 &ctx->Unpack, texObj, texImage);
920
921 t->dirty_images[0] |= (1 << level);
922 }
923 }
924 #endif
925
926
927 #if ENABLE_HW_3D_TEXTURE
928 static void
929 r200TexSubImage3D( GLcontext *ctx, GLenum target, GLint level,
930 GLint xoffset, GLint yoffset, GLint zoffset,
931 GLsizei width, GLsizei height, GLsizei depth,
932 GLenum format, GLenum type,
933 const GLvoid *pixels,
934 const struct gl_pixelstore_attrib *packing,
935 struct gl_texture_object *texObj,
936 struct gl_texture_image *texImage )
937 {
938 driTextureObject * t = (driTextureObject *) texObj->DriverData;
939
940 /* fprintf(stderr, "%s\n", __FUNCTION__); */
941
942 assert( t ); /* this _should_ be true */
943 if ( t ) {
944 driSwapOutTextureObject( t );
945 }
946 else {
947 t = (driTextureObject *) r200AllocTexObj( texObj );
948 if (!t) {
949 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
950 return;
951 }
952 texObj->DriverData = t;
953 }
954
955 _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
956 width, height, depth,
957 format, type, pixels, packing, texObj, texImage);
958
959 t->dirty_images[0] |= (1 << level);
960 }
961 #endif
962
963
964
965 static void r200TexEnv( GLcontext *ctx, GLenum target,
966 GLenum pname, const GLfloat *param )
967 {
968 r200ContextPtr rmesa = R200_CONTEXT(ctx);
969 GLuint unit = ctx->Texture.CurrentUnit;
970 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
971
972 if ( R200_DEBUG & DEBUG_STATE ) {
973 fprintf( stderr, "%s( %s )\n",
974 __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
975 }
976
977 /* This is incorrect: Need to maintain this data for each of
978 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
979 * between them according to _ReallyEnabled.
980 */
981 switch ( pname ) {
982 case GL_TEXTURE_ENV_COLOR: {
983 GLubyte c[4];
984 GLuint envColor;
985 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
986 envColor = r200PackColor( 4, c[0], c[1], c[2], c[3] );
987 if ( rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor ) {
988 R200_STATECHANGE( rmesa, tf );
989 rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] = envColor;
990 }
991 break;
992 }
993
994 case GL_TEXTURE_LOD_BIAS_EXT: {
995 GLfloat bias, min;
996 GLuint b;
997 const int fixed_one = 0x8000000;
998
999 /* The R200's LOD bias is a signed 2's complement value with a
1000 * range of -16.0 <= bias < 16.0.
1001 *
1002 * NOTE: Add a small bias to the bias for conform mipsel.c test.
1003 */
1004 bias = *param + .01;
1005 min = driQueryOptionb (&rmesa->optionCache, "no_neg_lod_bias") ?
1006 0.0 : -16.0;
1007 bias = CLAMP( bias, min, 16.0 );
1008 b = (int)(bias * fixed_one) & R200_LOD_BIAS_MASK;
1009
1010 if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] & R200_LOD_BIAS_MASK) != b ) {
1011 R200_STATECHANGE( rmesa, tex[unit] );
1012 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] &= ~R200_LOD_BIAS_MASK;
1013 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] |= b;
1014 }
1015 break;
1016 }
1017 case GL_COORD_REPLACE_ARB:
1018 if (ctx->Point.PointSprite) {
1019 R200_STATECHANGE( rmesa, spr );
1020 if ((GLenum)param[0]) {
1021 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_GEN_TEX_0 << unit;
1022 } else {
1023 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~(R200_PS_GEN_TEX_0 << unit);
1024 }
1025 }
1026 break;
1027 default:
1028 return;
1029 }
1030 }
1031
1032
1033 /**
1034 * Changes variables and flags for a state update, which will happen at the
1035 * next UpdateTextureState
1036 */
1037
1038 static void r200TexParameter( GLcontext *ctx, GLenum target,
1039 struct gl_texture_object *texObj,
1040 GLenum pname, const GLfloat *params )
1041 {
1042 r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData;
1043
1044 if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
1045 fprintf( stderr, "%s( %s )\n", __FUNCTION__,
1046 _mesa_lookup_enum_by_nr( pname ) );
1047 }
1048
1049 switch ( pname ) {
1050 case GL_TEXTURE_MIN_FILTER:
1051 case GL_TEXTURE_MAG_FILTER:
1052 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1053 r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
1054 r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
1055 break;
1056
1057 case GL_TEXTURE_WRAP_S:
1058 case GL_TEXTURE_WRAP_T:
1059 case GL_TEXTURE_WRAP_R:
1060 r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR );
1061 break;
1062
1063 case GL_TEXTURE_BORDER_COLOR:
1064 r200SetTexBorderColor( t, texObj->BorderColor );
1065 break;
1066
1067 case GL_TEXTURE_BASE_LEVEL:
1068 case GL_TEXTURE_MAX_LEVEL:
1069 case GL_TEXTURE_MIN_LOD:
1070 case GL_TEXTURE_MAX_LOD:
1071 /* This isn't the most efficient solution but there doesn't appear to
1072 * be a nice alternative. Since there's no LOD clamping,
1073 * we just have to rely on loading the right subset of mipmap levels
1074 * to simulate a clamped LOD.
1075 */
1076 driSwapOutTextureObject( (driTextureObject *) t );
1077 break;
1078
1079 default:
1080 return;
1081 }
1082
1083 /* Mark this texobj as dirty (one bit per tex unit)
1084 */
1085 t->dirty_state = TEX_ALL;
1086 }
1087
1088
1089
1090 static void r200BindTexture( GLcontext *ctx, GLenum target,
1091 struct gl_texture_object *texObj )
1092 {
1093 if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
1094 fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, (void *)texObj,
1095 ctx->Texture.CurrentUnit );
1096 }
1097
1098 if ( (target == GL_TEXTURE_1D)
1099 || (target == GL_TEXTURE_2D)
1100 #if ENABLE_HW_3D_TEXTURE
1101 || (target == GL_TEXTURE_3D)
1102 #endif
1103 || (target == GL_TEXTURE_CUBE_MAP)
1104 || (target == GL_TEXTURE_RECTANGLE_NV) ) {
1105 assert( texObj->DriverData != NULL );
1106 }
1107 }
1108
1109
1110 static void r200DeleteTexture( GLcontext *ctx,
1111 struct gl_texture_object *texObj )
1112 {
1113 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1114 driTextureObject * t = (driTextureObject *) texObj->DriverData;
1115
1116 if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
1117 fprintf( stderr, "%s( %p (target = %s) )\n", __FUNCTION__, (void *)texObj,
1118 _mesa_lookup_enum_by_nr( texObj->Target ) );
1119 }
1120
1121 if ( t != NULL ) {
1122 if ( rmesa ) {
1123 R200_FIREVERTICES( rmesa );
1124 }
1125
1126 driDestroyTextureObject( t );
1127 }
1128 /* Free mipmap images and the texture object itself */
1129 _mesa_delete_texture_object(ctx, texObj);
1130 }
1131
1132 /* Need:
1133 * - Same GEN_MODE for all active bits
1134 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
1135 * - STRQ presumably all supported (matrix means incoming R values
1136 * can end up in STQ, this has implications for vertex support,
1137 * presumably ok if maos is used, though?)
1138 *
1139 * Basically impossible to do this on the fly - just collect some
1140 * basic info & do the checks from ValidateState().
1141 */
1142 static void r200TexGen( GLcontext *ctx,
1143 GLenum coord,
1144 GLenum pname,
1145 const GLfloat *params )
1146 {
1147 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1148 GLuint unit = ctx->Texture.CurrentUnit;
1149 rmesa->recheck_texgen[unit] = GL_TRUE;
1150 }
1151
1152
1153 /**
1154 * Allocate a new texture object.
1155 * Called via ctx->Driver.NewTextureObject.
1156 * Note: this function will be called during context creation to
1157 * allocate the default texture objects.
1158 * Note: we could use containment here to 'derive' the driver-specific
1159 * texture object from the core mesa gl_texture_object. Not done at this time.
1160 * Fixup MaxAnisotropy according to user preference.
1161 */
1162 static struct gl_texture_object *
1163 r200NewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
1164 {
1165 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1166 struct gl_texture_object *obj;
1167 obj = _mesa_new_texture_object(ctx, name, target);
1168 if (!obj)
1169 return NULL;
1170 obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
1171 r200AllocTexObj( obj );
1172 return obj;
1173 }
1174
1175
1176 void r200InitTextureFuncs( struct dd_function_table *functions )
1177 {
1178 /* Note: we only plug in the functions we implement in the driver
1179 * since _mesa_init_driver_functions() was already called.
1180 */
1181 functions->ChooseTextureFormat = r200ChooseTextureFormat;
1182 functions->TexImage1D = r200TexImage1D;
1183 functions->TexImage2D = r200TexImage2D;
1184 #if ENABLE_HW_3D_TEXTURE
1185 functions->TexImage3D = r200TexImage3D;
1186 #else
1187 functions->TexImage3D = _mesa_store_teximage3d;
1188 #endif
1189 functions->TexSubImage1D = r200TexSubImage1D;
1190 functions->TexSubImage2D = r200TexSubImage2D;
1191 #if ENABLE_HW_3D_TEXTURE
1192 functions->TexSubImage3D = r200TexSubImage3D;
1193 #else
1194 functions->TexSubImage3D = _mesa_store_texsubimage3d;
1195 #endif
1196 functions->NewTextureObject = r200NewTextureObject;
1197 functions->BindTexture = r200BindTexture;
1198 functions->DeleteTexture = r200DeleteTexture;
1199 functions->IsTextureResident = driIsTextureResident;
1200
1201 functions->TexEnv = r200TexEnv;
1202 functions->TexParameter = r200TexParameter;
1203 functions->TexGen = r200TexGen;
1204
1205 functions->CompressedTexImage2D = r200CompressedTexImage2D;
1206 functions->CompressedTexSubImage2D = r200CompressedTexSubImage2D;
1207
1208 driInitTextureFormats();
1209
1210 #if 000
1211 /* moved or obsolete code */
1212 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1213 driInitTextureObjects( ctx, & rmesa->swapped,
1214 DRI_TEXMGR_DO_TEXTURE_1D
1215 | DRI_TEXMGR_DO_TEXTURE_2D );
1216
1217 /* Hack: r200NewTextureObject is not yet installed when the
1218 * default textures are created. Therefore set MaxAnisotropy of the
1219 * default 2D texture now. */
1220 ctx->Shared->Default2D->MaxAnisotropy = driQueryOptionf (&rmesa->optionCache,
1221 "def_max_anisotropy");
1222 #endif
1223 }