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