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