1 /**************************************************************************
3 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4 VA Linux Systems Inc., Fremont, California.
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.
28 **************************************************************************/
32 * Kevin E. Martin <martin@valinux.com>
33 * Gareth Hughes <gareth@valinux.com>
36 #include "main/glheader.h"
37 #include "main/imports.h"
38 #include "main/context.h"
39 #include "main/macros.h"
40 #include "main/teximage.h"
41 #include "main/texstate.h"
42 #include "main/texobj.h"
43 #include "main/enums.h"
44 #include "main/samplerobj.h"
46 #include "radeon_context.h"
47 #include "radeon_mipmap_tree.h"
48 #include "radeon_state.h"
49 #include "radeon_ioctl.h"
50 #include "radeon_swtcl.h"
51 #include "radeon_tex.h"
52 #include "radeon_tcl.h"
55 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
56 && (tx_table[f].format != 0xffffffff) )
58 /* ================================================================
59 * Texture combine functions
62 /* GL_ARB_texture_env_combine support
65 /* The color tables have combine functions for GL_SRC_COLOR,
66 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
68 static GLuint radeon_texture_color
[][RADEON_MAX_TEXTURE_UNITS
] =
71 RADEON_COLOR_ARG_A_T0_COLOR
,
72 RADEON_COLOR_ARG_A_T1_COLOR
,
73 RADEON_COLOR_ARG_A_T2_COLOR
76 RADEON_COLOR_ARG_A_T0_COLOR
| RADEON_COMP_ARG_A
,
77 RADEON_COLOR_ARG_A_T1_COLOR
| RADEON_COMP_ARG_A
,
78 RADEON_COLOR_ARG_A_T2_COLOR
| RADEON_COMP_ARG_A
81 RADEON_COLOR_ARG_A_T0_ALPHA
,
82 RADEON_COLOR_ARG_A_T1_ALPHA
,
83 RADEON_COLOR_ARG_A_T2_ALPHA
86 RADEON_COLOR_ARG_A_T0_ALPHA
| RADEON_COMP_ARG_A
,
87 RADEON_COLOR_ARG_A_T1_ALPHA
| RADEON_COMP_ARG_A
,
88 RADEON_COLOR_ARG_A_T2_ALPHA
| RADEON_COMP_ARG_A
92 static GLuint radeon_tfactor_color
[] =
94 RADEON_COLOR_ARG_A_TFACTOR_COLOR
,
95 RADEON_COLOR_ARG_A_TFACTOR_COLOR
| RADEON_COMP_ARG_A
,
96 RADEON_COLOR_ARG_A_TFACTOR_ALPHA
,
97 RADEON_COLOR_ARG_A_TFACTOR_ALPHA
| RADEON_COMP_ARG_A
100 static GLuint radeon_primary_color
[] =
102 RADEON_COLOR_ARG_A_DIFFUSE_COLOR
,
103 RADEON_COLOR_ARG_A_DIFFUSE_COLOR
| RADEON_COMP_ARG_A
,
104 RADEON_COLOR_ARG_A_DIFFUSE_ALPHA
,
105 RADEON_COLOR_ARG_A_DIFFUSE_ALPHA
| RADEON_COMP_ARG_A
108 static GLuint radeon_previous_color
[] =
110 RADEON_COLOR_ARG_A_CURRENT_COLOR
,
111 RADEON_COLOR_ARG_A_CURRENT_COLOR
| RADEON_COMP_ARG_A
,
112 RADEON_COLOR_ARG_A_CURRENT_ALPHA
,
113 RADEON_COLOR_ARG_A_CURRENT_ALPHA
| RADEON_COMP_ARG_A
116 /* GL_ZERO table - indices 0-3
117 * GL_ONE table - indices 1-4
119 static GLuint radeon_zero_color
[] =
121 RADEON_COLOR_ARG_A_ZERO
,
122 RADEON_COLOR_ARG_A_ZERO
| RADEON_COMP_ARG_A
,
123 RADEON_COLOR_ARG_A_ZERO
,
124 RADEON_COLOR_ARG_A_ZERO
| RADEON_COMP_ARG_A
,
125 RADEON_COLOR_ARG_A_ZERO
129 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
131 static GLuint radeon_texture_alpha
[][RADEON_MAX_TEXTURE_UNITS
] =
134 RADEON_ALPHA_ARG_A_T0_ALPHA
,
135 RADEON_ALPHA_ARG_A_T1_ALPHA
,
136 RADEON_ALPHA_ARG_A_T2_ALPHA
139 RADEON_ALPHA_ARG_A_T0_ALPHA
| RADEON_COMP_ARG_A
,
140 RADEON_ALPHA_ARG_A_T1_ALPHA
| RADEON_COMP_ARG_A
,
141 RADEON_ALPHA_ARG_A_T2_ALPHA
| RADEON_COMP_ARG_A
145 static GLuint radeon_tfactor_alpha
[] =
147 RADEON_ALPHA_ARG_A_TFACTOR_ALPHA
,
148 RADEON_ALPHA_ARG_A_TFACTOR_ALPHA
| RADEON_COMP_ARG_A
151 static GLuint radeon_primary_alpha
[] =
153 RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA
,
154 RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA
| RADEON_COMP_ARG_A
157 static GLuint radeon_previous_alpha
[] =
159 RADEON_ALPHA_ARG_A_CURRENT_ALPHA
,
160 RADEON_ALPHA_ARG_A_CURRENT_ALPHA
| RADEON_COMP_ARG_A
163 /* GL_ZERO table - indices 0-1
164 * GL_ONE table - indices 1-2
166 static GLuint radeon_zero_alpha
[] =
168 RADEON_ALPHA_ARG_A_ZERO
,
169 RADEON_ALPHA_ARG_A_ZERO
| RADEON_COMP_ARG_A
,
170 RADEON_ALPHA_ARG_A_ZERO
174 /* Extract the arg from slot A, shift it into the correct argument slot
175 * and set the corresponding complement bit.
177 #define RADEON_COLOR_ARG( n, arg ) \
180 ((color_arg[n] & RADEON_COLOR_ARG_MASK) \
181 << RADEON_COLOR_ARG_##arg##_SHIFT); \
183 ((color_arg[n] >> RADEON_COMP_ARG_SHIFT) \
184 << RADEON_COMP_ARG_##arg##_SHIFT); \
187 #define RADEON_ALPHA_ARG( n, arg ) \
190 ((alpha_arg[n] & RADEON_ALPHA_ARG_MASK) \
191 << RADEON_ALPHA_ARG_##arg##_SHIFT); \
193 ((alpha_arg[n] >> RADEON_COMP_ARG_SHIFT) \
194 << RADEON_COMP_ARG_##arg##_SHIFT); \
198 /* ================================================================
199 * Texture unit state management
202 static GLboolean
radeonUpdateTextureEnv( struct gl_context
*ctx
, int unit
)
204 r100ContextPtr rmesa
= R100_CONTEXT(ctx
);
205 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
206 GLuint color_combine
, alpha_combine
;
207 const GLuint color_combine0
= RADEON_COLOR_ARG_A_ZERO
| RADEON_COLOR_ARG_B_ZERO
208 | RADEON_COLOR_ARG_C_CURRENT_COLOR
| RADEON_BLEND_CTL_ADD
209 | RADEON_SCALE_1X
| RADEON_CLAMP_TX
;
210 const GLuint alpha_combine0
= RADEON_ALPHA_ARG_A_ZERO
| RADEON_ALPHA_ARG_B_ZERO
211 | RADEON_ALPHA_ARG_C_CURRENT_ALPHA
| RADEON_BLEND_CTL_ADD
212 | RADEON_SCALE_1X
| RADEON_CLAMP_TX
;
215 if ( RADEON_DEBUG
& RADEON_TEXTURE
) {
216 fprintf( stderr
, "%s( %p, %d )\n", __func__
, (void *)ctx
, unit
);
219 /* Set the texture environment state. Isn't this nice and clean?
220 * The chip will automagically set the texture alpha to 0xff when
221 * the texture format does not include an alpha component. This
222 * reduces the amount of special-casing we have to do, alpha-only
223 * textures being a notable exception. Doesn't work for luminance
224 * textures realized with I8 and ALPHA_IN_MAP not set neither (on r100).
226 /* Don't cache these results.
228 rmesa
->state
.texture
.unit
[unit
].format
= 0;
229 rmesa
->state
.texture
.unit
[unit
].envMode
= 0;
231 if ( !texUnit
->_Current
) {
232 color_combine
= color_combine0
;
233 alpha_combine
= alpha_combine0
;
236 GLuint color_arg
[3], alpha_arg
[3];
238 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
239 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
240 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
241 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
245 * Extract the color and alpha combine function arguments.
247 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
248 const GLint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
] - GL_SRC_COLOR
;
249 const GLuint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
254 if (texUnit
->_Current
->Image
[0][0]->_BaseFormat
== GL_ALPHA
)
255 color_arg
[i
] = radeon_zero_color
[op
];
257 color_arg
[i
] = radeon_texture_color
[op
][unit
];
260 color_arg
[i
] = radeon_tfactor_color
[op
];
262 case GL_PRIMARY_COLOR
:
263 color_arg
[i
] = radeon_primary_color
[op
];
266 color_arg
[i
] = radeon_previous_color
[op
];
269 color_arg
[i
] = radeon_zero_color
[op
];
272 color_arg
[i
] = radeon_zero_color
[op
+1];
277 GLuint txunit
= srcRGBi
- GL_TEXTURE0
;
278 if (ctx
->Texture
.Unit
[txunit
]._Current
->Image
[0][0]->_BaseFormat
== GL_ALPHA
)
279 color_arg
[i
] = radeon_zero_color
[op
];
281 /* implement ogl 1.4/1.5 core spec here, not specification of
282 * GL_ARB_texture_env_crossbar (which would require disabling blending
283 * instead of undefined results when referencing not enabled texunit) */
284 color_arg
[i
] = radeon_texture_color
[op
][txunit
];
292 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
293 const GLint op
= texUnit
->_CurrentCombine
->OperandA
[i
] - GL_SRC_ALPHA
;
294 const GLuint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
299 if (texUnit
->_Current
->Image
[0][0]->_BaseFormat
== GL_LUMINANCE
)
300 alpha_arg
[i
] = radeon_zero_alpha
[op
+1];
302 alpha_arg
[i
] = radeon_texture_alpha
[op
][unit
];
305 alpha_arg
[i
] = radeon_tfactor_alpha
[op
];
307 case GL_PRIMARY_COLOR
:
308 alpha_arg
[i
] = radeon_primary_alpha
[op
];
311 alpha_arg
[i
] = radeon_previous_alpha
[op
];
314 alpha_arg
[i
] = radeon_zero_alpha
[op
];
317 alpha_arg
[i
] = radeon_zero_alpha
[op
+1];
322 GLuint txunit
= srcAi
- GL_TEXTURE0
;
323 if (ctx
->Texture
.Unit
[txunit
]._Current
->Image
[0][0]->_BaseFormat
== GL_LUMINANCE
)
324 alpha_arg
[i
] = radeon_zero_alpha
[op
+1];
326 alpha_arg
[i
] = radeon_texture_alpha
[op
][txunit
];
335 * Build up the color and alpha combine functions.
337 switch ( texUnit
->_CurrentCombine
->ModeRGB
) {
339 color_combine
= (RADEON_COLOR_ARG_A_ZERO
|
340 RADEON_COLOR_ARG_B_ZERO
|
341 RADEON_BLEND_CTL_ADD
|
343 RADEON_COLOR_ARG( 0, C
);
346 color_combine
= (RADEON_COLOR_ARG_C_ZERO
|
347 RADEON_BLEND_CTL_ADD
|
349 RADEON_COLOR_ARG( 0, A
);
350 RADEON_COLOR_ARG( 1, B
);
353 color_combine
= (RADEON_COLOR_ARG_B_ZERO
|
355 RADEON_BLEND_CTL_ADD
|
357 RADEON_COLOR_ARG( 0, A
);
358 RADEON_COLOR_ARG( 1, C
);
361 color_combine
= (RADEON_COLOR_ARG_B_ZERO
|
363 RADEON_BLEND_CTL_ADDSIGNED
|
365 RADEON_COLOR_ARG( 0, A
);
366 RADEON_COLOR_ARG( 1, C
);
369 color_combine
= (RADEON_COLOR_ARG_B_ZERO
|
371 RADEON_BLEND_CTL_SUBTRACT
|
373 RADEON_COLOR_ARG( 0, A
);
374 RADEON_COLOR_ARG( 1, C
);
377 color_combine
= (RADEON_BLEND_CTL_BLEND
|
379 RADEON_COLOR_ARG( 0, B
);
380 RADEON_COLOR_ARG( 1, A
);
381 RADEON_COLOR_ARG( 2, C
);
384 case GL_DOT3_RGB_EXT
:
385 case GL_DOT3_RGBA_EXT
:
386 /* The EXT version of the DOT3 extension does not support the
387 * scale factor, but the ARB version (and the version in OpenGL
395 /* The R100 / RV200 only support a 1X multiplier in hardware
398 if ( RGBshift
!= (RADEON_SCALE_1X
>> RADEON_SCALE_SHIFT
) ) {
403 if ( (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
404 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ) {
405 /* is it necessary to set this or will it be ignored anyway? */
409 color_combine
= (RADEON_COLOR_ARG_C_ZERO
|
410 RADEON_BLEND_CTL_DOT3
|
412 RADEON_COLOR_ARG( 0, A
);
413 RADEON_COLOR_ARG( 1, B
);
416 case GL_MODULATE_ADD_ATI
:
417 color_combine
= (RADEON_BLEND_CTL_ADD
|
419 RADEON_COLOR_ARG( 0, A
);
420 RADEON_COLOR_ARG( 1, C
);
421 RADEON_COLOR_ARG( 2, B
);
423 case GL_MODULATE_SIGNED_ADD_ATI
:
424 color_combine
= (RADEON_BLEND_CTL_ADDSIGNED
|
426 RADEON_COLOR_ARG( 0, A
);
427 RADEON_COLOR_ARG( 1, C
);
428 RADEON_COLOR_ARG( 2, B
);
430 case GL_MODULATE_SUBTRACT_ATI
:
431 color_combine
= (RADEON_BLEND_CTL_SUBTRACT
|
433 RADEON_COLOR_ARG( 0, A
);
434 RADEON_COLOR_ARG( 1, C
);
435 RADEON_COLOR_ARG( 2, B
);
441 switch ( texUnit
->_CurrentCombine
->ModeA
) {
443 alpha_combine
= (RADEON_ALPHA_ARG_A_ZERO
|
444 RADEON_ALPHA_ARG_B_ZERO
|
445 RADEON_BLEND_CTL_ADD
|
447 RADEON_ALPHA_ARG( 0, C
);
450 alpha_combine
= (RADEON_ALPHA_ARG_C_ZERO
|
451 RADEON_BLEND_CTL_ADD
|
453 RADEON_ALPHA_ARG( 0, A
);
454 RADEON_ALPHA_ARG( 1, B
);
457 alpha_combine
= (RADEON_ALPHA_ARG_B_ZERO
|
459 RADEON_BLEND_CTL_ADD
|
461 RADEON_ALPHA_ARG( 0, A
);
462 RADEON_ALPHA_ARG( 1, C
);
465 alpha_combine
= (RADEON_ALPHA_ARG_B_ZERO
|
467 RADEON_BLEND_CTL_ADDSIGNED
|
469 RADEON_ALPHA_ARG( 0, A
);
470 RADEON_ALPHA_ARG( 1, C
);
473 alpha_combine
= (RADEON_COLOR_ARG_B_ZERO
|
475 RADEON_BLEND_CTL_SUBTRACT
|
477 RADEON_ALPHA_ARG( 0, A
);
478 RADEON_ALPHA_ARG( 1, C
);
481 alpha_combine
= (RADEON_BLEND_CTL_BLEND
|
483 RADEON_ALPHA_ARG( 0, B
);
484 RADEON_ALPHA_ARG( 1, A
);
485 RADEON_ALPHA_ARG( 2, C
);
488 case GL_MODULATE_ADD_ATI
:
489 alpha_combine
= (RADEON_BLEND_CTL_ADD
|
491 RADEON_ALPHA_ARG( 0, A
);
492 RADEON_ALPHA_ARG( 1, C
);
493 RADEON_ALPHA_ARG( 2, B
);
495 case GL_MODULATE_SIGNED_ADD_ATI
:
496 alpha_combine
= (RADEON_BLEND_CTL_ADDSIGNED
|
498 RADEON_ALPHA_ARG( 0, A
);
499 RADEON_ALPHA_ARG( 1, C
);
500 RADEON_ALPHA_ARG( 2, B
);
502 case GL_MODULATE_SUBTRACT_ATI
:
503 alpha_combine
= (RADEON_BLEND_CTL_SUBTRACT
|
505 RADEON_ALPHA_ARG( 0, A
);
506 RADEON_ALPHA_ARG( 1, C
);
507 RADEON_ALPHA_ARG( 2, B
);
513 if ( (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGB_EXT
)
514 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGB
) ) {
515 alpha_combine
|= RADEON_DOT_ALPHA_DONT_REPLICATE
;
519 * Apply the scale factor.
521 color_combine
|= (RGBshift
<< RADEON_SCALE_SHIFT
);
522 alpha_combine
|= (Ashift
<< RADEON_SCALE_SHIFT
);
528 if ( rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXCBLEND
] != color_combine
||
529 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXABLEND
] != alpha_combine
) {
530 RADEON_STATECHANGE( rmesa
, tex
[unit
] );
531 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXCBLEND
] = color_combine
;
532 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXABLEND
] = alpha_combine
;
538 void radeonSetTexBuffer2(__DRIcontext
*pDRICtx
, GLint target
, GLint texture_format
,
539 __DRIdrawable
*dPriv
)
541 struct gl_texture_object
*texObj
;
542 struct gl_texture_image
*texImage
;
543 struct radeon_renderbuffer
*rb
;
544 radeon_texture_image
*rImage
;
545 radeonContextPtr radeon
;
546 struct radeon_framebuffer
*rfb
;
549 mesa_format texFormat
;
551 radeon
= pDRICtx
->driverPrivate
;
553 rfb
= dPriv
->driverPrivate
;
554 texObj
= _mesa_get_current_tex_object(&radeon
->glCtx
, target
);
555 texImage
= _mesa_get_tex_image(&radeon
->glCtx
, texObj
, target
, 0);
557 rImage
= get_radeon_texture_image(texImage
);
558 t
= radeon_tex_obj(texObj
);
563 radeon_update_renderbuffers(pDRICtx
, dPriv
, GL_TRUE
);
564 rb
= rfb
->color_rb
[0];
565 if (rb
->bo
== NULL
) {
566 /* Failed to BO for the buffer */
570 _mesa_lock_texture(&radeon
->glCtx
, texObj
);
572 radeon_bo_unref(t
->bo
);
576 radeon_bo_unref(rImage
->bo
);
580 radeon_miptree_unreference(&t
->mt
);
581 radeon_miptree_unreference(&rImage
->mt
);
584 radeon_bo_ref(rImage
->bo
);
586 radeon_bo_ref(t
->bo
);
588 t
->image_override
= GL_TRUE
;
589 t
->override_offset
= 0;
592 if (texture_format
== __DRI_TEXTURE_FORMAT_RGB
) {
593 t
->pp_txformat
= tx_table
[MESA_FORMAT_BGR_UNORM8
].format
;
594 texFormat
= MESA_FORMAT_BGR_UNORM8
;
597 t
->pp_txformat
= tx_table
[MESA_FORMAT_B8G8R8A8_UNORM
].format
;
598 texFormat
= MESA_FORMAT_B8G8R8A8_UNORM
;
600 t
->pp_txfilter
|= tx_table
[MESA_FORMAT_B8G8R8A8_UNORM
].filter
;
604 texFormat
= MESA_FORMAT_BGR_UNORM8
;
605 t
->pp_txformat
= tx_table
[MESA_FORMAT_BGR_UNORM8
].format
;
606 t
->pp_txfilter
|= tx_table
[MESA_FORMAT_BGR_UNORM8
].filter
;
609 texFormat
= MESA_FORMAT_B5G6R5_UNORM
;
610 t
->pp_txformat
= tx_table
[MESA_FORMAT_B5G6R5_UNORM
].format
;
611 t
->pp_txfilter
|= tx_table
[MESA_FORMAT_B5G6R5_UNORM
].filter
;
615 _mesa_init_teximage_fields(&radeon
->glCtx
, texImage
,
616 rb
->base
.Base
.Width
, rb
->base
.Base
.Height
,
619 rImage
->base
.RowStride
= rb
->pitch
/ rb
->cpp
;
621 t
->pp_txpitch
&= (1 << 13) -1;
622 pitch_val
= rb
->pitch
;
624 t
->pp_txsize
= ((rb
->base
.Base
.Width
- 1) << RADEON_TEX_USIZE_SHIFT
)
625 | ((rb
->base
.Base
.Height
- 1) << RADEON_TEX_VSIZE_SHIFT
);
626 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
627 t
->pp_txformat
|= RADEON_TXFORMAT_NON_POWER2
;
628 t
->pp_txpitch
= pitch_val
;
631 t
->pp_txformat
&= ~(RADEON_TXFORMAT_WIDTH_MASK
|
632 RADEON_TXFORMAT_HEIGHT_MASK
|
633 RADEON_TXFORMAT_CUBIC_MAP_ENABLE
|
634 RADEON_TXFORMAT_F5_WIDTH_MASK
|
635 RADEON_TXFORMAT_F5_HEIGHT_MASK
);
636 t
->pp_txformat
|= ((texImage
->WidthLog2
<< RADEON_TXFORMAT_WIDTH_SHIFT
) |
637 (texImage
->HeightLog2
<< RADEON_TXFORMAT_HEIGHT_SHIFT
));
639 t
->validated
= GL_TRUE
;
640 _mesa_unlock_texture(&radeon
->glCtx
, texObj
);
645 void radeonSetTexBuffer(__DRIcontext
*pDRICtx
, GLint target
, __DRIdrawable
*dPriv
)
647 radeonSetTexBuffer2(pDRICtx
, target
, __DRI_TEXTURE_FORMAT_RGBA
, dPriv
);
651 #define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK | \
652 RADEON_MIN_FILTER_MASK | \
653 RADEON_MAG_FILTER_MASK | \
654 RADEON_MAX_ANISO_MASK | \
655 RADEON_YUV_TO_RGB | \
656 RADEON_YUV_TEMPERATURE_MASK | \
657 RADEON_CLAMP_S_MASK | \
658 RADEON_CLAMP_T_MASK | \
659 RADEON_BORDER_MODE_D3D )
661 #define TEXOBJ_TXFORMAT_MASK (RADEON_TXFORMAT_WIDTH_MASK | \
662 RADEON_TXFORMAT_HEIGHT_MASK | \
663 RADEON_TXFORMAT_FORMAT_MASK | \
664 RADEON_TXFORMAT_F5_WIDTH_MASK | \
665 RADEON_TXFORMAT_F5_HEIGHT_MASK | \
666 RADEON_TXFORMAT_ALPHA_IN_MAP | \
667 RADEON_TXFORMAT_CUBIC_MAP_ENABLE | \
668 RADEON_TXFORMAT_NON_POWER2)
671 static void disable_tex_obj_state( r100ContextPtr rmesa
,
674 RADEON_STATECHANGE( rmesa
, tex
[unit
] );
676 RADEON_STATECHANGE( rmesa
, tcl
);
677 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] &= ~(RADEON_ST_BIT(unit
) |
680 if (rmesa
->radeon
.TclFallback
& (RADEON_TCL_FALLBACK_TEXGEN_0
<<unit
)) {
681 TCL_FALLBACK( &rmesa
->radeon
.glCtx
, (RADEON_TCL_FALLBACK_TEXGEN_0
<<unit
), GL_FALSE
);
682 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
685 if (rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] & RADEON_TXFORMAT_CUBIC_MAP_ENABLE
) {
686 /* this seems to be a genuine (r100 only?) hw bug. Need to remove the
687 cubic_map bit on unit 2 when the unit is disabled, otherwise every
688 2nd (2d) mipmap on unit 0 will be broken (may not be needed for other
689 units, better be safe than sorry though).*/
690 RADEON_STATECHANGE( rmesa
, tex
[unit
] );
691 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXFORMAT
] &= ~RADEON_TXFORMAT_CUBIC_MAP_ENABLE
;
695 GLuint inputshift
= RADEON_TEXGEN_0_INPUT_SHIFT
+ unit
*4;
696 GLuint tmp
= rmesa
->TexGenEnabled
;
698 rmesa
->TexGenEnabled
&= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
699 rmesa
->TexGenEnabled
&= ~(RADEON_TEXMAT_0_ENABLE
<<unit
);
700 rmesa
->TexGenEnabled
&= ~(RADEON_TEXGEN_INPUT_MASK
<<inputshift
);
701 rmesa
->TexGenNeedNormals
[unit
] = 0;
702 rmesa
->TexGenEnabled
|=
703 (RADEON_TEXGEN_INPUT_TEXCOORD_0
+unit
) << inputshift
;
705 if (tmp
!= rmesa
->TexGenEnabled
) {
706 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
707 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE_MATRIX
;
712 static void import_tex_obj_state( r100ContextPtr rmesa
,
714 radeonTexObjPtr texobj
)
716 /* do not use RADEON_DB_STATE to avoid stale texture caches */
717 uint32_t *cmd
= &rmesa
->hw
.tex
[unit
].cmd
[TEX_CMD_0
];
718 GLuint se_coord_fmt
= rmesa
->hw
.set
.cmd
[SET_SE_COORDFMT
];
720 RADEON_STATECHANGE( rmesa
, tex
[unit
] );
722 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
723 cmd
[TEX_PP_TXFILTER
] |= texobj
->pp_txfilter
& TEXOBJ_TXFILTER_MASK
;
724 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
725 cmd
[TEX_PP_TXFORMAT
] |= texobj
->pp_txformat
& TEXOBJ_TXFORMAT_MASK
;
726 cmd
[TEX_PP_BORDER_COLOR
] = texobj
->pp_border_color
;
728 if (texobj
->pp_txformat
& RADEON_TXFORMAT_NON_POWER2
) {
729 uint32_t *txr_cmd
= &rmesa
->hw
.txr
[unit
].cmd
[TXR_CMD_0
];
730 txr_cmd
[TXR_PP_TEX_SIZE
] = texobj
->pp_txsize
; /* NPOT only! */
731 txr_cmd
[TXR_PP_TEX_PITCH
] = texobj
->pp_txpitch
; /* NPOT only! */
732 RADEON_STATECHANGE( rmesa
, txr
[unit
] );
735 if (texobj
->base
.Target
== GL_TEXTURE_RECTANGLE_NV
) {
736 se_coord_fmt
|= RADEON_VTX_ST0_NONPARAMETRIC
<< unit
;
739 se_coord_fmt
&= ~(RADEON_VTX_ST0_NONPARAMETRIC
<< unit
);
741 if (texobj
->base
.Target
== GL_TEXTURE_CUBE_MAP
) {
742 uint32_t *cube_cmd
= &rmesa
->hw
.cube
[unit
].cmd
[CUBE_CMD_0
];
744 RADEON_STATECHANGE( rmesa
, cube
[unit
] );
745 cube_cmd
[CUBE_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
746 /* state filled out in the cube_emit */
750 if (se_coord_fmt
!= rmesa
->hw
.set
.cmd
[SET_SE_COORDFMT
]) {
751 RADEON_STATECHANGE( rmesa
, set
);
752 rmesa
->hw
.set
.cmd
[SET_SE_COORDFMT
] = se_coord_fmt
;
755 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE_MATRIX
;
759 static void set_texgen_matrix( r100ContextPtr rmesa
,
761 const GLfloat
*s_plane
,
762 const GLfloat
*t_plane
,
763 const GLfloat
*r_plane
,
764 const GLfloat
*q_plane
)
766 rmesa
->TexGenMatrix
[unit
].m
[0] = s_plane
[0];
767 rmesa
->TexGenMatrix
[unit
].m
[4] = s_plane
[1];
768 rmesa
->TexGenMatrix
[unit
].m
[8] = s_plane
[2];
769 rmesa
->TexGenMatrix
[unit
].m
[12] = s_plane
[3];
771 rmesa
->TexGenMatrix
[unit
].m
[1] = t_plane
[0];
772 rmesa
->TexGenMatrix
[unit
].m
[5] = t_plane
[1];
773 rmesa
->TexGenMatrix
[unit
].m
[9] = t_plane
[2];
774 rmesa
->TexGenMatrix
[unit
].m
[13] = t_plane
[3];
776 rmesa
->TexGenMatrix
[unit
].m
[2] = r_plane
[0];
777 rmesa
->TexGenMatrix
[unit
].m
[6] = r_plane
[1];
778 rmesa
->TexGenMatrix
[unit
].m
[10] = r_plane
[2];
779 rmesa
->TexGenMatrix
[unit
].m
[14] = r_plane
[3];
781 rmesa
->TexGenMatrix
[unit
].m
[3] = q_plane
[0];
782 rmesa
->TexGenMatrix
[unit
].m
[7] = q_plane
[1];
783 rmesa
->TexGenMatrix
[unit
].m
[11] = q_plane
[2];
784 rmesa
->TexGenMatrix
[unit
].m
[15] = q_plane
[3];
786 rmesa
->TexGenEnabled
|= RADEON_TEXMAT_0_ENABLE
<< unit
;
787 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE_MATRIX
;
790 /* Returns GL_FALSE if fallback required.
792 static GLboolean
radeon_validate_texgen( struct gl_context
*ctx
, GLuint unit
)
794 r100ContextPtr rmesa
= R100_CONTEXT(ctx
);
795 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
796 GLuint inputshift
= RADEON_TEXGEN_0_INPUT_SHIFT
+ unit
*4;
797 GLuint tmp
= rmesa
->TexGenEnabled
;
798 static const GLfloat reflect
[16] = {
804 rmesa
->TexGenEnabled
&= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE
<< unit
);
805 rmesa
->TexGenEnabled
&= ~(RADEON_TEXMAT_0_ENABLE
<< unit
);
806 rmesa
->TexGenEnabled
&= ~(RADEON_TEXGEN_INPUT_MASK
<< inputshift
);
807 rmesa
->TexGenNeedNormals
[unit
] = 0;
809 if ((texUnit
->TexGenEnabled
& (S_BIT
|T_BIT
|R_BIT
|Q_BIT
)) == 0) {
810 /* Disabled, no fallback:
812 rmesa
->TexGenEnabled
|=
813 (RADEON_TEXGEN_INPUT_TEXCOORD_0
+ unit
) << inputshift
;
816 /* the r100 cannot do texgen for some coords and not for others
817 * we do not detect such cases (certainly can't do it here) and just
818 * ASSUME that when S and T are texgen enabled we do not need other
819 * non-texgen enabled coords, no matter if the R and Q bits are texgen
820 * enabled. Still check for mixed mode texgen for all coords.
822 else if ( (texUnit
->TexGenEnabled
& S_BIT
) &&
823 (texUnit
->TexGenEnabled
& T_BIT
) &&
824 (texUnit
->GenS
.Mode
== texUnit
->GenT
.Mode
) ) {
825 if ( ((texUnit
->TexGenEnabled
& R_BIT
) &&
826 (texUnit
->GenS
.Mode
!= texUnit
->GenR
.Mode
)) ||
827 ((texUnit
->TexGenEnabled
& Q_BIT
) &&
828 (texUnit
->GenS
.Mode
!= texUnit
->GenQ
.Mode
)) ) {
829 /* Mixed modes, fallback:
831 if (RADEON_DEBUG
& RADEON_FALLBACKS
)
832 fprintf(stderr
, "fallback mixed texgen\n");
835 rmesa
->TexGenEnabled
|= RADEON_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
838 /* some texgen mode not including both S and T bits */
839 if (RADEON_DEBUG
& RADEON_FALLBACKS
)
840 fprintf(stderr
, "fallback mixed texgen/nontexgen\n");
844 if ((texUnit
->TexGenEnabled
& (R_BIT
| Q_BIT
)) != 0) {
845 /* need this here for vtxfmt presumably. Argh we need to set
846 this from way too many places, would be much easier if we could leave
847 tcl q coord always enabled as on r200) */
848 RADEON_STATECHANGE( rmesa
, tcl
);
849 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_Q_BIT(unit
);
852 switch (texUnit
->GenS
.Mode
) {
853 case GL_OBJECT_LINEAR
:
854 rmesa
->TexGenEnabled
|= RADEON_TEXGEN_INPUT_OBJ
<< inputshift
;
855 set_texgen_matrix( rmesa
, unit
,
856 texUnit
->GenS
.ObjectPlane
,
857 texUnit
->GenT
.ObjectPlane
,
858 texUnit
->GenR
.ObjectPlane
,
859 texUnit
->GenQ
.ObjectPlane
);
863 rmesa
->TexGenEnabled
|= RADEON_TEXGEN_INPUT_EYE
<< inputshift
;
864 set_texgen_matrix( rmesa
, unit
,
865 texUnit
->GenS
.EyePlane
,
866 texUnit
->GenT
.EyePlane
,
867 texUnit
->GenR
.EyePlane
,
868 texUnit
->GenQ
.EyePlane
);
871 case GL_REFLECTION_MAP_NV
:
872 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
873 rmesa
->TexGenEnabled
|= RADEON_TEXGEN_INPUT_EYE_REFLECT
<< inputshift
;
874 /* TODO: unknown if this is needed/correct */
875 set_texgen_matrix( rmesa
, unit
, reflect
, reflect
+ 4,
876 reflect
+ 8, reflect
+ 12 );
879 case GL_NORMAL_MAP_NV
:
880 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
881 rmesa
->TexGenEnabled
|= RADEON_TEXGEN_INPUT_EYE_NORMAL
<< inputshift
;
885 /* the mode which everyone uses :-( */
887 /* Unsupported mode, fallback:
889 if (RADEON_DEBUG
& RADEON_FALLBACKS
)
890 fprintf(stderr
, "fallback GL_SPHERE_MAP\n");
894 if (tmp
!= rmesa
->TexGenEnabled
) {
895 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE_MATRIX
;
902 * Compute the cached hardware register values for the given texture object.
904 * \param rmesa Context pointer
905 * \param t the r300 texture object
907 static GLboolean
setup_hardware_state(r100ContextPtr rmesa
, radeonTexObj
*t
, int unit
)
909 const struct gl_texture_image
*firstImage
;
910 GLint log2Width
, log2Height
, texelBytes
;
916 firstImage
= t
->base
.Image
[0][t
->minLod
];
918 log2Width
= firstImage
->WidthLog2
;
919 log2Height
= firstImage
->HeightLog2
;
920 texelBytes
= _mesa_get_format_bytes(firstImage
->TexFormat
);
922 if (!t
->image_override
) {
923 if (VALID_FORMAT(firstImage
->TexFormat
)) {
924 const struct tx_table
*table
= tx_table
;
926 t
->pp_txformat
&= ~(RADEON_TXFORMAT_FORMAT_MASK
|
927 RADEON_TXFORMAT_ALPHA_IN_MAP
);
928 t
->pp_txfilter
&= ~RADEON_YUV_TO_RGB
;
930 t
->pp_txformat
|= table
[ firstImage
->TexFormat
].format
;
931 t
->pp_txfilter
|= table
[ firstImage
->TexFormat
].filter
;
933 _mesa_problem(NULL
, "unexpected texture format in %s",
939 t
->pp_txfilter
&= ~RADEON_MAX_MIP_LEVEL_MASK
;
940 t
->pp_txfilter
|= (t
->maxLod
- t
->minLod
) << RADEON_MAX_MIP_LEVEL_SHIFT
;
942 t
->pp_txformat
&= ~(RADEON_TXFORMAT_WIDTH_MASK
|
943 RADEON_TXFORMAT_HEIGHT_MASK
|
944 RADEON_TXFORMAT_CUBIC_MAP_ENABLE
|
945 RADEON_TXFORMAT_F5_WIDTH_MASK
|
946 RADEON_TXFORMAT_F5_HEIGHT_MASK
);
947 t
->pp_txformat
|= ((log2Width
<< RADEON_TXFORMAT_WIDTH_SHIFT
) |
948 (log2Height
<< RADEON_TXFORMAT_HEIGHT_SHIFT
));
952 if (t
->base
.Target
== GL_TEXTURE_CUBE_MAP
) {
953 assert(log2Width
== log2Height
);
954 t
->pp_txformat
|= ((log2Width
<< RADEON_TXFORMAT_F5_WIDTH_SHIFT
) |
955 (log2Height
<< RADEON_TXFORMAT_F5_HEIGHT_SHIFT
) |
956 /* don't think we need this bit, if it exists at all - fglrx does not set it */
957 (RADEON_TXFORMAT_CUBIC_MAP_ENABLE
));
958 t
->pp_cubic_faces
= ((log2Width
<< RADEON_FACE_WIDTH_1_SHIFT
) |
959 (log2Height
<< RADEON_FACE_HEIGHT_1_SHIFT
) |
960 (log2Width
<< RADEON_FACE_WIDTH_2_SHIFT
) |
961 (log2Height
<< RADEON_FACE_HEIGHT_2_SHIFT
) |
962 (log2Width
<< RADEON_FACE_WIDTH_3_SHIFT
) |
963 (log2Height
<< RADEON_FACE_HEIGHT_3_SHIFT
) |
964 (log2Width
<< RADEON_FACE_WIDTH_4_SHIFT
) |
965 (log2Height
<< RADEON_FACE_HEIGHT_4_SHIFT
));
968 t
->pp_txsize
= (((firstImage
->Width
- 1) << RADEON_TEX_USIZE_SHIFT
)
969 | ((firstImage
->Height
- 1) << RADEON_TEX_VSIZE_SHIFT
));
971 if ( !t
->image_override
) {
972 if (_mesa_is_format_compressed(firstImage
->TexFormat
))
973 t
->pp_txpitch
= (firstImage
->Width
+ 63) & ~(63);
975 t
->pp_txpitch
= ((firstImage
->Width
* texelBytes
) + 63) & ~(63);
979 if (t
->base
.Target
== GL_TEXTURE_RECTANGLE_NV
) {
980 t
->pp_txformat
|= RADEON_TXFORMAT_NON_POWER2
;
986 static GLboolean
radeon_validate_texture(struct gl_context
*ctx
, struct gl_texture_object
*texObj
, int unit
)
988 r100ContextPtr rmesa
= R100_CONTEXT(ctx
);
989 radeonTexObj
*t
= radeon_tex_obj(texObj
);
992 if (!radeon_validate_texture_miptree(ctx
, _mesa_get_samplerobj(ctx
, unit
), texObj
))
995 ret
= setup_hardware_state(rmesa
, t
, unit
);
999 /* yuv conversion only works in first unit */
1000 if (unit
!= 0 && (t
->pp_txfilter
& RADEON_YUV_TO_RGB
))
1003 RADEON_STATECHANGE( rmesa
, ctx
);
1004 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |=
1005 (RADEON_TEX_0_ENABLE
| RADEON_TEX_BLEND_0_ENABLE
) << unit
;
1006 RADEON_STATECHANGE( rmesa
, tcl
);
1007 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_ST_BIT(unit
);
1009 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1011 radeonTexUpdateParameters(ctx
, unit
);
1012 import_tex_obj_state( rmesa
, unit
, t
);
1014 if (rmesa
->recheck_texgen
[unit
]) {
1015 GLboolean fallback
= !radeon_validate_texgen( ctx
, unit
);
1016 TCL_FALLBACK( ctx
, (RADEON_TCL_FALLBACK_TEXGEN_0
<<unit
), fallback
);
1017 rmesa
->recheck_texgen
[unit
] = 0;
1018 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE_MATRIX
;
1021 if ( ! radeonUpdateTextureEnv( ctx
, unit
) ) {
1024 FALLBACK( rmesa
, RADEON_FALLBACK_BORDER_MODE
, t
->border_fallback
);
1026 t
->validated
= GL_TRUE
;
1027 return !t
->border_fallback
;
1030 static GLboolean
radeonUpdateTextureUnit( struct gl_context
*ctx
, int unit
)
1032 r100ContextPtr rmesa
= R100_CONTEXT(ctx
);
1034 if (ctx
->Texture
.Unit
[unit
]._Current
&&
1035 ctx
->Texture
.Unit
[unit
]._Current
->Target
== GL_TEXTURE_3D
) {
1036 disable_tex_obj_state(rmesa
, unit
);
1037 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
1041 if (!ctx
->Texture
.Unit
[unit
]._Current
) {
1042 /* disable the unit */
1043 disable_tex_obj_state(rmesa
, unit
);
1044 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
1048 if (!radeon_validate_texture(ctx
, ctx
->Texture
.Unit
[unit
]._Current
, unit
)) {
1050 "failed to validate texture for unit %d.\n",
1052 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
1055 rmesa
->state
.texture
.unit
[unit
].texobj
= radeon_tex_obj(ctx
->Texture
.Unit
[unit
]._Current
);
1059 void radeonUpdateTextureState( struct gl_context
*ctx
)
1061 r100ContextPtr rmesa
= R100_CONTEXT(ctx
);
1064 /* set the ctx all textures off */
1065 RADEON_STATECHANGE( rmesa
, ctx
);
1066 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~((RADEON_TEX_ENABLE_MASK
) | (RADEON_TEX_BLEND_ENABLE_MASK
));
1068 ok
= (radeonUpdateTextureUnit( ctx
, 0 ) &&
1069 radeonUpdateTextureUnit( ctx
, 1 ) &&
1070 radeonUpdateTextureUnit( ctx
, 2 ));
1072 FALLBACK( rmesa
, RADEON_FALLBACK_TEXTURE
, !ok
);
1074 if (rmesa
->radeon
.TclFallback
)
1075 radeonChooseVertexState( ctx
);