added a few more fallbackStrings (Andreas Stenglein)
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_tex.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c,v 1.6 2002/09/16 18:05:20 eich Exp $ */
2 /*
3 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4 VA Linux Systems Inc., Fremont, California.
5
6 All Rights Reserved.
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 * Gareth Hughes <gareth@valinux.com>
32 * Brian Paul <brianp@valinux.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 "teximage.h"
45 #include "texobj.h"
46
47
48 #include "radeon_context.h"
49 #include "radeon_state.h"
50 #include "radeon_ioctl.h"
51 #include "radeon_swtcl.h"
52 #include "radeon_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 radeonSetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap )
67 {
68 GLboolean is_clamp = GL_FALSE;
69 GLboolean is_clamp_to_border = GL_FALSE;
70
71 t->pp_txfilter &= ~(RADEON_CLAMP_S_MASK | RADEON_CLAMP_T_MASK | RADEON_BORDER_MODE_D3D);
72
73 switch ( swrap ) {
74 case GL_REPEAT:
75 t->pp_txfilter |= RADEON_CLAMP_S_WRAP;
76 break;
77 case GL_CLAMP:
78 t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_GL;
79 is_clamp = GL_TRUE;
80 break;
81 case GL_CLAMP_TO_EDGE:
82 t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST;
83 break;
84 case GL_CLAMP_TO_BORDER:
85 t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_GL;
86 is_clamp_to_border = GL_TRUE;
87 break;
88 case GL_MIRRORED_REPEAT:
89 t->pp_txfilter |= RADEON_CLAMP_S_MIRROR;
90 break;
91 case GL_MIRROR_CLAMP_EXT:
92 t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_GL;
93 is_clamp = GL_TRUE;
94 break;
95 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
96 t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_LAST;
97 break;
98 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
99 t->pp_txfilter |= RADEON_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 switch ( twrap ) {
107 case GL_REPEAT:
108 t->pp_txfilter |= RADEON_CLAMP_T_WRAP;
109 break;
110 case GL_CLAMP:
111 t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_GL;
112 is_clamp = GL_TRUE;
113 break;
114 case GL_CLAMP_TO_EDGE:
115 t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST;
116 break;
117 case GL_CLAMP_TO_BORDER:
118 t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_GL;
119 is_clamp_to_border = GL_TRUE;
120 break;
121 case GL_MIRRORED_REPEAT:
122 t->pp_txfilter |= RADEON_CLAMP_T_MIRROR;
123 break;
124 case GL_MIRROR_CLAMP_EXT:
125 t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_GL;
126 is_clamp = GL_TRUE;
127 break;
128 case GL_MIRROR_CLAMP_TO_EDGE_EXT:
129 t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_LAST;
130 break;
131 case GL_MIRROR_CLAMP_TO_BORDER_EXT:
132 t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_GL;
133 is_clamp_to_border = GL_TRUE;
134 break;
135 default:
136 _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
137 }
138
139 if ( is_clamp_to_border ) {
140 t->pp_txfilter |= RADEON_BORDER_MODE_D3D;
141 }
142
143 t->border_fallback = (is_clamp && is_clamp_to_border);
144 }
145
146 static void radeonSetTexMaxAnisotropy( radeonTexObjPtr t, GLfloat max )
147 {
148 t->pp_txfilter &= ~RADEON_MAX_ANISO_MASK;
149
150 if ( max == 1.0 ) {
151 t->pp_txfilter |= RADEON_MAX_ANISO_1_TO_1;
152 } else if ( max <= 2.0 ) {
153 t->pp_txfilter |= RADEON_MAX_ANISO_2_TO_1;
154 } else if ( max <= 4.0 ) {
155 t->pp_txfilter |= RADEON_MAX_ANISO_4_TO_1;
156 } else if ( max <= 8.0 ) {
157 t->pp_txfilter |= RADEON_MAX_ANISO_8_TO_1;
158 } else {
159 t->pp_txfilter |= RADEON_MAX_ANISO_16_TO_1;
160 }
161 }
162
163 /**
164 * Set the texture magnification and minification modes.
165 *
166 * \param t Texture whose filter modes are to be set
167 * \param minf Texture minification mode
168 * \param magf Texture magnification mode
169 */
170
171 static void radeonSetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf )
172 {
173 GLuint anisotropy = (t->pp_txfilter & RADEON_MAX_ANISO_MASK);
174
175 t->pp_txfilter &= ~(RADEON_MIN_FILTER_MASK | RADEON_MAG_FILTER_MASK);
176
177 if ( anisotropy == RADEON_MAX_ANISO_1_TO_1 ) {
178 switch ( minf ) {
179 case GL_NEAREST:
180 t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST;
181 break;
182 case GL_LINEAR:
183 t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR;
184 break;
185 case GL_NEAREST_MIPMAP_NEAREST:
186 t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST;
187 break;
188 case GL_NEAREST_MIPMAP_LINEAR:
189 t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST;
190 break;
191 case GL_LINEAR_MIPMAP_NEAREST:
192 t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR;
193 break;
194 case GL_LINEAR_MIPMAP_LINEAR:
195 t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR;
196 break;
197 }
198 } else {
199 switch ( minf ) {
200 case GL_NEAREST:
201 t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST;
202 break;
203 case GL_LINEAR:
204 t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_LINEAR;
205 break;
206 case GL_NEAREST_MIPMAP_NEAREST:
207 case GL_LINEAR_MIPMAP_NEAREST:
208 t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST;
209 break;
210 case GL_NEAREST_MIPMAP_LINEAR:
211 case GL_LINEAR_MIPMAP_LINEAR:
212 t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR;
213 break;
214 }
215 }
216
217 switch ( magf ) {
218 case GL_NEAREST:
219 t->pp_txfilter |= RADEON_MAG_FILTER_NEAREST;
220 break;
221 case GL_LINEAR:
222 t->pp_txfilter |= RADEON_MAG_FILTER_LINEAR;
223 break;
224 }
225 }
226
227 static void radeonSetTexBorderColor( radeonTexObjPtr t, GLubyte c[4] )
228 {
229 t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
230 }
231
232
233 /**
234 * Allocate space for and load the mesa images into the texture memory block.
235 * This will happen before drawing with a new texture, or drawing with a
236 * texture after it was swapped out or teximaged again.
237 */
238
239 static radeonTexObjPtr radeonAllocTexObj( struct gl_texture_object *texObj )
240 {
241 radeonTexObjPtr t;
242
243 t = CALLOC_STRUCT( radeon_tex_obj );
244 texObj->DriverData = t;
245 if ( t != NULL ) {
246 if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
247 fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, (void *)texObj, (void *)t );
248 }
249
250 /* Initialize non-image-dependent parts of the state:
251 */
252 t->base.tObj = texObj;
253 t->border_fallback = GL_FALSE;
254
255 t->pp_txfilter = RADEON_BORDER_MODE_OGL;
256 t->pp_txformat = (RADEON_TXFORMAT_ENDIAN_NO_SWAP |
257 RADEON_TXFORMAT_PERSPECTIVE_ENABLE);
258
259 make_empty_list( & t->base );
260
261 radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT );
262 radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
263 radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
264 radeonSetTexBorderColor( t, texObj->_BorderChan );
265 }
266
267 return t;
268 }
269
270
271 static const struct gl_texture_format *
272 radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
273 GLenum format, GLenum type )
274 {
275 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
276 const GLboolean do32bpt =
277 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
278 const GLboolean force16bpt =
279 ( rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
280 (void) format;
281
282 switch ( internalFormat ) {
283 case 4:
284 case GL_RGBA:
285 case GL_COMPRESSED_RGBA:
286 switch ( type ) {
287 case GL_UNSIGNED_INT_10_10_10_2:
288 case GL_UNSIGNED_INT_2_10_10_10_REV:
289 return do32bpt ? _dri_texformat_argb8888 : _dri_texformat_argb1555;
290 case GL_UNSIGNED_SHORT_4_4_4_4:
291 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
292 return _dri_texformat_argb4444;
293 case GL_UNSIGNED_SHORT_5_5_5_1:
294 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
295 return _dri_texformat_argb1555;
296 default:
297 return do32bpt ? _dri_texformat_rgba8888 : _dri_texformat_argb4444;
298 }
299
300 case 3:
301 case GL_RGB:
302 case GL_COMPRESSED_RGB:
303 switch ( type ) {
304 case GL_UNSIGNED_SHORT_4_4_4_4:
305 case GL_UNSIGNED_SHORT_4_4_4_4_REV:
306 return _dri_texformat_argb4444;
307 case GL_UNSIGNED_SHORT_5_5_5_1:
308 case GL_UNSIGNED_SHORT_1_5_5_5_REV:
309 return _dri_texformat_argb1555;
310 case GL_UNSIGNED_SHORT_5_6_5:
311 case GL_UNSIGNED_SHORT_5_6_5_REV:
312 return _dri_texformat_rgb565;
313 default:
314 return do32bpt ? _dri_texformat_rgba8888 : _dri_texformat_rgb565;
315 }
316
317 case GL_RGBA8:
318 case GL_RGB10_A2:
319 case GL_RGBA12:
320 case GL_RGBA16:
321 return !force16bpt ?
322 _dri_texformat_rgba8888 : _dri_texformat_argb4444;
323
324 case GL_RGBA4:
325 case GL_RGBA2:
326 return _dri_texformat_argb4444;
327
328 case GL_RGB5_A1:
329 return _dri_texformat_argb1555;
330
331 case GL_RGB8:
332 case GL_RGB10:
333 case GL_RGB12:
334 case GL_RGB16:
335 return !force16bpt ? _dri_texformat_rgba8888 : _dri_texformat_rgb565;
336
337 case GL_RGB5:
338 case GL_RGB4:
339 case GL_R3_G3_B2:
340 return _dri_texformat_rgb565;
341
342 case GL_ALPHA:
343 case GL_ALPHA4:
344 case GL_ALPHA8:
345 case GL_ALPHA12:
346 case GL_ALPHA16:
347 case GL_COMPRESSED_ALPHA:
348 return _dri_texformat_a8;
349
350 case 1:
351 case GL_LUMINANCE:
352 case GL_LUMINANCE4:
353 case GL_LUMINANCE8:
354 case GL_LUMINANCE12:
355 case GL_LUMINANCE16:
356 case GL_COMPRESSED_LUMINANCE:
357 return _dri_texformat_l8;
358
359 case 2:
360 case GL_LUMINANCE_ALPHA:
361 case GL_LUMINANCE4_ALPHA4:
362 case GL_LUMINANCE6_ALPHA2:
363 case GL_LUMINANCE8_ALPHA8:
364 case GL_LUMINANCE12_ALPHA4:
365 case GL_LUMINANCE12_ALPHA12:
366 case GL_LUMINANCE16_ALPHA16:
367 case GL_COMPRESSED_LUMINANCE_ALPHA:
368 return _dri_texformat_al88;
369
370 case GL_INTENSITY:
371 case GL_INTENSITY4:
372 case GL_INTENSITY8:
373 case GL_INTENSITY12:
374 case GL_INTENSITY16:
375 case GL_COMPRESSED_INTENSITY:
376 return _dri_texformat_i8;
377
378 case GL_YCBCR_MESA:
379 if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
380 type == GL_UNSIGNED_BYTE)
381 return &_mesa_texformat_ycbcr;
382 else
383 return &_mesa_texformat_ycbcr_rev;
384
385 case GL_RGB_S3TC:
386 case GL_RGB4_S3TC:
387 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
388 return &_mesa_texformat_rgb_dxt1;
389
390 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
391 return &_mesa_texformat_rgba_dxt1;
392
393 case GL_RGBA_S3TC:
394 case GL_RGBA4_S3TC:
395 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
396 return &_mesa_texformat_rgba_dxt3;
397
398 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
399 return &_mesa_texformat_rgba_dxt5;
400
401 default:
402 _mesa_problem(ctx, "unexpected texture format in %s", __FUNCTION__);
403 return NULL;
404 }
405
406 return NULL; /* never get here */
407 }
408
409
410 static void radeonTexImage1D( GLcontext *ctx, GLenum target, GLint level,
411 GLint internalFormat,
412 GLint width, GLint border,
413 GLenum format, GLenum type, const GLvoid *pixels,
414 const struct gl_pixelstore_attrib *packing,
415 struct gl_texture_object *texObj,
416 struct gl_texture_image *texImage )
417 {
418 driTextureObject * t = (driTextureObject *) texObj->DriverData;
419
420 if ( t ) {
421 driSwapOutTextureObject( t );
422 }
423 else {
424 t = (driTextureObject *) radeonAllocTexObj( texObj );
425 if (!t) {
426 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
427 return;
428 }
429 }
430
431 /* Note, this will call ChooseTextureFormat */
432 _mesa_store_teximage1d(ctx, target, level, internalFormat,
433 width, border, format, type, pixels,
434 &ctx->Unpack, texObj, texImage);
435
436 t->dirty_images[0] |= (1 << level);
437 }
438
439
440 static void radeonTexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
441 GLint xoffset,
442 GLsizei width,
443 GLenum format, GLenum type,
444 const GLvoid *pixels,
445 const struct gl_pixelstore_attrib *packing,
446 struct gl_texture_object *texObj,
447 struct gl_texture_image *texImage )
448 {
449 driTextureObject * t = (driTextureObject *) texObj->DriverData;
450
451 assert( t ); /* this _should_ be true */
452 if ( t ) {
453 driSwapOutTextureObject( t );
454 }
455 else {
456 t = (driTextureObject *) radeonAllocTexObj( texObj );
457 if (!t) {
458 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
459 return;
460 }
461 }
462
463 _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
464 format, type, pixels, packing, texObj,
465 texImage);
466
467 t->dirty_images[0] |= (1 << level);
468 }
469
470
471 static void radeonTexImage2D( GLcontext *ctx, GLenum target, GLint level,
472 GLint internalFormat,
473 GLint width, GLint height, GLint border,
474 GLenum format, GLenum type, const GLvoid *pixels,
475 const struct gl_pixelstore_attrib *packing,
476 struct gl_texture_object *texObj,
477 struct gl_texture_image *texImage )
478 {
479 driTextureObject * t = (driTextureObject *) texObj->DriverData;
480 GLuint face;
481
482 /* which cube face or ordinary 2D image */
483 switch (target) {
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;
491 ASSERT(face < 6);
492 break;
493 default:
494 face = 0;
495 }
496
497 if ( t != NULL ) {
498 driSwapOutTextureObject( t );
499 }
500 else {
501 t = (driTextureObject *) radeonAllocTexObj( texObj );
502 if (!t) {
503 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
504 return;
505 }
506 }
507
508 /* Note, this will call ChooseTextureFormat */
509 _mesa_store_teximage2d(ctx, target, level, internalFormat,
510 width, height, border, format, type, pixels,
511 &ctx->Unpack, texObj, texImage);
512
513 t->dirty_images[face] |= (1 << level);
514 }
515
516
517 static void radeonTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
518 GLint xoffset, GLint yoffset,
519 GLsizei width, GLsizei height,
520 GLenum format, GLenum type,
521 const GLvoid *pixels,
522 const struct gl_pixelstore_attrib *packing,
523 struct gl_texture_object *texObj,
524 struct gl_texture_image *texImage )
525 {
526 driTextureObject * t = (driTextureObject *) texObj->DriverData;
527 GLuint face;
528
529 /* which cube face or ordinary 2D image */
530 switch (target) {
531 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
532 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
533 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
534 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
535 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
536 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
537 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
538 ASSERT(face < 6);
539 break;
540 default:
541 face = 0;
542 }
543
544 assert( t ); /* this _should_ be true */
545 if ( t ) {
546 driSwapOutTextureObject( t );
547 }
548 else {
549 t = (driTextureObject *) radeonAllocTexObj( texObj );
550 if (!t) {
551 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
552 return;
553 }
554 }
555
556 _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
557 height, format, type, pixels, packing, texObj,
558 texImage);
559
560 t->dirty_images[face] |= (1 << level);
561 }
562
563 static void radeonCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
564 GLint internalFormat,
565 GLint width, GLint height, GLint border,
566 GLsizei imageSize, const GLvoid *data,
567 struct gl_texture_object *texObj,
568 struct gl_texture_image *texImage )
569 {
570 driTextureObject * t = (driTextureObject *) texObj->DriverData;
571 GLuint face;
572
573 /* which cube face or ordinary 2D image */
574 switch (target) {
575 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
576 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
577 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
578 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
579 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
580 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
581 face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
582 ASSERT(face < 6);
583 break;
584 default:
585 face = 0;
586 }
587
588 if ( t != NULL ) {
589 driSwapOutTextureObject( t );
590 }
591 else {
592 t = (driTextureObject *) radeonAllocTexObj( texObj );
593 if (!t) {
594 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
595 return;
596 }
597 }
598
599 /* Note, this will call ChooseTextureFormat */
600 _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
601 height, border, imageSize, data, texObj, texImage);
602
603 t->dirty_images[face] |= (1 << level);
604 }
605
606
607 static void radeonCompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
608 GLint xoffset, GLint yoffset,
609 GLsizei width, GLsizei height,
610 GLenum format,
611 GLsizei imageSize, const GLvoid *data,
612 struct gl_texture_object *texObj,
613 struct gl_texture_image *texImage )
614 {
615 driTextureObject * t = (driTextureObject *) texObj->DriverData;
616 GLuint face;
617
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 assert( t ); /* this _should_ be true */
635 if ( t ) {
636 driSwapOutTextureObject( t );
637 }
638 else {
639 t = (driTextureObject *) radeonAllocTexObj( texObj );
640 if (!t) {
641 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D");
642 return;
643 }
644 }
645
646 _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
647 height, format, imageSize, data, texObj, texImage);
648
649 t->dirty_images[face] |= (1 << level);
650 }
651
652 #define SCALED_FLOAT_TO_BYTE( x, scale ) \
653 (((GLuint)((255.0F / scale) * (x))) / 2)
654
655 static void radeonTexEnv( GLcontext *ctx, GLenum target,
656 GLenum pname, const GLfloat *param )
657 {
658 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
659 GLuint unit = ctx->Texture.CurrentUnit;
660 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
661
662 if ( RADEON_DEBUG & DEBUG_STATE ) {
663 fprintf( stderr, "%s( %s )\n",
664 __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
665 }
666
667 switch ( pname ) {
668 case GL_TEXTURE_ENV_COLOR: {
669 GLubyte c[4];
670 GLuint envColor;
671 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
672 envColor = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
673 if ( rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] != envColor ) {
674 RADEON_STATECHANGE( rmesa, tex[unit] );
675 rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] = envColor;
676 }
677 break;
678 }
679
680 case GL_TEXTURE_LOD_BIAS_EXT: {
681 GLfloat bias, min;
682 GLuint b;
683
684 /* The Radeon's LOD bias is a signed 2's complement value with a
685 * range of -1.0 <= bias < 4.0. We break this into two linear
686 * functions, one mapping [-1.0,0.0] to [-128,0] and one mapping
687 * [0.0,4.0] to [0,127].
688 */
689 min = driQueryOptionb (&rmesa->optionCache, "no_neg_lod_bias") ?
690 0.0 : -1.0;
691 bias = CLAMP( *param, min, 4.0 );
692 if ( bias == 0 ) {
693 b = 0;
694 } else if ( bias > 0 ) {
695 b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 4.0 )) << RADEON_LOD_BIAS_SHIFT;
696 } else {
697 b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 1.0 )) << RADEON_LOD_BIAS_SHIFT;
698 }
699 if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] & RADEON_LOD_BIAS_MASK) != b ) {
700 RADEON_STATECHANGE( rmesa, tex[unit] );
701 rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] &= ~RADEON_LOD_BIAS_MASK;
702 rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] |= (b & RADEON_LOD_BIAS_MASK);
703 }
704 break;
705 }
706
707 default:
708 return;
709 }
710 }
711
712
713 /**
714 * Changes variables and flags for a state update, which will happen at the
715 * next UpdateTextureState
716 */
717
718 static void radeonTexParameter( GLcontext *ctx, GLenum target,
719 struct gl_texture_object *texObj,
720 GLenum pname, const GLfloat *params )
721 {
722 radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
723
724 if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
725 fprintf( stderr, "%s( %s )\n", __FUNCTION__,
726 _mesa_lookup_enum_by_nr( pname ) );
727 }
728
729 switch ( pname ) {
730 case GL_TEXTURE_MIN_FILTER:
731 case GL_TEXTURE_MAG_FILTER:
732 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
733 radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
734 radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
735 break;
736
737 case GL_TEXTURE_WRAP_S:
738 case GL_TEXTURE_WRAP_T:
739 radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT );
740 break;
741
742 case GL_TEXTURE_BORDER_COLOR:
743 radeonSetTexBorderColor( t, texObj->_BorderChan );
744 break;
745
746 case GL_TEXTURE_BASE_LEVEL:
747 case GL_TEXTURE_MAX_LEVEL:
748 case GL_TEXTURE_MIN_LOD:
749 case GL_TEXTURE_MAX_LOD:
750 /* This isn't the most efficient solution but there doesn't appear to
751 * be a nice alternative. Since there's no LOD clamping,
752 * we just have to rely on loading the right subset of mipmap levels
753 * to simulate a clamped LOD.
754 */
755 driSwapOutTextureObject( (driTextureObject *) t );
756 break;
757
758 default:
759 return;
760 }
761
762 /* Mark this texobj as dirty (one bit per tex unit)
763 */
764 t->dirty_state = TEX_ALL;
765 }
766
767
768 static void radeonBindTexture( GLcontext *ctx, GLenum target,
769 struct gl_texture_object *texObj )
770 {
771 if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
772 fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, (void *)texObj,
773 ctx->Texture.CurrentUnit );
774 }
775
776 assert( (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D &&
777 target != GL_TEXTURE_RECTANGLE_NV) ||
778 (texObj->DriverData != NULL) );
779 }
780
781
782 static void radeonDeleteTexture( GLcontext *ctx,
783 struct gl_texture_object *texObj )
784 {
785 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
786 driTextureObject * t = (driTextureObject *) texObj->DriverData;
787
788 if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
789 fprintf( stderr, "%s( %p (target = %s) )\n", __FUNCTION__, (void *)texObj,
790 _mesa_lookup_enum_by_nr( texObj->Target ) );
791 }
792
793 if ( t != NULL ) {
794 if ( rmesa ) {
795 RADEON_FIREVERTICES( rmesa );
796 }
797
798 driDestroyTextureObject( t );
799 }
800
801 /* Free mipmap images and the texture object itself */
802 _mesa_delete_texture_object(ctx, texObj);
803 }
804
805 /* Need:
806 * - Same GEN_MODE for all active bits
807 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
808 * - STRQ presumably all supported (matrix means incoming R values
809 * can end up in STQ, this has implications for vertex support,
810 * presumably ok if maos is used, though?)
811 *
812 * Basically impossible to do this on the fly - just collect some
813 * basic info & do the checks from ValidateState().
814 */
815 static void radeonTexGen( GLcontext *ctx,
816 GLenum coord,
817 GLenum pname,
818 const GLfloat *params )
819 {
820 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
821 GLuint unit = ctx->Texture.CurrentUnit;
822 rmesa->recheck_texgen[unit] = GL_TRUE;
823 }
824
825 /**
826 * Allocate a new texture object.
827 * Called via ctx->Driver.NewTextureObject.
828 * Note: we could use containment here to 'derive' the driver-specific
829 * texture object from the core mesa gl_texture_object. Not done at this time.
830 */
831 static struct gl_texture_object *
832 radeonNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
833 {
834 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
835 struct gl_texture_object *obj;
836 obj = _mesa_new_texture_object(ctx, name, target);
837 if (!obj)
838 return NULL;
839 obj->MaxAnisotropy = rmesa->initialMaxAnisotropy;
840 radeonAllocTexObj( obj );
841 return obj;
842 }
843
844
845 void radeonInitTextureFuncs( struct dd_function_table *functions )
846 {
847 functions->ChooseTextureFormat = radeonChooseTextureFormat;
848 functions->TexImage1D = radeonTexImage1D;
849 functions->TexImage2D = radeonTexImage2D;
850 functions->TexSubImage1D = radeonTexSubImage1D;
851 functions->TexSubImage2D = radeonTexSubImage2D;
852
853 functions->NewTextureObject = radeonNewTextureObject;
854 functions->BindTexture = radeonBindTexture;
855 functions->DeleteTexture = radeonDeleteTexture;
856 functions->IsTextureResident = driIsTextureResident;
857
858 functions->TexEnv = radeonTexEnv;
859 functions->TexParameter = radeonTexParameter;
860 functions->TexGen = radeonTexGen;
861
862 functions->CompressedTexImage2D = radeonCompressedTexImage2D;
863 functions->CompressedTexSubImage2D = radeonCompressedTexSubImage2D;
864
865 driInitTextureFormats();
866 }