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.
28 **************************************************************************/
32 * Keith Whitwell <keith@tungstengraphics.com>
35 #include "main/glheader.h"
36 #include "main/imports.h"
37 #include "main/context.h"
38 #include "main/macros.h"
39 #include "main/texformat.h"
40 #include "main/teximage.h"
41 #include "main/texobj.h"
42 #include "main/enums.h"
44 #include "radeon_common.h"
45 #include "radeon_mipmap_tree.h"
46 #include "r200_context.h"
47 #include "r200_state.h"
48 #include "r200_ioctl.h"
49 #include "r200_swtcl.h"
54 #define R200_TXFORMAT_A8 R200_TXFORMAT_I8
55 #define R200_TXFORMAT_L8 R200_TXFORMAT_I8
56 #define R200_TXFORMAT_AL88 R200_TXFORMAT_AI88
57 #define R200_TXFORMAT_YCBCR R200_TXFORMAT_YVYU422
58 #define R200_TXFORMAT_YCBCR_REV R200_TXFORMAT_VYUY422
59 #define R200_TXFORMAT_RGB_DXT1 R200_TXFORMAT_DXT1
60 #define R200_TXFORMAT_RGBA_DXT1 R200_TXFORMAT_DXT1
61 #define R200_TXFORMAT_RGBA_DXT3 R200_TXFORMAT_DXT23
62 #define R200_TXFORMAT_RGBA_DXT5 R200_TXFORMAT_DXT45
65 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, 0 }
66 #define _COLOR_REV(f) \
67 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f, 0 }
69 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
70 #define _ALPHA_REV(f) \
71 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
73 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, R200_YUV_TO_RGB }
75 [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
76 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
77 && (tx_table_be[f].format != 0xffffffff) )
80 GLuint format
, filter
;
83 static const struct tx_table tx_table_be
[] =
85 [ MESA_FORMAT_RGBA8888
] = { R200_TXFORMAT_ABGR8888
| R200_TXFORMAT_ALPHA_IN_MAP
, 0 },
112 static const struct tx_table tx_table_le
[] =
115 [ MESA_FORMAT_RGBA8888_REV
] = { R200_TXFORMAT_ABGR8888
| R200_TXFORMAT_ALPHA_IN_MAP
, 0 },
117 _ALPHA_REV(ARGB8888
),
118 [ MESA_FORMAT_RGB888
] = { R200_TXFORMAT_ARGB8888
, 0 },
122 _ALPHA_REV(ARGB4444
),
124 _ALPHA_REV(ARGB1555
),
145 /* ================================================================
146 * Texture combine functions
149 /* GL_ARB_texture_env_combine support
152 /* The color tables have combine functions for GL_SRC_COLOR,
153 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
155 static GLuint r200_register_color
[][R200_MAX_TEXTURE_UNITS
] =
158 R200_TXC_ARG_A_R0_COLOR
,
159 R200_TXC_ARG_A_R1_COLOR
,
160 R200_TXC_ARG_A_R2_COLOR
,
161 R200_TXC_ARG_A_R3_COLOR
,
162 R200_TXC_ARG_A_R4_COLOR
,
163 R200_TXC_ARG_A_R5_COLOR
166 R200_TXC_ARG_A_R0_COLOR
| R200_TXC_COMP_ARG_A
,
167 R200_TXC_ARG_A_R1_COLOR
| R200_TXC_COMP_ARG_A
,
168 R200_TXC_ARG_A_R2_COLOR
| R200_TXC_COMP_ARG_A
,
169 R200_TXC_ARG_A_R3_COLOR
| R200_TXC_COMP_ARG_A
,
170 R200_TXC_ARG_A_R4_COLOR
| R200_TXC_COMP_ARG_A
,
171 R200_TXC_ARG_A_R5_COLOR
| R200_TXC_COMP_ARG_A
174 R200_TXC_ARG_A_R0_ALPHA
,
175 R200_TXC_ARG_A_R1_ALPHA
,
176 R200_TXC_ARG_A_R2_ALPHA
,
177 R200_TXC_ARG_A_R3_ALPHA
,
178 R200_TXC_ARG_A_R4_ALPHA
,
179 R200_TXC_ARG_A_R5_ALPHA
182 R200_TXC_ARG_A_R0_ALPHA
| R200_TXC_COMP_ARG_A
,
183 R200_TXC_ARG_A_R1_ALPHA
| R200_TXC_COMP_ARG_A
,
184 R200_TXC_ARG_A_R2_ALPHA
| R200_TXC_COMP_ARG_A
,
185 R200_TXC_ARG_A_R3_ALPHA
| R200_TXC_COMP_ARG_A
,
186 R200_TXC_ARG_A_R4_ALPHA
| R200_TXC_COMP_ARG_A
,
187 R200_TXC_ARG_A_R5_ALPHA
| R200_TXC_COMP_ARG_A
191 static GLuint r200_tfactor_color
[] =
193 R200_TXC_ARG_A_TFACTOR_COLOR
,
194 R200_TXC_ARG_A_TFACTOR_COLOR
| R200_TXC_COMP_ARG_A
,
195 R200_TXC_ARG_A_TFACTOR_ALPHA
,
196 R200_TXC_ARG_A_TFACTOR_ALPHA
| R200_TXC_COMP_ARG_A
199 static GLuint r200_tfactor1_color
[] =
201 R200_TXC_ARG_A_TFACTOR1_COLOR
,
202 R200_TXC_ARG_A_TFACTOR1_COLOR
| R200_TXC_COMP_ARG_A
,
203 R200_TXC_ARG_A_TFACTOR1_ALPHA
,
204 R200_TXC_ARG_A_TFACTOR1_ALPHA
| R200_TXC_COMP_ARG_A
207 static GLuint r200_primary_color
[] =
209 R200_TXC_ARG_A_DIFFUSE_COLOR
,
210 R200_TXC_ARG_A_DIFFUSE_COLOR
| R200_TXC_COMP_ARG_A
,
211 R200_TXC_ARG_A_DIFFUSE_ALPHA
,
212 R200_TXC_ARG_A_DIFFUSE_ALPHA
| R200_TXC_COMP_ARG_A
215 /* GL_ZERO table - indices 0-3
216 * GL_ONE table - indices 1-4
218 static GLuint r200_zero_color
[] =
221 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
223 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
227 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
229 static GLuint r200_register_alpha
[][R200_MAX_TEXTURE_UNITS
] =
232 R200_TXA_ARG_A_R0_ALPHA
,
233 R200_TXA_ARG_A_R1_ALPHA
,
234 R200_TXA_ARG_A_R2_ALPHA
,
235 R200_TXA_ARG_A_R3_ALPHA
,
236 R200_TXA_ARG_A_R4_ALPHA
,
237 R200_TXA_ARG_A_R5_ALPHA
240 R200_TXA_ARG_A_R0_ALPHA
| R200_TXA_COMP_ARG_A
,
241 R200_TXA_ARG_A_R1_ALPHA
| R200_TXA_COMP_ARG_A
,
242 R200_TXA_ARG_A_R2_ALPHA
| R200_TXA_COMP_ARG_A
,
243 R200_TXA_ARG_A_R3_ALPHA
| R200_TXA_COMP_ARG_A
,
244 R200_TXA_ARG_A_R4_ALPHA
| R200_TXA_COMP_ARG_A
,
245 R200_TXA_ARG_A_R5_ALPHA
| R200_TXA_COMP_ARG_A
249 static GLuint r200_tfactor_alpha
[] =
251 R200_TXA_ARG_A_TFACTOR_ALPHA
,
252 R200_TXA_ARG_A_TFACTOR_ALPHA
| R200_TXA_COMP_ARG_A
255 static GLuint r200_tfactor1_alpha
[] =
257 R200_TXA_ARG_A_TFACTOR1_ALPHA
,
258 R200_TXA_ARG_A_TFACTOR1_ALPHA
| R200_TXA_COMP_ARG_A
261 static GLuint r200_primary_alpha
[] =
263 R200_TXA_ARG_A_DIFFUSE_ALPHA
,
264 R200_TXA_ARG_A_DIFFUSE_ALPHA
| R200_TXA_COMP_ARG_A
267 /* GL_ZERO table - indices 0-1
268 * GL_ONE table - indices 1-2
270 static GLuint r200_zero_alpha
[] =
273 R200_TXA_ARG_A_ZERO
| R200_TXA_COMP_ARG_A
,
278 /* Extract the arg from slot A, shift it into the correct argument slot
279 * and set the corresponding complement bit.
281 #define R200_COLOR_ARG( n, arg ) \
284 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
285 << R200_TXC_ARG_##arg##_SHIFT); \
287 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
288 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
291 #define R200_ALPHA_ARG( n, arg ) \
294 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
295 << R200_TXA_ARG_##arg##_SHIFT); \
297 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
298 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
302 /* ================================================================
303 * Texture unit state management
306 static GLboolean
r200UpdateTextureEnv( GLcontext
*ctx
, int unit
, int slot
, GLuint replaceargs
)
308 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
309 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
310 GLuint color_combine
, alpha_combine
;
311 GLuint color_scale
= rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] &
312 ~(R200_TXC_SCALE_MASK
| R200_TXC_OUTPUT_REG_MASK
| R200_TXC_TFACTOR_SEL_MASK
|
313 R200_TXC_TFACTOR1_SEL_MASK
);
314 GLuint alpha_scale
= rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] &
315 ~(R200_TXA_DOT_ALPHA
| R200_TXA_SCALE_MASK
| R200_TXA_OUTPUT_REG_MASK
|
316 R200_TXA_TFACTOR_SEL_MASK
| R200_TXA_TFACTOR1_SEL_MASK
);
318 /* texUnit->_Current can be NULL if and only if the texture unit is
319 * not actually enabled.
321 assert( (texUnit
->_ReallyEnabled
== 0)
322 || (texUnit
->_Current
!= NULL
) );
324 if ( R200_DEBUG
& DEBUG_TEXTURE
) {
325 fprintf( stderr
, "%s( %p, %d )\n", __FUNCTION__
, (void *)ctx
, unit
);
328 /* Set the texture environment state. Isn't this nice and clean?
329 * The chip will automagically set the texture alpha to 0xff when
330 * the texture format does not include an alpha component. This
331 * reduces the amount of special-casing we have to do, alpha-only
332 * textures being a notable exception.
335 color_scale
|= ((rmesa
->state
.texture
.unit
[unit
].outputreg
+ 1) << R200_TXC_OUTPUT_REG_SHIFT
) |
336 (unit
<< R200_TXC_TFACTOR_SEL_SHIFT
) |
337 (replaceargs
<< R200_TXC_TFACTOR1_SEL_SHIFT
);
338 alpha_scale
|= ((rmesa
->state
.texture
.unit
[unit
].outputreg
+ 1) << R200_TXA_OUTPUT_REG_SHIFT
) |
339 (unit
<< R200_TXA_TFACTOR_SEL_SHIFT
) |
340 (replaceargs
<< R200_TXA_TFACTOR1_SEL_SHIFT
);
342 if ( !texUnit
->_ReallyEnabled
) {
344 color_combine
= R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
345 | R200_TXC_ARG_C_DIFFUSE_COLOR
| R200_TXC_OP_MADD
;
346 alpha_combine
= R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
347 | R200_TXA_ARG_C_DIFFUSE_ALPHA
| R200_TXA_OP_MADD
;
350 GLuint color_arg
[3], alpha_arg
[3];
352 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
353 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
354 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
355 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
358 const GLint replaceoprgb
=
359 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->OperandRGB
[0] - GL_SRC_COLOR
;
360 const GLint replaceopa
=
361 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->OperandA
[0] - GL_SRC_ALPHA
;
364 * Extract the color and alpha combine function arguments.
366 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
367 GLint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
] - GL_SRC_COLOR
;
368 const GLint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
373 color_arg
[i
] = r200_register_color
[op
][unit
];
376 color_arg
[i
] = r200_tfactor_color
[op
];
378 case GL_PRIMARY_COLOR
:
379 color_arg
[i
] = r200_primary_color
[op
];
382 if (replaceargs
!= unit
) {
383 const GLint srcRGBreplace
=
384 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->SourceRGB
[0];
386 op
= op
^ replaceopa
;
389 op
= op
^ replaceoprgb
;
391 switch (srcRGBreplace
) {
393 color_arg
[i
] = r200_register_color
[op
][replaceargs
];
396 color_arg
[i
] = r200_tfactor1_color
[op
];
398 case GL_PRIMARY_COLOR
:
399 color_arg
[i
] = r200_primary_color
[op
];
403 color_arg
[i
] = r200_primary_color
[op
];
405 color_arg
[i
] = r200_register_color
[op
]
406 [rmesa
->state
.texture
.unit
[replaceargs
- 1].outputreg
];
409 color_arg
[i
] = r200_zero_color
[op
];
412 color_arg
[i
] = r200_zero_color
[op
+1];
420 color_arg
[i
] = r200_register_color
[op
][srcRGBreplace
- GL_TEXTURE0
];
428 color_arg
[i
] = r200_primary_color
[op
];
430 color_arg
[i
] = r200_register_color
[op
]
431 [rmesa
->state
.texture
.unit
[unit
- 1].outputreg
];
435 color_arg
[i
] = r200_zero_color
[op
];
438 color_arg
[i
] = r200_zero_color
[op
+1];
446 color_arg
[i
] = r200_register_color
[op
][srcRGBi
- GL_TEXTURE0
];
453 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
454 GLint op
= texUnit
->_CurrentCombine
->OperandA
[i
] - GL_SRC_ALPHA
;
455 const GLint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
460 alpha_arg
[i
] = r200_register_alpha
[op
][unit
];
463 alpha_arg
[i
] = r200_tfactor_alpha
[op
];
465 case GL_PRIMARY_COLOR
:
466 alpha_arg
[i
] = r200_primary_alpha
[op
];
469 if (replaceargs
!= unit
) {
470 const GLint srcAreplace
=
471 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->SourceA
[0];
472 op
= op
^ replaceopa
;
473 switch (srcAreplace
) {
475 alpha_arg
[i
] = r200_register_alpha
[op
][replaceargs
];
478 alpha_arg
[i
] = r200_tfactor1_alpha
[op
];
480 case GL_PRIMARY_COLOR
:
481 alpha_arg
[i
] = r200_primary_alpha
[op
];
485 alpha_arg
[i
] = r200_primary_alpha
[op
];
487 alpha_arg
[i
] = r200_register_alpha
[op
]
488 [rmesa
->state
.texture
.unit
[replaceargs
- 1].outputreg
];
491 alpha_arg
[i
] = r200_zero_alpha
[op
];
494 alpha_arg
[i
] = r200_zero_alpha
[op
+1];
502 alpha_arg
[i
] = r200_register_alpha
[op
][srcAreplace
- GL_TEXTURE0
];
510 alpha_arg
[i
] = r200_primary_alpha
[op
];
512 alpha_arg
[i
] = r200_register_alpha
[op
]
513 [rmesa
->state
.texture
.unit
[unit
- 1].outputreg
];
517 alpha_arg
[i
] = r200_zero_alpha
[op
];
520 alpha_arg
[i
] = r200_zero_alpha
[op
+1];
528 alpha_arg
[i
] = r200_register_alpha
[op
][srcAi
- GL_TEXTURE0
];
536 * Build up the color and alpha combine functions.
538 switch ( texUnit
->_CurrentCombine
->ModeRGB
) {
540 color_combine
= (R200_TXC_ARG_A_ZERO
|
541 R200_TXC_ARG_B_ZERO
|
543 R200_COLOR_ARG( 0, C
);
546 color_combine
= (R200_TXC_ARG_C_ZERO
|
548 R200_COLOR_ARG( 0, A
);
549 R200_COLOR_ARG( 1, B
);
552 color_combine
= (R200_TXC_ARG_B_ZERO
|
553 R200_TXC_COMP_ARG_B
|
555 R200_COLOR_ARG( 0, A
);
556 R200_COLOR_ARG( 1, C
);
559 color_combine
= (R200_TXC_ARG_B_ZERO
|
560 R200_TXC_COMP_ARG_B
|
561 R200_TXC_BIAS_ARG_C
| /* new */
562 R200_TXC_OP_MADD
); /* was ADDSIGNED */
563 R200_COLOR_ARG( 0, A
);
564 R200_COLOR_ARG( 1, C
);
567 color_combine
= (R200_TXC_ARG_B_ZERO
|
568 R200_TXC_COMP_ARG_B
|
571 R200_COLOR_ARG( 0, A
);
572 R200_COLOR_ARG( 1, C
);
575 color_combine
= (R200_TXC_OP_LERP
);
576 R200_COLOR_ARG( 0, B
);
577 R200_COLOR_ARG( 1, A
);
578 R200_COLOR_ARG( 2, C
);
581 case GL_DOT3_RGB_EXT
:
582 case GL_DOT3_RGBA_EXT
:
583 /* The EXT version of the DOT3 extension does not support the
584 * scale factor, but the ARB version (and the version in OpenGL
592 /* DOT3 works differently on R200 than on R100. On R100, just
593 * setting the DOT3 mode did everything for you. On R200, the
594 * driver has to enable the biasing and scale in the inputs to
595 * put them in the proper [-1,1] range. This is what the 4x and
596 * the -0.5 in the DOT3 spec do. The post-scale is then set
600 color_combine
= (R200_TXC_ARG_C_ZERO
|
602 R200_TXC_BIAS_ARG_A
|
603 R200_TXC_BIAS_ARG_B
|
604 R200_TXC_SCALE_ARG_A
|
605 R200_TXC_SCALE_ARG_B
);
606 R200_COLOR_ARG( 0, A
);
607 R200_COLOR_ARG( 1, B
);
610 case GL_MODULATE_ADD_ATI
:
611 color_combine
= (R200_TXC_OP_MADD
);
612 R200_COLOR_ARG( 0, A
);
613 R200_COLOR_ARG( 1, C
);
614 R200_COLOR_ARG( 2, B
);
616 case GL_MODULATE_SIGNED_ADD_ATI
:
617 color_combine
= (R200_TXC_BIAS_ARG_C
| /* new */
618 R200_TXC_OP_MADD
); /* was ADDSIGNED */
619 R200_COLOR_ARG( 0, A
);
620 R200_COLOR_ARG( 1, C
);
621 R200_COLOR_ARG( 2, B
);
623 case GL_MODULATE_SUBTRACT_ATI
:
624 color_combine
= (R200_TXC_NEG_ARG_C
|
626 R200_COLOR_ARG( 0, A
);
627 R200_COLOR_ARG( 1, C
);
628 R200_COLOR_ARG( 2, B
);
634 switch ( texUnit
->_CurrentCombine
->ModeA
) {
636 alpha_combine
= (R200_TXA_ARG_A_ZERO
|
637 R200_TXA_ARG_B_ZERO
|
639 R200_ALPHA_ARG( 0, C
);
642 alpha_combine
= (R200_TXA_ARG_C_ZERO
|
644 R200_ALPHA_ARG( 0, A
);
645 R200_ALPHA_ARG( 1, B
);
648 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
649 R200_TXA_COMP_ARG_B
|
651 R200_ALPHA_ARG( 0, A
);
652 R200_ALPHA_ARG( 1, C
);
655 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
656 R200_TXA_COMP_ARG_B
|
657 R200_TXA_BIAS_ARG_C
| /* new */
658 R200_TXA_OP_MADD
); /* was ADDSIGNED */
659 R200_ALPHA_ARG( 0, A
);
660 R200_ALPHA_ARG( 1, C
);
663 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
664 R200_TXA_COMP_ARG_B
|
667 R200_ALPHA_ARG( 0, A
);
668 R200_ALPHA_ARG( 1, C
);
671 alpha_combine
= (R200_TXA_OP_LERP
);
672 R200_ALPHA_ARG( 0, B
);
673 R200_ALPHA_ARG( 1, A
);
674 R200_ALPHA_ARG( 2, C
);
677 case GL_MODULATE_ADD_ATI
:
678 alpha_combine
= (R200_TXA_OP_MADD
);
679 R200_ALPHA_ARG( 0, A
);
680 R200_ALPHA_ARG( 1, C
);
681 R200_ALPHA_ARG( 2, B
);
683 case GL_MODULATE_SIGNED_ADD_ATI
:
684 alpha_combine
= (R200_TXA_BIAS_ARG_C
| /* new */
685 R200_TXA_OP_MADD
); /* was ADDSIGNED */
686 R200_ALPHA_ARG( 0, A
);
687 R200_ALPHA_ARG( 1, C
);
688 R200_ALPHA_ARG( 2, B
);
690 case GL_MODULATE_SUBTRACT_ATI
:
691 alpha_combine
= (R200_TXA_NEG_ARG_C
|
693 R200_ALPHA_ARG( 0, A
);
694 R200_ALPHA_ARG( 1, C
);
695 R200_ALPHA_ARG( 2, B
);
701 if ( (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
702 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ) {
703 alpha_scale
|= R200_TXA_DOT_ALPHA
;
708 * Apply the scale factor.
710 color_scale
|= (RGBshift
<< R200_TXC_SCALE_SHIFT
);
711 alpha_scale
|= (Ashift
<< R200_TXA_SCALE_SHIFT
);
717 if ( rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND
] != color_combine
||
718 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND
] != alpha_combine
||
719 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] != color_scale
||
720 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] != alpha_scale
) {
721 R200_STATECHANGE( rmesa
, pix
[slot
] );
722 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND
] = color_combine
;
723 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND
] = alpha_combine
;
724 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] = color_scale
;
725 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] = alpha_scale
;
731 void r200SetTexOffset(__DRIcontext
* pDRICtx
, GLint texname
,
732 unsigned long long offset
, GLint depth
, GLuint pitch
)
734 r200ContextPtr rmesa
= pDRICtx
->driverPrivate
;
735 struct gl_texture_object
*tObj
=
736 _mesa_lookup_texture(rmesa
->radeon
.glCtx
, texname
);
737 radeonTexObjPtr t
= radeon_tex_obj(tObj
);
742 t
->image_override
= GL_TRUE
;
748 t
->override_offset
= offset
;
749 t
->pp_txpitch
= pitch
- 32;
753 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_ARGB8888
].format
;
754 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_ARGB8888
].filter
;
758 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_RGB888
].format
;
759 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_RGB888
].filter
;
762 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_RGB565
].format
;
763 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_RGB565
].filter
;
768 void r200SetTexBuffer2(__DRIcontext
*pDRICtx
, GLint target
, GLint glx_texture_format
,
769 __DRIdrawable
*dPriv
)
771 struct gl_texture_unit
*texUnit
;
772 struct gl_texture_object
*texObj
;
773 struct gl_texture_image
*texImage
;
774 struct radeon_renderbuffer
*rb
;
775 radeon_texture_image
*rImage
;
776 radeonContextPtr radeon
;
777 r200ContextPtr rmesa
;
778 struct radeon_framebuffer
*rfb
;
781 uint32_t internalFormat
, type
, format
;
784 format
= GL_UNSIGNED_BYTE
;
785 internalFormat
= (glx_texture_format
== GLX_TEXTURE_FORMAT_RGB_EXT
? 3 : 4);
787 radeon
= pDRICtx
->driverPrivate
;
788 rmesa
= pDRICtx
->driverPrivate
;
790 rfb
= dPriv
->driverPrivate
;
791 texUnit
= &radeon
->glCtx
->Texture
.Unit
[radeon
->glCtx
->Texture
.CurrentUnit
];
792 texObj
= _mesa_select_tex_object(radeon
->glCtx
, texUnit
, target
);
793 texImage
= _mesa_get_tex_image(radeon
->glCtx
, texObj
, target
, 0);
795 rImage
= get_radeon_texture_image(texImage
);
796 t
= radeon_tex_obj(texObj
);
801 radeon_update_renderbuffers(pDRICtx
, dPriv
);
802 /* back & depth buffer are useless free them right away */
803 rb
= (void*)rfb
->base
.Attachment
[BUFFER_DEPTH
].Renderbuffer
;
805 radeon_bo_unref(rb
->bo
);
808 rb
= (void*)rfb
->base
.Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
810 radeon_bo_unref(rb
->bo
);
813 rb
= rfb
->color_rb
[0];
814 if (rb
->bo
== NULL
) {
815 /* Failed to BO for the buffer */
819 _mesa_lock_texture(radeon
->glCtx
, texObj
);
821 radeon_bo_unref(t
->bo
);
825 radeon_bo_unref(rImage
->bo
);
829 radeon_miptree_unreference(t
->mt
);
833 radeon_miptree_unreference(rImage
->mt
);
836 _mesa_init_teximage_fields(radeon
->glCtx
, target
, texImage
,
837 rb
->base
.Width
, rb
->base
.Height
, 1, 0, rb
->cpp
);
838 texImage
->RowStride
= rb
->pitch
/ rb
->cpp
;
839 texImage
->TexFormat
= radeonChooseTextureFormat(radeon
->glCtx
,
843 radeon_bo_ref(rImage
->bo
);
845 radeon_bo_ref(t
->bo
);
847 t
->image_override
= GL_TRUE
;
848 t
->override_offset
= 0;
849 t
->pp_txpitch
&= (1 << 13) -1;
850 pitch_val
= rb
->pitch
;
853 if (glx_texture_format
== GLX_TEXTURE_FORMAT_RGB_EXT
)
854 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_RGB888
].format
;
856 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_ARGB8888
].format
;
857 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_ARGB8888
].filter
;
861 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_RGB888
].format
;
862 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_RGB888
].filter
;
865 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_RGB565
].format
;
866 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_RGB565
].filter
;
869 t
->pp_txsize
= ((rb
->base
.Width
- 1) << RADEON_TEX_USIZE_SHIFT
)
870 | ((rb
->base
.Height
- 1) << RADEON_TEX_VSIZE_SHIFT
);
871 t
->pp_txformat
|= R200_TXFORMAT_NON_POWER2
;
872 t
->pp_txpitch
= pitch_val
;
875 t
->validated
= GL_TRUE
;
876 _mesa_unlock_texture(radeon
->glCtx
, texObj
);
881 void r200SetTexBuffer(__DRIcontext
*pDRICtx
, GLint target
, __DRIdrawable
*dPriv
)
883 r200SetTexBuffer2(pDRICtx
, target
, GLX_TEXTURE_FORMAT_RGBA_EXT
, dPriv
);
890 static GLboolean
r200UpdateAllTexEnv( GLcontext
*ctx
)
892 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
893 GLint i
, j
, currslot
;
894 GLint maxunitused
= -1;
895 GLboolean texregfree
[6] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
896 GLubyte stageref
[7] = {0, 0, 0, 0, 0, 0, 0};
897 GLint nextunit
[R200_MAX_TEXTURE_UNITS
] = {0, 0, 0, 0, 0, 0};
898 GLint currentnext
= -1;
901 /* find highest used unit */
902 for ( j
= 0; j
< R200_MAX_TEXTURE_UNITS
; j
++) {
903 if (ctx
->Texture
.Unit
[j
]._ReallyEnabled
) {
907 stageref
[maxunitused
+ 1] = REF_COLOR
| REF_ALPHA
;
909 for ( j
= maxunitused
; j
>= 0; j
-- ) {
910 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[j
];
912 rmesa
->state
.texture
.unit
[j
].outputreg
= -1;
914 if (stageref
[j
+ 1]) {
916 /* use the lowest available reg. That gets us automatically reg0 for the last stage.
917 need this even for disabled units, as it may get referenced due to the replace
919 for ( i
= 0 ; i
< R200_MAX_TEXTURE_UNITS
; i
++ ) {
921 rmesa
->state
.texture
.unit
[j
].outputreg
= i
;
925 if (rmesa
->state
.texture
.unit
[j
].outputreg
== -1) {
926 /* no more free regs we can use. Need a fallback :-( */
930 nextunit
[j
] = currentnext
;
932 if (!texUnit
->_ReallyEnabled
) {
933 /* the not enabled stages are referenced "indirectly",
934 must not cut off the lower stages */
935 stageref
[j
] = REF_COLOR
| REF_ALPHA
;
940 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
941 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
942 const GLboolean isdot3rgba
= (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ||
943 (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
);
946 /* check if we need the color part, special case for dot3_rgba
947 as if only the alpha part is referenced later on it still is using the color part */
948 if ((stageref
[j
+ 1] & REF_COLOR
) || isdot3rgba
) {
949 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
950 const GLuint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
951 const GLuint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
];
954 /* op 0/1 are referencing color, op 2/3 alpha */
955 stageref
[j
] |= (op
>> 1) + 1;
958 texregfree
[j
] = GL_FALSE
;
966 texregfree
[srcRGBi
- GL_TEXTURE0
] = GL_FALSE
;
968 default: /* don't care about other sources here */
974 /* alpha args are ignored for dot3_rgba */
975 if ((stageref
[j
+ 1] & REF_ALPHA
) && !isdot3rgba
) {
977 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
978 const GLuint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
981 stageref
[j
] |= REF_ALPHA
;
984 texregfree
[j
] = GL_FALSE
;
992 texregfree
[srcAi
- GL_TEXTURE0
] = GL_FALSE
;
994 default: /* don't care about other sources here */
1002 /* don't enable texture sampling for units if the result is not used */
1003 for (i
= 0; i
< R200_MAX_TEXTURE_UNITS
; i
++) {
1004 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
&& !texregfree
[i
])
1005 rmesa
->state
.texture
.unit
[i
].unitneeded
= ctx
->Texture
.Unit
[i
]._ReallyEnabled
;
1006 else rmesa
->state
.texture
.unit
[i
].unitneeded
= 0;
1011 rmesa
->state
.envneeded
= 1;
1014 while ((i
<= maxunitused
) && (i
>= 0)) {
1015 /* only output instruction if the results are referenced */
1016 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
&& stageref
[i
+1]) {
1017 GLuint replaceunit
= i
;
1018 /* try to optimize GL_REPLACE away (only one level deep though) */
1019 if ( (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ModeRGB
== GL_REPLACE
) &&
1020 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ModeA
== GL_REPLACE
) &&
1021 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ScaleShiftRGB
== 0) &&
1022 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ScaleShiftA
== 0) &&
1023 (nextunit
[i
] > 0) ) {
1024 /* yippie! can optimize it away! */
1029 /* need env instruction slot */
1030 rmesa
->state
.envneeded
|= 1 << currslot
;
1031 ok
= r200UpdateTextureEnv( ctx
, i
, currslot
, replaceunit
);
1032 if (!ok
) return GL_FALSE
;
1038 if (currslot
== 0) {
1039 /* need one stage at least */
1040 rmesa
->state
.texture
.unit
[0].outputreg
= 0;
1041 ok
= r200UpdateTextureEnv( ctx
, 0, 0, 0 );
1044 R200_STATECHANGE( rmesa
, ctx
);
1045 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~(R200_TEX_BLEND_ENABLE_MASK
| R200_MULTI_PASS_ENABLE
);
1046 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= rmesa
->state
.envneeded
<< R200_TEX_BLEND_0_ENABLE_SHIFT
;
1055 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
1056 R200_MIN_FILTER_MASK | \
1057 R200_MAG_FILTER_MASK | \
1058 R200_MAX_ANISO_MASK | \
1060 R200_YUV_TEMPERATURE_MASK | \
1061 R200_CLAMP_S_MASK | \
1062 R200_CLAMP_T_MASK | \
1063 R200_BORDER_MODE_D3D )
1065 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
1066 R200_TXFORMAT_HEIGHT_MASK | \
1067 R200_TXFORMAT_FORMAT_MASK | \
1068 R200_TXFORMAT_F5_WIDTH_MASK | \
1069 R200_TXFORMAT_F5_HEIGHT_MASK | \
1070 R200_TXFORMAT_ALPHA_IN_MAP | \
1071 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
1072 R200_TXFORMAT_NON_POWER2)
1074 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
1075 R200_TEXCOORD_MASK | \
1076 R200_CLAMP_Q_MASK | \
1077 R200_VOLUME_FILTER_MASK)
1080 static void disable_tex_obj_state( r200ContextPtr rmesa
,
1084 R200_STATECHANGE( rmesa
, vtx
);
1085 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
1087 if (rmesa
->radeon
.TclFallback
& (R200_TCL_FALLBACK_TEXGEN_0
<<unit
)) {
1088 TCL_FALLBACK( rmesa
->radeon
.glCtx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), GL_FALSE
);
1091 /* Actually want to keep all units less than max active texture
1092 * enabled, right? Fix this for >2 texunits.
1096 GLuint tmp
= rmesa
->TexGenEnabled
;
1098 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
1099 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
1100 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
1101 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1103 if (tmp
!= rmesa
->TexGenEnabled
) {
1104 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1105 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE_MATRIX
;
1109 static void import_tex_obj_state( r200ContextPtr rmesa
,
1111 radeonTexObjPtr texobj
)
1113 /* do not use RADEON_DB_STATE to avoid stale texture caches */
1114 GLuint
*cmd
= &rmesa
->hw
.tex
[unit
].cmd
[TEX_CMD_0
];
1116 R200_STATECHANGE( rmesa
, tex
[unit
] );
1118 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
1119 cmd
[TEX_PP_TXFILTER
] |= texobj
->pp_txfilter
& TEXOBJ_TXFILTER_MASK
;
1120 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1121 cmd
[TEX_PP_TXFORMAT
] |= texobj
->pp_txformat
& TEXOBJ_TXFORMAT_MASK
;
1122 cmd
[TEX_PP_TXFORMAT_X
] &= ~TEXOBJ_TXFORMAT_X_MASK
;
1123 cmd
[TEX_PP_TXFORMAT_X
] |= texobj
->pp_txformat_x
& TEXOBJ_TXFORMAT_X_MASK
;
1124 cmd
[TEX_PP_TXSIZE
] = texobj
->pp_txsize
; /* NPOT only! */
1125 cmd
[TEX_PP_TXPITCH
] = texobj
->pp_txpitch
; /* NPOT only! */
1126 cmd
[TEX_PP_BORDER_COLOR
] = texobj
->pp_border_color
;
1128 if (texobj
->base
.Target
== GL_TEXTURE_CUBE_MAP
) {
1129 GLuint
*cube_cmd
= &rmesa
->hw
.cube
[unit
].cmd
[CUBE_CMD_0
];
1131 R200_STATECHANGE( rmesa
, cube
[unit
] );
1132 cube_cmd
[CUBE_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
1133 if (rmesa
->radeon
.radeonScreen
->drmSupportsFragShader
) {
1134 /* that value is submitted twice. could change cube atom
1135 to not include that command when new drm is used */
1136 cmd
[TEX_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
1142 static void set_texgen_matrix( r200ContextPtr rmesa
,
1144 const GLfloat
*s_plane
,
1145 const GLfloat
*t_plane
,
1146 const GLfloat
*r_plane
,
1147 const GLfloat
*q_plane
)
1171 _math_matrix_loadf( &(rmesa
->TexGenMatrix
[unit
]), m
);
1172 _math_matrix_analyse( &(rmesa
->TexGenMatrix
[unit
]) );
1173 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<<unit
;
1177 static GLuint
r200_need_dis_texgen(const GLbitfield texGenEnabled
,
1178 const GLfloat
*planeS
,
1179 const GLfloat
*planeT
,
1180 const GLfloat
*planeR
,
1181 const GLfloat
*planeQ
)
1183 GLuint needtgenable
= 0;
1185 if (!(texGenEnabled
& S_BIT
)) {
1186 if (((texGenEnabled
& T_BIT
) && planeT
[0] != 0.0) ||
1187 ((texGenEnabled
& R_BIT
) && planeR
[0] != 0.0) ||
1188 ((texGenEnabled
& Q_BIT
) && planeQ
[0] != 0.0)) {
1189 needtgenable
|= S_BIT
;
1192 if (!(texGenEnabled
& T_BIT
)) {
1193 if (((texGenEnabled
& S_BIT
) && planeS
[1] != 0.0) ||
1194 ((texGenEnabled
& R_BIT
) && planeR
[1] != 0.0) ||
1195 ((texGenEnabled
& Q_BIT
) && planeQ
[1] != 0.0)) {
1196 needtgenable
|= T_BIT
;
1199 if (!(texGenEnabled
& R_BIT
)) {
1200 if (((texGenEnabled
& S_BIT
) && planeS
[2] != 0.0) ||
1201 ((texGenEnabled
& T_BIT
) && planeT
[2] != 0.0) ||
1202 ((texGenEnabled
& Q_BIT
) && planeQ
[2] != 0.0)) {
1203 needtgenable
|= R_BIT
;
1206 if (!(texGenEnabled
& Q_BIT
)) {
1207 if (((texGenEnabled
& S_BIT
) && planeS
[3] != 0.0) ||
1208 ((texGenEnabled
& T_BIT
) && planeT
[3] != 0.0) ||
1209 ((texGenEnabled
& R_BIT
) && planeR
[3] != 0.0)) {
1210 needtgenable
|= Q_BIT
;
1214 return needtgenable
;
1219 * Returns GL_FALSE if fallback required.
1221 static GLboolean
r200_validate_texgen( GLcontext
*ctx
, GLuint unit
)
1223 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1224 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1225 GLuint inputshift
= R200_TEXGEN_0_INPUT_SHIFT
+ unit
*4;
1228 GLboolean mixed_fallback
= GL_FALSE
;
1229 static const GLfloat I
[16] = {
1234 static const GLfloat reflect
[16] = {
1240 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1241 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
1242 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
1243 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
1244 tgi
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] & ~(R200_TEXGEN_INPUT_MASK
<<
1246 tgcm
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] & ~(R200_TEXGEN_COMP_MASK
<<
1250 fprintf(stderr
, "%s unit %d\n", __FUNCTION__
, unit
);
1252 if (texUnit
->TexGenEnabled
& S_BIT
) {
1253 mode
= texUnit
->GenS
.Mode
;
1255 tgcm
|= R200_TEXGEN_COMP_S
<< (unit
* 4);
1258 if (texUnit
->TexGenEnabled
& T_BIT
) {
1259 if (texUnit
->GenT
.Mode
!= mode
)
1260 mixed_fallback
= GL_TRUE
;
1262 tgcm
|= R200_TEXGEN_COMP_T
<< (unit
* 4);
1264 if (texUnit
->TexGenEnabled
& R_BIT
) {
1265 if (texUnit
->GenR
.Mode
!= mode
)
1266 mixed_fallback
= GL_TRUE
;
1268 tgcm
|= R200_TEXGEN_COMP_R
<< (unit
* 4);
1271 if (texUnit
->TexGenEnabled
& Q_BIT
) {
1272 if (texUnit
->GenQ
.Mode
!= mode
)
1273 mixed_fallback
= GL_TRUE
;
1275 tgcm
|= R200_TEXGEN_COMP_Q
<< (unit
* 4);
1278 if (mixed_fallback
) {
1279 if (R200_DEBUG
& DEBUG_FALLBACKS
)
1280 fprintf(stderr
, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
1281 texUnit
->TexGenEnabled
, texUnit
->GenS
.Mode
, texUnit
->GenT
.Mode
,
1282 texUnit
->GenR
.Mode
, texUnit
->GenQ
.Mode
);
1286 /* we CANNOT do mixed mode if the texgen mode requires a plane where the input
1287 is not enabled for texgen, since the planes are concatenated into texmat,
1288 and thus the input will come from texcoord rather than tex gen equation!
1289 Either fallback or just hope that those texcoords aren't really needed...
1290 Assuming the former will cause lots of unnecessary fallbacks, the latter will
1291 generate bogus results sometimes - it's pretty much impossible to really know
1292 when a fallback is needed, depends on texmat and what sort of texture is bound
1293 etc, - for now fallback if we're missing either S or T bits, there's a high
1294 probability we need the texcoords in that case.
1295 That's a lot of work for some obscure texgen mixed mode fixup - why oh why
1296 doesn't the chip just directly accept the plane parameters :-(. */
1298 case GL_OBJECT_LINEAR
: {
1299 GLuint needtgenable
= r200_need_dis_texgen( texUnit
->TexGenEnabled
,
1300 texUnit
->GenS
.ObjectPlane
,
1301 texUnit
->GenT
.ObjectPlane
,
1302 texUnit
->GenR
.ObjectPlane
,
1303 texUnit
->GenQ
.ObjectPlane
);
1304 if (needtgenable
& (S_BIT
| T_BIT
)) {
1305 if (R200_DEBUG
& DEBUG_FALLBACKS
)
1306 fprintf(stderr
, "fallback mixed texgen / obj plane, 0x%x\n",
1307 texUnit
->TexGenEnabled
);
1310 if (needtgenable
& (R_BIT
)) {
1311 tgcm
&= ~(R200_TEXGEN_COMP_R
<< (unit
* 4));
1313 if (needtgenable
& (Q_BIT
)) {
1314 tgcm
&= ~(R200_TEXGEN_COMP_Q
<< (unit
* 4));
1317 tgi
|= R200_TEXGEN_INPUT_OBJ
<< inputshift
;
1318 set_texgen_matrix( rmesa
, unit
,
1319 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->GenS
.ObjectPlane
: I
,
1320 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->GenT
.ObjectPlane
: I
+ 4,
1321 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->GenR
.ObjectPlane
: I
+ 8,
1322 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->GenQ
.ObjectPlane
: I
+ 12);
1326 case GL_EYE_LINEAR
: {
1327 GLuint needtgenable
= r200_need_dis_texgen( texUnit
->TexGenEnabled
,
1328 texUnit
->GenS
.EyePlane
,
1329 texUnit
->GenT
.EyePlane
,
1330 texUnit
->GenR
.EyePlane
,
1331 texUnit
->GenQ
.EyePlane
);
1332 if (needtgenable
& (S_BIT
| T_BIT
)) {
1333 if (R200_DEBUG
& DEBUG_FALLBACKS
)
1334 fprintf(stderr
, "fallback mixed texgen / eye plane, 0x%x\n",
1335 texUnit
->TexGenEnabled
);
1338 if (needtgenable
& (R_BIT
)) {
1339 tgcm
&= ~(R200_TEXGEN_COMP_R
<< (unit
* 4));
1341 if (needtgenable
& (Q_BIT
)) {
1342 tgcm
&= ~(R200_TEXGEN_COMP_Q
<< (unit
* 4));
1344 tgi
|= R200_TEXGEN_INPUT_EYE
<< inputshift
;
1345 set_texgen_matrix( rmesa
, unit
,
1346 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->GenS
.EyePlane
: I
,
1347 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->GenT
.EyePlane
: I
+ 4,
1348 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->GenR
.EyePlane
: I
+ 8,
1349 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->GenQ
.EyePlane
: I
+ 12);
1353 case GL_REFLECTION_MAP_NV
:
1354 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1355 tgi
|= R200_TEXGEN_INPUT_EYE_REFLECT
<< inputshift
;
1356 /* pretty weird, must only negate when lighting is enabled? */
1357 if (ctx
->Light
.Enabled
)
1358 set_texgen_matrix( rmesa
, unit
,
1359 (texUnit
->TexGenEnabled
& S_BIT
) ? reflect
: I
,
1360 (texUnit
->TexGenEnabled
& T_BIT
) ? reflect
+ 4 : I
+ 4,
1361 (texUnit
->TexGenEnabled
& R_BIT
) ? reflect
+ 8 : I
+ 8,
1365 case GL_NORMAL_MAP_NV
:
1366 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1367 tgi
|= R200_TEXGEN_INPUT_EYE_NORMAL
<<inputshift
;
1371 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1372 tgi
|= R200_TEXGEN_INPUT_SPHERE
<<inputshift
;
1376 /* All texgen units were disabled, so just pass coords through. */
1377 tgi
|= unit
<< inputshift
;
1381 /* Unsupported mode, fallback:
1383 if (R200_DEBUG
& DEBUG_FALLBACKS
)
1384 fprintf(stderr
, "fallback unsupported texgen, %d\n",
1385 texUnit
->GenS
.Mode
);
1389 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
1390 rmesa
->TexGenCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
1392 if (tgi
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] ||
1393 tgcm
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
])
1395 R200_STATECHANGE(rmesa
, tcg
);
1396 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] = tgi
;
1397 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] = tgcm
;
1403 void set_re_cntl_d3d( GLcontext
*ctx
, int unit
, GLboolean use_d3d
)
1405 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1409 re_cntl
= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] & ~(R200_VTX_STQ0_D3D
<< (2 * unit
));
1411 re_cntl
|= R200_VTX_STQ0_D3D
<< (2 * unit
);
1413 if ( re_cntl
!= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] ) {
1414 R200_STATECHANGE( rmesa
, set
);
1415 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] = re_cntl
;
1420 * Compute the cached hardware register values for the given texture object.
1422 * \param rmesa Context pointer
1423 * \param t the r300 texture object
1425 static void setup_hardware_state(r200ContextPtr rmesa
, radeonTexObj
*t
)
1427 int firstlevel
= t
->mt
? t
->mt
->firstLevel
: 0;
1428 const struct gl_texture_image
*firstImage
= t
->base
.Image
[0][firstlevel
];
1429 GLint log2Width
, log2Height
, log2Depth
, texelBytes
;
1435 log2Width
= firstImage
->WidthLog2
;
1436 log2Height
= firstImage
->HeightLog2
;
1437 log2Depth
= firstImage
->DepthLog2
;
1438 texelBytes
= firstImage
->TexFormat
->TexelBytes
;
1441 if (!t
->image_override
) {
1442 if (VALID_FORMAT(firstImage
->TexFormat
->MesaFormat
)) {
1443 const struct tx_table
*table
= _mesa_little_endian() ? tx_table_le
:
1446 t
->pp_txformat
&= ~(R200_TXFORMAT_FORMAT_MASK
|
1447 R200_TXFORMAT_ALPHA_IN_MAP
);
1448 t
->pp_txfilter
&= ~R200_YUV_TO_RGB
;
1450 t
->pp_txformat
|= table
[ firstImage
->TexFormat
->MesaFormat
].format
;
1451 t
->pp_txfilter
|= table
[ firstImage
->TexFormat
->MesaFormat
].filter
;
1453 _mesa_problem(NULL
, "unexpected texture format in %s",
1459 t
->pp_txfilter
&= ~R200_MAX_MIP_LEVEL_MASK
;
1460 t
->pp_txfilter
|= (t
->mt
->lastLevel
- t
->mt
->firstLevel
) << R200_MAX_MIP_LEVEL_SHIFT
;
1462 t
->pp_txformat
&= ~(R200_TXFORMAT_WIDTH_MASK
|
1463 R200_TXFORMAT_HEIGHT_MASK
|
1464 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
1465 R200_TXFORMAT_F5_WIDTH_MASK
|
1466 R200_TXFORMAT_F5_HEIGHT_MASK
);
1467 t
->pp_txformat
|= ((log2Width
<< R200_TXFORMAT_WIDTH_SHIFT
) |
1468 (log2Height
<< R200_TXFORMAT_HEIGHT_SHIFT
));
1472 t
->pp_txformat_x
&= ~(R200_DEPTH_LOG2_MASK
| R200_TEXCOORD_MASK
);
1473 if (t
->base
.Target
== GL_TEXTURE_3D
) {
1474 t
->pp_txformat_x
|= (log2Depth
<< R200_DEPTH_LOG2_SHIFT
);
1475 t
->pp_txformat_x
|= R200_TEXCOORD_VOLUME
;
1478 else if (t
->base
.Target
== GL_TEXTURE_CUBE_MAP
) {
1479 ASSERT(log2Width
== log2Height
);
1480 t
->pp_txformat
|= ((log2Width
<< R200_TXFORMAT_F5_WIDTH_SHIFT
) |
1481 (log2Height
<< R200_TXFORMAT_F5_HEIGHT_SHIFT
) |
1482 /* don't think we need this bit, if it exists at all - fglrx does not set it */
1483 (R200_TXFORMAT_CUBIC_MAP_ENABLE
));
1484 t
->pp_txformat_x
|= R200_TEXCOORD_CUBIC_ENV
;
1485 t
->pp_cubic_faces
= ((log2Width
<< R200_FACE_WIDTH_1_SHIFT
) |
1486 (log2Height
<< R200_FACE_HEIGHT_1_SHIFT
) |
1487 (log2Width
<< R200_FACE_WIDTH_2_SHIFT
) |
1488 (log2Height
<< R200_FACE_HEIGHT_2_SHIFT
) |
1489 (log2Width
<< R200_FACE_WIDTH_3_SHIFT
) |
1490 (log2Height
<< R200_FACE_HEIGHT_3_SHIFT
) |
1491 (log2Width
<< R200_FACE_WIDTH_4_SHIFT
) |
1492 (log2Height
<< R200_FACE_HEIGHT_4_SHIFT
));
1495 /* If we don't in fact send enough texture coordinates, q will be 1,
1496 * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
1498 t
->pp_txformat_x
|= R200_TEXCOORD_PROJ
;
1501 t
->pp_txsize
= (((firstImage
->Width
- 1) << R200_PP_TX_WIDTHMASK_SHIFT
)
1502 | ((firstImage
->Height
- 1) << R200_PP_TX_HEIGHTMASK_SHIFT
));
1504 if ( !t
->image_override
) {
1505 if (firstImage
->IsCompressed
)
1506 t
->pp_txpitch
= (firstImage
->Width
+ 63) & ~(63);
1508 t
->pp_txpitch
= ((firstImage
->Width
* texelBytes
) + 63) & ~(63);
1509 t
->pp_txpitch
-= 32;
1512 if (t
->base
.Target
== GL_TEXTURE_RECTANGLE_NV
) {
1513 t
->pp_txformat
|= R200_TXFORMAT_NON_POWER2
;
1518 static GLboolean
r200_validate_texture(GLcontext
*ctx
, struct gl_texture_object
*texObj
, int unit
)
1520 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1521 radeonTexObj
*t
= radeon_tex_obj(texObj
);
1523 if (!radeon_validate_texture_miptree(ctx
, texObj
))
1526 r200_validate_texgen(ctx
, unit
);
1527 /* Configure the hardware registers (more precisely, the cached version
1528 * of the hardware registers). */
1529 setup_hardware_state(rmesa
, t
);
1531 if (texObj
->Target
== GL_TEXTURE_RECTANGLE_NV
||
1532 texObj
->Target
== GL_TEXTURE_2D
||
1533 texObj
->Target
== GL_TEXTURE_1D
)
1534 set_re_cntl_d3d( ctx
, unit
, GL_FALSE
);
1536 set_re_cntl_d3d( ctx
, unit
, GL_TRUE
);
1537 R200_STATECHANGE( rmesa
, ctx
);
1538 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_0_ENABLE
<< unit
;
1540 R200_STATECHANGE( rmesa
, vtx
);
1541 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
1542 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] |= 4 << (unit
* 3);
1544 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1545 import_tex_obj_state( rmesa
, unit
, t
);
1547 if (rmesa
->recheck_texgen
[unit
]) {
1548 GLboolean fallback
= !r200_validate_texgen( ctx
, unit
);
1549 TCL_FALLBACK( ctx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), fallback
);
1550 rmesa
->recheck_texgen
[unit
] = 0;
1551 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE_MATRIX
;
1554 t
->validated
= GL_TRUE
;
1556 FALLBACK( rmesa
, RADEON_FALLBACK_BORDER_MODE
, t
->border_fallback
);
1558 return !t
->border_fallback
;
1561 static GLboolean
r200UpdateTextureUnit(GLcontext
*ctx
, int unit
)
1563 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1564 GLuint unitneeded
= rmesa
->state
.texture
.unit
[unit
].unitneeded
;
1567 /* disable the unit */
1568 disable_tex_obj_state(rmesa
, unit
);
1572 if (!r200_validate_texture(ctx
, ctx
->Texture
.Unit
[unit
]._Current
, unit
)) {
1574 "failed to validate texture for unit %d.\n",
1576 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
1580 rmesa
->state
.texture
.unit
[unit
].texobj
= radeon_tex_obj(ctx
->Texture
.Unit
[unit
]._Current
);
1585 void r200UpdateTextureState( GLcontext
*ctx
)
1587 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1591 /* NOTE: must not manipulate rmesa->state.texture.unit[].unitneeded or
1592 rmesa->state.envneeded before a R200_STATECHANGE (or R200_NEWPRIM) since
1593 we use these to determine if we want to emit the corresponding state
1595 R200_NEWPRIM( rmesa
);
1597 if (ctx
->ATIFragmentShader
._Enabled
) {
1599 for (i
= 0; i
< R200_MAX_TEXTURE_UNITS
; i
++) {
1600 rmesa
->state
.texture
.unit
[i
].unitneeded
= ctx
->Texture
.Unit
[i
]._ReallyEnabled
;
1605 ok
= r200UpdateAllTexEnv( ctx
);
1608 ok
= (r200UpdateTextureUnit( ctx
, 0 ) &&
1609 r200UpdateTextureUnit( ctx
, 1 ) &&
1610 r200UpdateTextureUnit( ctx
, 2 ) &&
1611 r200UpdateTextureUnit( ctx
, 3 ) &&
1612 r200UpdateTextureUnit( ctx
, 4 ) &&
1613 r200UpdateTextureUnit( ctx
, 5 ));
1616 if (ok
&& ctx
->ATIFragmentShader
._Enabled
) {
1617 r200UpdateFragmentShader(ctx
);
1620 FALLBACK( rmesa
, R200_FALLBACK_TEXTURE
, !ok
);
1622 if (rmesa
->radeon
.TclFallback
)
1623 r200ChooseVertexState( ctx
);
1626 if (rmesa
->radeon
.radeonScreen
->chip_family
== CHIP_FAMILY_R200
) {
1629 * T0 hang workaround -------------
1630 * not needed for r200 derivatives
1632 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_ENABLE_MASK
) == R200_TEX_0_ENABLE
&&
1633 (rmesa
->hw
.tex
[0].cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) > R200_MIN_FILTER_LINEAR
) {
1635 R200_STATECHANGE(rmesa
, ctx
);
1636 R200_STATECHANGE(rmesa
, tex
[1]);
1637 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_1_ENABLE
;
1638 if (!(rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] & R200_PPX_TEX_1_ENABLE
))
1639 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1640 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] |= R200_TXFORMAT_LOOKUP_DISABLE
;
1642 else if (!ctx
->ATIFragmentShader
._Enabled
) {
1643 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
) &&
1644 (rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] & R200_TXFORMAT_LOOKUP_DISABLE
)) {
1645 R200_STATECHANGE(rmesa
, tex
[1]);
1646 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~R200_TXFORMAT_LOOKUP_DISABLE
;
1649 /* do the same workaround for the first pass of a fragment shader.
1650 * completely unknown if necessary / sufficient.
1652 if ((rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] & R200_PPX_TEX_ENABLE_MASK
) == R200_PPX_TEX_0_ENABLE
&&
1653 (rmesa
->hw
.tex
[0].cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) > R200_MIN_FILTER_LINEAR
) {
1655 R200_STATECHANGE(rmesa
, cst
);
1656 R200_STATECHANGE(rmesa
, tex
[1]);
1657 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] |= R200_PPX_TEX_1_ENABLE
;
1658 if (!(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
))
1659 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1660 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXMULTI_CTL
] |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE
;
1663 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1664 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1665 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1666 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1667 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1668 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1669 R200_MIN_FILTER_LINEAR)) {
1670 R200_STATECHANGE(rmesa, ctx);
1671 R200_STATECHANGE(rmesa, tex[i+1]);
1672 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1673 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1674 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1677 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1678 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1679 R200_STATECHANGE(rmesa, tex[i+1]);
1680 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1686 * Texture cache LRU hang workaround -------------
1687 * not needed for r200 derivatives
1688 * hopefully this covers first pass of a shader as well
1691 /* While the cases below attempt to only enable the workaround in the
1692 * specific cases necessary, they were insufficient. See bugzilla #1519,
1693 * #729, #814. Tests with quake3 showed no impact on performance.
1698 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) &&
1699 ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1701 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1702 ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1704 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1705 ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1711 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) &&
1712 ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1714 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1715 ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1717 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1718 ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1724 if (dbg
!= rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
]) {
1725 R200_STATECHANGE( rmesa
, tam
);
1726 rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
] = dbg
;
1727 if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg
);