2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
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:
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.
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.
31 * Keith Whitwell <keith@tungstengraphics.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"
48 #include "radeon_mipmap_tree.h"
49 #include "r200_context.h"
50 #include "r200_state.h"
51 #include "r200_ioctl.h"
52 #include "r200_swtcl.h"
60 * Set the texture wrap modes.
62 * \param t Texture object whose wrap modes are to be set
63 * \param swrap Wrap mode for the \a s texture coordinate
64 * \param twrap Wrap mode for the \a t texture coordinate
67 static void r200SetTexWrap( radeonTexObjPtr t
, GLenum swrap
, GLenum twrap
, GLenum rwrap
)
69 GLboolean is_clamp
= GL_FALSE
;
70 GLboolean is_clamp_to_border
= GL_FALSE
;
71 struct gl_texture_object
*tObj
= &t
->base
;
73 t
->pp_txfilter
&= ~(R200_CLAMP_S_MASK
| R200_CLAMP_T_MASK
| R200_BORDER_MODE_D3D
);
77 t
->pp_txfilter
|= R200_CLAMP_S_WRAP
;
80 t
->pp_txfilter
|= R200_CLAMP_S_CLAMP_GL
;
83 case GL_CLAMP_TO_EDGE
:
84 t
->pp_txfilter
|= R200_CLAMP_S_CLAMP_LAST
;
86 case GL_CLAMP_TO_BORDER
:
87 t
->pp_txfilter
|= R200_CLAMP_S_CLAMP_GL
;
88 is_clamp_to_border
= GL_TRUE
;
90 case GL_MIRRORED_REPEAT
:
91 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR
;
93 case GL_MIRROR_CLAMP_EXT
:
94 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR_CLAMP_GL
;
97 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
98 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR_CLAMP_LAST
;
100 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
101 t
->pp_txfilter
|= R200_CLAMP_S_MIRROR_CLAMP_GL
;
102 is_clamp_to_border
= GL_TRUE
;
105 _mesa_problem(NULL
, "bad S wrap mode in %s", __FUNCTION__
);
108 if (tObj
->Target
!= GL_TEXTURE_1D
) {
111 t
->pp_txfilter
|= R200_CLAMP_T_WRAP
;
114 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_GL
;
117 case GL_CLAMP_TO_EDGE
:
118 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_LAST
;
120 case GL_CLAMP_TO_BORDER
:
121 t
->pp_txfilter
|= R200_CLAMP_T_CLAMP_GL
;
122 is_clamp_to_border
= GL_TRUE
;
124 case GL_MIRRORED_REPEAT
:
125 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR
;
127 case GL_MIRROR_CLAMP_EXT
:
128 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_GL
;
131 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
132 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_LAST
;
134 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
135 t
->pp_txfilter
|= R200_CLAMP_T_MIRROR_CLAMP_GL
;
136 is_clamp_to_border
= GL_TRUE
;
139 _mesa_problem(NULL
, "bad T wrap mode in %s", __FUNCTION__
);
143 t
->pp_txformat_x
&= ~R200_CLAMP_Q_MASK
;
147 t
->pp_txformat_x
|= R200_CLAMP_Q_WRAP
;
150 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_GL
;
153 case GL_CLAMP_TO_EDGE
:
154 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_LAST
;
156 case GL_CLAMP_TO_BORDER
:
157 t
->pp_txformat_x
|= R200_CLAMP_Q_CLAMP_GL
;
158 is_clamp_to_border
= GL_TRUE
;
160 case GL_MIRRORED_REPEAT
:
161 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR
;
163 case GL_MIRROR_CLAMP_EXT
:
164 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_GL
;
167 case GL_MIRROR_CLAMP_TO_EDGE_EXT
:
168 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_LAST
;
170 case GL_MIRROR_CLAMP_TO_BORDER_EXT
:
171 t
->pp_txformat_x
|= R200_CLAMP_Q_MIRROR_CLAMP_GL
;
172 is_clamp_to_border
= GL_TRUE
;
175 _mesa_problem(NULL
, "bad R wrap mode in %s", __FUNCTION__
);
178 if ( is_clamp_to_border
) {
179 t
->pp_txfilter
|= R200_BORDER_MODE_D3D
;
182 t
->border_fallback
= (is_clamp
&& is_clamp_to_border
);
185 static void r200SetTexMaxAnisotropy( radeonTexObjPtr t
, GLfloat max
)
187 t
->pp_txfilter
&= ~R200_MAX_ANISO_MASK
;
190 t
->pp_txfilter
|= R200_MAX_ANISO_1_TO_1
;
191 } else if ( max
<= 2.0 ) {
192 t
->pp_txfilter
|= R200_MAX_ANISO_2_TO_1
;
193 } else if ( max
<= 4.0 ) {
194 t
->pp_txfilter
|= R200_MAX_ANISO_4_TO_1
;
195 } else if ( max
<= 8.0 ) {
196 t
->pp_txfilter
|= R200_MAX_ANISO_8_TO_1
;
198 t
->pp_txfilter
|= R200_MAX_ANISO_16_TO_1
;
203 * Set the texture magnification and minification modes.
205 * \param t Texture whose filter modes are to be set
206 * \param minf Texture minification mode
207 * \param magf Texture magnification mode
210 static void r200SetTexFilter( radeonTexObjPtr t
, GLenum minf
, GLenum magf
)
212 GLuint anisotropy
= (t
->pp_txfilter
& R200_MAX_ANISO_MASK
);
214 t
->pp_txfilter
&= ~(R200_MIN_FILTER_MASK
| R200_MAG_FILTER_MASK
);
215 t
->pp_txformat_x
&= ~R200_VOLUME_FILTER_MASK
;
217 if ( anisotropy
== R200_MAX_ANISO_1_TO_1
) {
220 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST
;
223 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR
;
225 case GL_NEAREST_MIPMAP_NEAREST
:
226 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST_MIP_NEAREST
;
228 case GL_NEAREST_MIPMAP_LINEAR
:
229 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR_MIP_NEAREST
;
231 case GL_LINEAR_MIPMAP_NEAREST
:
232 t
->pp_txfilter
|= R200_MIN_FILTER_NEAREST_MIP_LINEAR
;
234 case GL_LINEAR_MIPMAP_LINEAR
:
235 t
->pp_txfilter
|= R200_MIN_FILTER_LINEAR_MIP_LINEAR
;
241 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST
;
244 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_LINEAR
;
246 case GL_NEAREST_MIPMAP_NEAREST
:
247 case GL_LINEAR_MIPMAP_NEAREST
:
248 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
;
250 case GL_NEAREST_MIPMAP_LINEAR
:
251 case GL_LINEAR_MIPMAP_LINEAR
:
252 t
->pp_txfilter
|= R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR
;
257 /* Note we don't have 3D mipmaps so only use the mag filter setting
258 * to set the 3D texture filter mode.
262 t
->pp_txfilter
|= R200_MAG_FILTER_NEAREST
;
263 t
->pp_txformat_x
|= R200_VOLUME_FILTER_NEAREST
;
266 t
->pp_txfilter
|= R200_MAG_FILTER_LINEAR
;
267 t
->pp_txformat_x
|= R200_VOLUME_FILTER_LINEAR
;
272 static void r200SetTexBorderColor( radeonTexObjPtr t
, GLubyte c
[4] )
274 t
->pp_border_color
= radeonPackColor( 4, c
[0], c
[1], c
[2], c
[3] );
281 static void r200TexEnv( GLcontext
*ctx
, GLenum target
,
282 GLenum pname
, const GLfloat
*param
)
284 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
285 GLuint unit
= ctx
->Texture
.CurrentUnit
;
286 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
288 if ( R200_DEBUG
& DEBUG_STATE
) {
289 fprintf( stderr
, "%s( %s )\n",
290 __FUNCTION__
, _mesa_lookup_enum_by_nr( pname
) );
293 /* This is incorrect: Need to maintain this data for each of
294 * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch
295 * between them according to _ReallyEnabled.
298 case GL_TEXTURE_ENV_COLOR
: {
301 UNCLAMPED_FLOAT_TO_RGBA_CHAN( c
, texUnit
->EnvColor
);
302 envColor
= radeonPackColor( 4, c
[0], c
[1], c
[2], c
[3] );
303 if ( rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] != envColor
) {
304 R200_STATECHANGE( rmesa
, tf
);
305 rmesa
->hw
.tf
.cmd
[TF_TFACTOR_0
+ unit
] = envColor
;
310 case GL_TEXTURE_LOD_BIAS_EXT
: {
313 const int fixed_one
= 0x8000000;
315 /* The R200's LOD bias is a signed 2's complement value with a
316 * range of -16.0 <= bias < 16.0.
318 * NOTE: Add a small bias to the bias for conform mipsel.c test.
321 min
= driQueryOptionb (&rmesa
->radeon
.optionCache
, "no_neg_lod_bias") ?
323 bias
= CLAMP( bias
, min
, 16.0 );
324 b
= (int)(bias
* fixed_one
) & R200_LOD_BIAS_MASK
;
326 if ( (rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] & R200_LOD_BIAS_MASK
) != b
) {
327 R200_STATECHANGE( rmesa
, tex
[unit
] );
328 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] &= ~R200_LOD_BIAS_MASK
;
329 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT_X
] |= b
;
333 case GL_COORD_REPLACE_ARB
:
334 if (ctx
->Point
.PointSprite
) {
335 R200_STATECHANGE( rmesa
, spr
);
336 if ((GLenum
)param
[0]) {
337 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] |= R200_PS_GEN_TEX_0
<< unit
;
339 rmesa
->hw
.spr
.cmd
[SPR_POINT_SPRITE_CNTL
] &= ~(R200_PS_GEN_TEX_0
<< unit
);
350 * Changes variables and flags for a state update, which will happen at the
351 * next UpdateTextureState
354 static void r200TexParameter( GLcontext
*ctx
, GLenum target
,
355 struct gl_texture_object
*texObj
,
356 GLenum pname
, const GLfloat
*params
)
358 radeonTexObj
* t
= radeon_tex_obj(texObj
);
360 if ( R200_DEBUG
& (DEBUG_STATE
|DEBUG_TEXTURE
) ) {
361 fprintf( stderr
, "%s( %s )\n", __FUNCTION__
,
362 _mesa_lookup_enum_by_nr( pname
) );
366 case GL_TEXTURE_MIN_FILTER
:
367 case GL_TEXTURE_MAG_FILTER
:
368 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
369 r200SetTexMaxAnisotropy( t
, texObj
->MaxAnisotropy
);
370 r200SetTexFilter( t
, texObj
->MinFilter
, texObj
->MagFilter
);
373 case GL_TEXTURE_WRAP_S
:
374 case GL_TEXTURE_WRAP_T
:
375 case GL_TEXTURE_WRAP_R
:
376 r200SetTexWrap( t
, texObj
->WrapS
, texObj
->WrapT
, texObj
->WrapR
);
379 case GL_TEXTURE_BORDER_COLOR
:
380 r200SetTexBorderColor( t
, texObj
->_BorderChan
);
383 case GL_TEXTURE_BASE_LEVEL
:
384 case GL_TEXTURE_MAX_LEVEL
:
385 case GL_TEXTURE_MIN_LOD
:
386 case GL_TEXTURE_MAX_LOD
:
387 /* This isn't the most efficient solution but there doesn't appear to
388 * be a nice alternative. Since there's no LOD clamping,
389 * we just have to rely on loading the right subset of mipmap levels
390 * to simulate a clamped LOD.
392 driSwapOutTextureObject( (driTextureObject
*) t
);
399 /* Mark this texobj as dirty (one bit per tex unit)
401 t
->dirty_state
= R200_TEX_ALL
;
405 static void r200DeleteTexture(GLcontext
* ctx
, struct gl_texture_object
*texObj
)
407 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
408 radeonTexObj
* t
= radeon_tex_obj(texObj
);
410 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
411 fprintf(stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
,
413 _mesa_lookup_enum_by_nr(texObj
->Target
));
418 R200_FIREVERTICES(rmesa
);
419 for ( i
= 0 ; i
< rmesa
->radeon
.glCtx
->Const
.MaxTextureUnits
; i
++ ) {
420 if ( t
== rmesa
->state
.texture
.unit
[i
].texobj
) {
421 rmesa
->state
.texture
.unit
[i
].texobj
= NULL
;
422 rmesa
->hw
.tex
[i
].dirty
= GL_FALSE
;
423 rmesa
->hw
.cube
[i
].dirty
= GL_FALSE
;
429 radeon_miptree_unreference(t
->mt
);
432 _mesa_delete_texture_object(ctx
, texObj
);
436 * - Same GEN_MODE for all active bits
437 * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
438 * - STRQ presumably all supported (matrix means incoming R values
439 * can end up in STQ, this has implications for vertex support,
440 * presumably ok if maos is used, though?)
442 * Basically impossible to do this on the fly - just collect some
443 * basic info & do the checks from ValidateState().
445 static void r200TexGen( GLcontext
*ctx
,
448 const GLfloat
*params
)
450 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
451 GLuint unit
= ctx
->Texture
.CurrentUnit
;
452 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
457 * Allocate a new texture object.
458 * Called via ctx->Driver.NewTextureObject.
459 * Note: this function will be called during context creation to
460 * allocate the default texture objects.
461 * Fixup MaxAnisotropy according to user preference.
463 static struct gl_texture_object
*r200NewTextureObject(GLcontext
* ctx
,
467 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
468 radeonTexObj
* t
= CALLOC_STRUCT(radeon_tex_obj
);
471 if (RADEON_DEBUG
& (DEBUG_STATE
| DEBUG_TEXTURE
)) {
472 fprintf(stderr
, "%s( %p (target = %s) )\n", __FUNCTION__
,
473 t
, _mesa_lookup_enum_by_nr(target
));
476 _mesa_initialize_texture_object(&t
->base
, name
, target
);
477 t
->base
.MaxAnisotropy
= rmesa
->radeon
.initialMaxAnisotropy
;
479 /* Initialize hardware state */
480 r200SetTexWrap( t
, t
->base
.WrapS
, t
->base
.WrapT
, t
->base
.WrapR
);
481 r200SetTexMaxAnisotropy( t
, t
->base
.MaxAnisotropy
);
482 r200SetTexFilter(t
, t
->base
.MinFilter
, t
->base
.MagFilter
);
483 r200SetTexBorderColor(t
, t
->base
._BorderChan
);
490 void r200InitTextureFuncs( struct dd_function_table
*functions
)
492 /* Note: we only plug in the functions we implement in the driver
493 * since _mesa_init_driver_functions() was already called.
495 functions
->ChooseTextureFormat
= radeonChooseTextureFormat
;
496 functions
->TexImage1D
= radeonTexImage1D
;
497 functions
->TexImage2D
= radeonTexImage2D
;
498 #if ENABLE_HW_3D_TEXTURE
499 functions
->TexImage3D
= radeonTexImage3D
;
501 functions
->TexImage3D
= _mesa_store_teximage3d
;
503 functions
->TexSubImage1D
= radeonTexSubImage1D
;
504 functions
->TexSubImage2D
= radeonTexSubImage2D
;
505 #if ENABLE_HW_3D_TEXTURE
506 functions
->TexSubImage3D
= radeonTexSubImage3D
;
508 functions
->TexSubImage3D
= _mesa_store_texsubimage3d
;
510 functions
->NewTextureObject
= r200NewTextureObject
;
511 // functions->BindTexture = r200BindTexture;
512 functions
->DeleteTexture
= r200DeleteTexture
;
513 functions
->IsTextureResident
= driIsTextureResident
;
515 functions
->TexEnv
= r200TexEnv
;
516 functions
->TexParameter
= r200TexParameter
;
517 functions
->TexGen
= r200TexGen
;
519 functions
->CompressedTexImage2D
= radeonCompressedTexImage2D
;
520 functions
->CompressedTexSubImage2D
= radeonCompressedTexSubImage2D
;
522 functions
->GenerateMipmap
= radeon_generate_mipmap
;
524 functions
->NewTextureImage
= radeonNewTextureImage
;
525 functions
->FreeTexImageData
= radeonFreeTexImageData
;
526 functions
->MapTexture
= radeonMapTexture
;
527 functions
->UnmapTexture
= radeonUnmapTexture
;
529 driInitTextureFormats();