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