2 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
3 VA Linux Systems Inc., Fremont, California.
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:
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.
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.
30 * Gareth Hughes <gareth@valinux.com>
31 * Brian Paul <brianp@valinux.com>
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"
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"
57 * Set the texture wrap modes.
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
64 static void radeonSetTexWrap( radeonTexObjPtr t
, GLenum swrap
, GLenum twrap
)
66 GLboolean is_clamp
= GL_FALSE
;
67 GLboolean is_clamp_to_border
= GL_FALSE
;
69 t
->pp_txfilter
&= ~(RADEON_CLAMP_S_MASK
| RADEON_CLAMP_T_MASK
| RADEON_BORDER_MODE_D3D
);
73 t
->pp_txfilter
|= RADEON_CLAMP_S_WRAP
;
76 t
->pp_txfilter
|= RADEON_CLAMP_S_CLAMP_GL
;
79 case GL_CLAMP_TO_EDGE
:
80 t
->pp_txfilter
|= RADEON_CLAMP_S_CLAMP_LAST
;
82 case GL_CLAMP_TO_BORDER
:
83 t
->pp_txfilter
|= RADEON_CLAMP_S_CLAMP_GL
;
84 is_clamp_to_border
= GL_TRUE
;
86 case GL_MIRRORED_REPEAT
:
87 t
->pp_txfilter
|= RADEON_CLAMP_S_MIRROR
;
89 case GL_MIRROR_CLAMP_EXT
:
90 t
->pp_txfilter
|= RADEON_CLAMP_S_MIRROR_CLAMP_GL
;
93 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
94 t
->pp_txfilter
|= RADEON_CLAMP_S_MIRROR_CLAMP_LAST
;
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
;
101 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
106 t
->pp_txfilter
|= RADEON_CLAMP_T_WRAP
;
109 t
->pp_txfilter
|= RADEON_CLAMP_T_CLAMP_GL
;
112 case GL_CLAMP_TO_EDGE
:
113 t
->pp_txfilter
|= RADEON_CLAMP_T_CLAMP_LAST
;
115 case GL_CLAMP_TO_BORDER
:
116 t
->pp_txfilter
|= RADEON_CLAMP_T_CLAMP_GL
;
117 is_clamp_to_border
= GL_TRUE
;
119 case GL_MIRRORED_REPEAT
:
120 t
->pp_txfilter
|= RADEON_CLAMP_T_MIRROR
;
122 case GL_MIRROR_CLAMP_EXT
:
123 t
->pp_txfilter
|= RADEON_CLAMP_T_MIRROR_CLAMP_GL
;
126 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
127 t
->pp_txfilter
|= RADEON_CLAMP_T_MIRROR_CLAMP_LAST
;
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
;
134 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
137 if ( is_clamp_to_border
) {
138 t
->pp_txfilter
|= RADEON_BORDER_MODE_D3D
;
141 t
->border_fallback
= (is_clamp
&& is_clamp_to_border
);
144 static void radeonSetTexMaxAnisotropy( radeonTexObjPtr t
, GLfloat max
)
146 t
->pp_txfilter
&= ~RADEON_MAX_ANISO_MASK
;
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
;
157 t
->pp_txfilter
|= RADEON_MAX_ANISO_16_TO_1
;
162 * Set the texture magnification and minification modes.
164 * \param t Texture whose filter modes are to be set
165 * \param minf Texture minification mode
166 * \param magf Texture magnification mode
169 static void radeonSetTexFilter( radeonTexObjPtr t
, GLenum minf
, GLenum magf
)
171 GLuint anisotropy
= (t
->pp_txfilter
& RADEON_MAX_ANISO_MASK
);
173 t
->pp_txfilter
&= ~(RADEON_MIN_FILTER_MASK
| RADEON_MAG_FILTER_MASK
);
175 /* r100 chips can't handle mipmaps/aniso for cubemap/volume textures */
176 if ( t
->base
.tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
179 case GL_NEAREST_MIPMAP_NEAREST
:
180 case GL_NEAREST_MIPMAP_LINEAR
:
181 t
->pp_txfilter
|= RADEON_MIN_FILTER_NEAREST
;
184 case GL_LINEAR_MIPMAP_NEAREST
:
185 case GL_LINEAR_MIPMAP_LINEAR
:
186 t
->pp_txfilter
|= RADEON_MIN_FILTER_LINEAR
;
192 else if ( anisotropy
== RADEON_MAX_ANISO_1_TO_1
) {
195 t
->pp_txfilter
|= RADEON_MIN_FILTER_NEAREST
;
198 t
->pp_txfilter
|= RADEON_MIN_FILTER_LINEAR
;
200 case GL_NEAREST_MIPMAP_NEAREST
:
201 t
->pp_txfilter
|= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST
;
203 case GL_NEAREST_MIPMAP_LINEAR
:
204 t
->pp_txfilter
|= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST
;
206 case GL_LINEAR_MIPMAP_NEAREST
:
207 t
->pp_txfilter
|= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR
;
209 case GL_LINEAR_MIPMAP_LINEAR
:
210 t
->pp_txfilter
|= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR
;
216 t
->pp_txfilter
|= RADEON_MIN_FILTER_ANISO_NEAREST
;
219 t
->pp_txfilter
|= RADEON_MIN_FILTER_ANISO_LINEAR
;
221 case GL_NEAREST_MIPMAP_NEAREST
:
222 case GL_LINEAR_MIPMAP_NEAREST
:
223 t
->pp_txfilter
|= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
;
225 case GL_NEAREST_MIPMAP_LINEAR
:
226 case GL_LINEAR_MIPMAP_LINEAR
:
227 t
->pp_txfilter
|= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR
;
234 t
->pp_txfilter
|= RADEON_MAG_FILTER_NEAREST
;
237 t
->pp_txfilter
|= RADEON_MAG_FILTER_LINEAR
;
242 static void radeonSetTexBorderColor( radeonTexObjPtr t
, const GLfloat color
[4] )
245 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
246 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
247 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
248 CLAMPED_FLOAT_TO_UBYTE(c
[3], color
[3]);
249 t
->pp_border_color
= radeonPackColor( 4, c
[0], c
[1], c
[2], c
[3] );
254 * Allocate space for and load the mesa images into the texture memory block.
255 * This will happen before drawing with a new texture, or drawing with a
256 * texture after it was swapped out or teximaged again.
259 static radeonTexObjPtr
radeonAllocTexObj( struct gl_texture_object
*texObj
)
263 t
= CALLOC_STRUCT( radeon_tex_obj
);
264 texObj
->DriverData
= t
;
266 if ( RADEON_DEBUG
& DEBUG_TEXTURE
) {
267 fprintf( stderr
, "%s( %p, %p )\n", __FUNCTION__
, (void *)texObj
, (void *)t
);
270 /* Initialize non-image-dependent parts of the state:
272 t
->base
.tObj
= texObj
;
273 t
->border_fallback
= GL_FALSE
;
275 t
->pp_txfilter
= RADEON_BORDER_MODE_OGL
;
276 t
->pp_txformat
= (RADEON_TXFORMAT_ENDIAN_NO_SWAP
|
277 RADEON_TXFORMAT_PERSPECTIVE_ENABLE
);
279 make_empty_list( & t
->base
);
281 radeonSetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
);
282 radeonSetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
283 radeonSetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
284 radeonSetTexBorderColor( t
, texObj
->BorderColor
);
291 static const struct gl_texture_format
*
292 radeonChooseTextureFormat( GLcontext
*ctx
, GLint internalFormat
,
293 GLenum format
, GLenum type
)
295 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
296 const GLboolean do32bpt
=
297 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_32
);
298 const GLboolean force16bpt
=
299 ( rmesa
->texture_depth
== DRI_CONF_TEXTURE_DEPTH_FORCE_16
);
302 switch ( internalFormat
) {
305 case GL_COMPRESSED_RGBA
:
307 case GL_UNSIGNED_INT_10_10_10_2
:
308 case GL_UNSIGNED_INT_2_10_10_10_REV
:
309 return do32bpt
? _dri_texformat_argb8888
: _dri_texformat_argb1555
;
310 case GL_UNSIGNED_SHORT_4_4_4_4
:
311 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
312 return _dri_texformat_argb4444
;
313 case GL_UNSIGNED_SHORT_5_5_5_1
:
314 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
315 return _dri_texformat_argb1555
;
317 return do32bpt
? _dri_texformat_argb8888
: _dri_texformat_argb4444
;
322 case GL_COMPRESSED_RGB
:
324 case GL_UNSIGNED_SHORT_4_4_4_4
:
325 case GL_UNSIGNED_SHORT_4_4_4_4_REV
:
326 return _dri_texformat_argb4444
;
327 case GL_UNSIGNED_SHORT_5_5_5_1
:
328 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
329 return _dri_texformat_argb1555
;
330 case GL_UNSIGNED_SHORT_5_6_5
:
331 case GL_UNSIGNED_SHORT_5_6_5_REV
:
332 return _dri_texformat_rgb565
;
334 return do32bpt
? _dri_texformat_argb8888
: _dri_texformat_rgb565
;
342 _dri_texformat_argb8888
: _dri_texformat_argb4444
;
346 return _dri_texformat_argb4444
;
349 return _dri_texformat_argb1555
;
355 return !force16bpt
? _dri_texformat_argb8888
: _dri_texformat_rgb565
;
360 return _dri_texformat_rgb565
;
367 case GL_COMPRESSED_ALPHA
:
368 return _dri_texformat_a8
;
376 case GL_COMPRESSED_LUMINANCE
:
377 return _dri_texformat_l8
;
380 case GL_LUMINANCE_ALPHA
:
381 case GL_LUMINANCE4_ALPHA4
:
382 case GL_LUMINANCE6_ALPHA2
:
383 case GL_LUMINANCE8_ALPHA8
:
384 case GL_LUMINANCE12_ALPHA4
:
385 case GL_LUMINANCE12_ALPHA12
:
386 case GL_LUMINANCE16_ALPHA16
:
387 case GL_COMPRESSED_LUMINANCE_ALPHA
:
388 return _dri_texformat_al88
;
395 case GL_COMPRESSED_INTENSITY
:
396 return _dri_texformat_i8
;
399 if (type
== GL_UNSIGNED_SHORT_8_8_APPLE
||
400 type
== GL_UNSIGNED_BYTE
)
401 return &_mesa_texformat_ycbcr
;
403 return &_mesa_texformat_ycbcr_rev
;
407 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
408 return &_mesa_texformat_rgb_dxt1
;
410 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
411 return &_mesa_texformat_rgba_dxt1
;
415 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
416 return &_mesa_texformat_rgba_dxt3
;
418 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
419 return &_mesa_texformat_rgba_dxt5
;
422 _mesa_problem(ctx
, "unexpected texture format in %s", __FUNCTION__
);
426 return NULL
; /* never get here */
430 static void radeonTexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
431 GLint internalFormat
,
432 GLint width
, GLint border
,
433 GLenum format
, GLenum type
, const GLvoid
*pixels
,
434 const struct gl_pixelstore_attrib
*packing
,
435 struct gl_texture_object
*texObj
,
436 struct gl_texture_image
*texImage
)
438 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
441 driSwapOutTextureObject( t
);
444 t
= (driTextureObject
*) radeonAllocTexObj( texObj
);
446 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage1D");
451 /* Note, this will call ChooseTextureFormat */
452 _mesa_store_teximage1d(ctx
, target
, level
, internalFormat
,
453 width
, border
, format
, type
, pixels
,
454 &ctx
->Unpack
, texObj
, texImage
);
456 t
->dirty_images
[0] |= (1 << level
);
460 static void radeonTexSubImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
463 GLenum format
, GLenum type
,
464 const GLvoid
*pixels
,
465 const struct gl_pixelstore_attrib
*packing
,
466 struct gl_texture_object
*texObj
,
467 struct gl_texture_image
*texImage
)
469 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
471 assert( t
); /* this _should_ be true */
473 driSwapOutTextureObject( t
);
476 t
= (driTextureObject
*) radeonAllocTexObj( texObj
);
478 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage1D");
483 _mesa_store_texsubimage1d(ctx
, target
, level
, xoffset
, width
,
484 format
, type
, pixels
, packing
, texObj
,
487 t
->dirty_images
[0] |= (1 << level
);
491 static void radeonTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
492 GLint internalFormat
,
493 GLint width
, GLint height
, GLint border
,
494 GLenum format
, GLenum type
, const GLvoid
*pixels
,
495 const struct gl_pixelstore_attrib
*packing
,
496 struct gl_texture_object
*texObj
,
497 struct gl_texture_image
*texImage
)
499 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
502 /* which cube face or ordinary 2D image */
504 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
505 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
506 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
507 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
508 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
509 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
510 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
518 driSwapOutTextureObject( t
);
521 t
= (driTextureObject
*) radeonAllocTexObj( texObj
);
523 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage2D");
528 /* Note, this will call ChooseTextureFormat */
529 _mesa_store_teximage2d(ctx
, target
, level
, internalFormat
,
530 width
, height
, border
, format
, type
, pixels
,
531 &ctx
->Unpack
, texObj
, texImage
);
533 t
->dirty_images
[face
] |= (1 << level
);
537 static void radeonTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
538 GLint xoffset
, GLint yoffset
,
539 GLsizei width
, GLsizei height
,
540 GLenum format
, GLenum type
,
541 const GLvoid
*pixels
,
542 const struct gl_pixelstore_attrib
*packing
,
543 struct gl_texture_object
*texObj
,
544 struct gl_texture_image
*texImage
)
546 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
549 /* which cube face or ordinary 2D image */
551 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
552 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
553 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
554 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
555 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
556 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
557 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
564 assert( t
); /* this _should_ be true */
566 driSwapOutTextureObject( t
);
569 t
= (driTextureObject
*) radeonAllocTexObj( texObj
);
571 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexSubImage2D");
576 _mesa_store_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
577 height
, format
, type
, pixels
, packing
, texObj
,
580 t
->dirty_images
[face
] |= (1 << level
);
583 static void radeonCompressedTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
584 GLint internalFormat
,
585 GLint width
, GLint height
, GLint border
,
586 GLsizei imageSize
, const GLvoid
*data
,
587 struct gl_texture_object
*texObj
,
588 struct gl_texture_image
*texImage
)
590 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
593 /* which cube face or ordinary 2D image */
595 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
596 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
597 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
598 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
599 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
600 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
601 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
609 driSwapOutTextureObject( t
);
612 t
= (driTextureObject
*) radeonAllocTexObj( texObj
);
614 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage2D");
619 /* Note, this will call ChooseTextureFormat */
620 _mesa_store_compressed_teximage2d(ctx
, target
, level
, internalFormat
, width
,
621 height
, border
, imageSize
, data
, texObj
, texImage
);
623 t
->dirty_images
[face
] |= (1 << level
);
627 static void radeonCompressedTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
628 GLint xoffset
, GLint yoffset
,
629 GLsizei width
, GLsizei height
,
631 GLsizei imageSize
, const GLvoid
*data
,
632 struct gl_texture_object
*texObj
,
633 struct gl_texture_image
*texImage
)
635 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
639 /* which cube face or ordinary 2D image */
641 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
642 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
643 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
644 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
645 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
646 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
647 face
= (GLuint
) target
- (GLuint
) GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
654 assert( t
); /* this _should_ be true */
656 driSwapOutTextureObject( t
);
659 t
= (driTextureObject
*) radeonAllocTexObj( texObj
);
661 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexSubImage2D");
666 _mesa_store_compressed_texsubimage2d(ctx
, target
, level
, xoffset
, yoffset
, width
,
667 height
, format
, imageSize
, data
, texObj
, texImage
);
669 t
->dirty_images
[face
] |= (1 << level
);
672 #define SCALED_FLOAT_TO_BYTE( x, scale ) \
673 (((GLuint)((255.0F / scale) * (x))) / 2)
675 static void radeonTexEnv( GLcontext
*ctx
, GLenum target
,
676 GLenum pname
, const GLfloat
*param
)
678 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
679 GLuint unit
= ctx
->Texture
.CurrentUnit
;
680 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
682 if ( RADEON_DEBUG
& DEBUG_STATE
) {
683 fprintf( stderr
, "%s( %s )\n",
684 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
688 case GL_TEXTURE_ENV_COLOR
: {
691 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
692 envColor
= radeonPackColor( 4, c
[0], c
[1], c
[2], c
[3] );
693 if ( rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TFACTOR
] != envColor
) {
694 RADEON_STATECHANGE( rmesa
, tex
[unit
] );
695 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TFACTOR
] = envColor
;
700 case GL_TEXTURE_LOD_BIAS_EXT
: {
704 /* The Radeon's LOD bias is a signed 2's complement value with a
705 * range of -1.0 <= bias < 4.0. We break this into two linear
706 * functions, one mapping [-1.0,0.0] to [-128,0] and one mapping
707 * [0.0,4.0] to [0,127].
709 min
= driQueryOptionb (&rmesa
->optionCache
, "no_neg_lod_bias") ?
711 bias
= CLAMP( *param
, min
, 4.0 );
714 } else if ( bias
> 0 ) {
715 b
= ((GLuint
)SCALED_FLOAT_TO_BYTE( bias
, 4.0 )) << RADEON_LOD_BIAS_SHIFT
;
717 b
= ((GLuint
)SCALED_FLOAT_TO_BYTE( bias
, 1.0 )) << RADEON_LOD_BIAS_SHIFT
;
719 if ( (rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFILTER
] & RADEON_LOD_BIAS_MASK
) != b
) {
720 RADEON_STATECHANGE( rmesa
, tex
[unit
] );
721 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFILTER
] &= ~RADEON_LOD_BIAS_MASK
;
722 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFILTER
] |= (b
& RADEON_LOD_BIAS_MASK
);
734 * Changes variables and flags for a state update, which will happen at the
735 * next UpdateTextureState
738 static void radeonTexParameter( GLcontext
*ctx
, GLenum target
,
739 struct gl_texture_object
*texObj
,
740 GLenum pname
, const GLfloat
*params
)
742 radeonTexObjPtr t
= (radeonTexObjPtr
) texObj
->DriverData
;
744 if ( RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
745 fprintf( stderr
, "%s( %s )\n", __FUNCTION__
,
746 _mesa_lookup_enum_by_nr( pname
) );
750 case GL_TEXTURE_MIN_FILTER
:
751 case GL_TEXTURE_MAG_FILTER
:
752 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
753 radeonSetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
754 radeonSetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
757 case GL_TEXTURE_WRAP_S
:
758 case GL_TEXTURE_WRAP_T
:
759 radeonSetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
);
762 case GL_TEXTURE_BORDER_COLOR
:
763 radeonSetTexBorderColor( t
, texObj
->BorderColor
);
766 case GL_TEXTURE_BASE_LEVEL
:
767 case GL_TEXTURE_MAX_LEVEL
:
768 case GL_TEXTURE_MIN_LOD
:
769 case GL_TEXTURE_MAX_LOD
:
770 /* This isn't the most efficient solution but there doesn't appear to
771 * be a nice alternative. Since there's no LOD clamping,
772 * we just have to rely on loading the right subset of mipmap levels
773 * to simulate a clamped LOD.
775 driSwapOutTextureObject( (driTextureObject
*) t
);
782 /* Mark this texobj as dirty (one bit per tex unit)
784 t
->dirty_state
= TEX_ALL
;
788 static void radeonBindTexture( GLcontext
*ctx
, GLenum target
,
789 struct gl_texture_object
*texObj
)
791 if ( RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
792 fprintf( stderr
, "%s( %p ) unit=%d\n", __FUNCTION__
, (void *)texObj
,
793 ctx
->Texture
.CurrentUnit
);
796 assert( (target
!= GL_TEXTURE_1D
&& target
!= GL_TEXTURE_2D
&&
797 target
!= GL_TEXTURE_RECTANGLE_NV
&& target
!= GL_TEXTURE_CUBE_MAP
) ||
798 (texObj
->DriverData
!= NULL
) );
802 static void radeonDeleteTexture( GLcontext
*ctx
,
803 struct gl_texture_object
*texObj
)
805 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
806 driTextureObject
* t
= (driTextureObject
*) texObj
->DriverData
;
808 if ( RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
809 fprintf( stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
, (void *)texObj
,
810 _mesa_lookup_enum_by_nr( texObj
->Target
) );
815 RADEON_FIREVERTICES( rmesa
);
818 driDestroyTextureObject( t
);
821 /* Free mipmap images and the texture object itself */
822 _mesa_delete_texture_object(ctx
, texObj
);
826 * - Same GEN_MODE for all active bits
827 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
828 * - STRQ presumably all supported (matrix means incoming R values
829 * can end up in STQ, this has implications for vertex support,
830 * presumably ok if maos is used, though?)
832 * Basically impossible to do this on the fly - just collect some
833 * basic info & do the checks from ValidateState().
835 static void radeonTexGen( GLcontext
*ctx
,
838 const GLfloat
*params
)
840 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
841 GLuint unit
= ctx
->Texture
.CurrentUnit
;
842 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
846 * Allocate a new texture object.
847 * Called via ctx->Driver.NewTextureObject.
848 * Note: we could use containment here to 'derive' the driver-specific
849 * texture object from the core mesa gl_texture_object. Not done at this time.
851 static struct gl_texture_object
*
852 radeonNewTextureObject( GLcontext
*ctx
, GLuint name
, GLenum target
)
854 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
855 struct gl_texture_object
*obj
;
856 obj
= _mesa_new_texture_object(ctx
, name
, target
);
859 obj
->MaxAnisotropy
= rmesa
->initialMaxAnisotropy
;
860 radeonAllocTexObj( obj
);
865 void radeonInitTextureFuncs( struct dd_function_table
*functions
)
867 functions
->ChooseTextureFormat
= radeonChooseTextureFormat
;
868 functions
->TexImage1D
= radeonTexImage1D
;
869 functions
->TexImage2D
= radeonTexImage2D
;
870 functions
->TexSubImage1D
= radeonTexSubImage1D
;
871 functions
->TexSubImage2D
= radeonTexSubImage2D
;
873 functions
->NewTextureObject
= radeonNewTextureObject
;
874 functions
->BindTexture
= radeonBindTexture
;
875 functions
->DeleteTexture
= radeonDeleteTexture
;
876 functions
->IsTextureResident
= driIsTextureResident
;
878 functions
->TexEnv
= radeonTexEnv
;
879 functions
->TexParameter
= radeonTexParameter
;
880 functions
->TexGen
= radeonTexGen
;
882 functions
->CompressedTexImage2D
= radeonCompressedTexImage2D
;
883 functions
->CompressedTexSubImage2D
= radeonCompressedTexSubImage2D
;
885 driInitTextureFormats();