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/teximage.h"
40 #include "main/texobj.h"
41 #include "main/enums.h"
43 #include "radeon_common.h"
44 #include "radeon_mipmap_tree.h"
45 #include "r200_context.h"
46 #include "r200_state.h"
47 #include "r200_ioctl.h"
48 #include "r200_swtcl.h"
53 #define R200_TXFORMAT_A8 R200_TXFORMAT_I8
54 #define R200_TXFORMAT_L8 R200_TXFORMAT_I8
55 #define R200_TXFORMAT_AL88 R200_TXFORMAT_AI88
56 #define R200_TXFORMAT_YCBCR R200_TXFORMAT_YVYU422
57 #define R200_TXFORMAT_YCBCR_REV R200_TXFORMAT_VYUY422
58 #define R200_TXFORMAT_RGB_DXT1 R200_TXFORMAT_DXT1
59 #define R200_TXFORMAT_RGBA_DXT1 R200_TXFORMAT_DXT1
60 #define R200_TXFORMAT_RGBA_DXT3 R200_TXFORMAT_DXT23
61 #define R200_TXFORMAT_RGBA_DXT5 R200_TXFORMAT_DXT45
64 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, 0 }
65 #define _COLOR_REV(f) \
66 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f, 0 }
68 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
69 #define _ALPHA_REV(f) \
70 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
72 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, R200_YUV_TO_RGB }
74 [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
75 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
76 && (tx_table_be[f].format != 0xffffffff) )
79 GLuint format
, filter
;
82 static const struct tx_table tx_table_be
[] =
84 [ MESA_FORMAT_RGBA8888
] = { R200_TXFORMAT_ABGR8888
| R200_TXFORMAT_ALPHA_IN_MAP
, 0 },
110 static const struct tx_table tx_table_le
[] =
113 [ MESA_FORMAT_RGBA8888_REV
] = { R200_TXFORMAT_ABGR8888
| R200_TXFORMAT_ALPHA_IN_MAP
, 0 },
115 _ALPHA_REV(ARGB8888
),
116 [ MESA_FORMAT_RGB888
] = { R200_TXFORMAT_ARGB8888
, 0 },
120 _ALPHA_REV(ARGB4444
),
122 _ALPHA_REV(ARGB1555
),
142 /* ================================================================
143 * Texture combine functions
146 /* GL_ARB_texture_env_combine support
149 /* The color tables have combine functions for GL_SRC_COLOR,
150 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
152 static GLuint r200_register_color
[][R200_MAX_TEXTURE_UNITS
] =
155 R200_TXC_ARG_A_R0_COLOR
,
156 R200_TXC_ARG_A_R1_COLOR
,
157 R200_TXC_ARG_A_R2_COLOR
,
158 R200_TXC_ARG_A_R3_COLOR
,
159 R200_TXC_ARG_A_R4_COLOR
,
160 R200_TXC_ARG_A_R5_COLOR
163 R200_TXC_ARG_A_R0_COLOR
| R200_TXC_COMP_ARG_A
,
164 R200_TXC_ARG_A_R1_COLOR
| R200_TXC_COMP_ARG_A
,
165 R200_TXC_ARG_A_R2_COLOR
| R200_TXC_COMP_ARG_A
,
166 R200_TXC_ARG_A_R3_COLOR
| R200_TXC_COMP_ARG_A
,
167 R200_TXC_ARG_A_R4_COLOR
| R200_TXC_COMP_ARG_A
,
168 R200_TXC_ARG_A_R5_COLOR
| R200_TXC_COMP_ARG_A
171 R200_TXC_ARG_A_R0_ALPHA
,
172 R200_TXC_ARG_A_R1_ALPHA
,
173 R200_TXC_ARG_A_R2_ALPHA
,
174 R200_TXC_ARG_A_R3_ALPHA
,
175 R200_TXC_ARG_A_R4_ALPHA
,
176 R200_TXC_ARG_A_R5_ALPHA
179 R200_TXC_ARG_A_R0_ALPHA
| R200_TXC_COMP_ARG_A
,
180 R200_TXC_ARG_A_R1_ALPHA
| R200_TXC_COMP_ARG_A
,
181 R200_TXC_ARG_A_R2_ALPHA
| R200_TXC_COMP_ARG_A
,
182 R200_TXC_ARG_A_R3_ALPHA
| R200_TXC_COMP_ARG_A
,
183 R200_TXC_ARG_A_R4_ALPHA
| R200_TXC_COMP_ARG_A
,
184 R200_TXC_ARG_A_R5_ALPHA
| R200_TXC_COMP_ARG_A
188 static GLuint r200_tfactor_color
[] =
190 R200_TXC_ARG_A_TFACTOR_COLOR
,
191 R200_TXC_ARG_A_TFACTOR_COLOR
| R200_TXC_COMP_ARG_A
,
192 R200_TXC_ARG_A_TFACTOR_ALPHA
,
193 R200_TXC_ARG_A_TFACTOR_ALPHA
| R200_TXC_COMP_ARG_A
196 static GLuint r200_tfactor1_color
[] =
198 R200_TXC_ARG_A_TFACTOR1_COLOR
,
199 R200_TXC_ARG_A_TFACTOR1_COLOR
| R200_TXC_COMP_ARG_A
,
200 R200_TXC_ARG_A_TFACTOR1_ALPHA
,
201 R200_TXC_ARG_A_TFACTOR1_ALPHA
| R200_TXC_COMP_ARG_A
204 static GLuint r200_primary_color
[] =
206 R200_TXC_ARG_A_DIFFUSE_COLOR
,
207 R200_TXC_ARG_A_DIFFUSE_COLOR
| R200_TXC_COMP_ARG_A
,
208 R200_TXC_ARG_A_DIFFUSE_ALPHA
,
209 R200_TXC_ARG_A_DIFFUSE_ALPHA
| R200_TXC_COMP_ARG_A
212 /* GL_ZERO table - indices 0-3
213 * GL_ONE table - indices 1-4
215 static GLuint r200_zero_color
[] =
218 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
220 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
224 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
226 static GLuint r200_register_alpha
[][R200_MAX_TEXTURE_UNITS
] =
229 R200_TXA_ARG_A_R0_ALPHA
,
230 R200_TXA_ARG_A_R1_ALPHA
,
231 R200_TXA_ARG_A_R2_ALPHA
,
232 R200_TXA_ARG_A_R3_ALPHA
,
233 R200_TXA_ARG_A_R4_ALPHA
,
234 R200_TXA_ARG_A_R5_ALPHA
237 R200_TXA_ARG_A_R0_ALPHA
| R200_TXA_COMP_ARG_A
,
238 R200_TXA_ARG_A_R1_ALPHA
| R200_TXA_COMP_ARG_A
,
239 R200_TXA_ARG_A_R2_ALPHA
| R200_TXA_COMP_ARG_A
,
240 R200_TXA_ARG_A_R3_ALPHA
| R200_TXA_COMP_ARG_A
,
241 R200_TXA_ARG_A_R4_ALPHA
| R200_TXA_COMP_ARG_A
,
242 R200_TXA_ARG_A_R5_ALPHA
| R200_TXA_COMP_ARG_A
246 static GLuint r200_tfactor_alpha
[] =
248 R200_TXA_ARG_A_TFACTOR_ALPHA
,
249 R200_TXA_ARG_A_TFACTOR_ALPHA
| R200_TXA_COMP_ARG_A
252 static GLuint r200_tfactor1_alpha
[] =
254 R200_TXA_ARG_A_TFACTOR1_ALPHA
,
255 R200_TXA_ARG_A_TFACTOR1_ALPHA
| R200_TXA_COMP_ARG_A
258 static GLuint r200_primary_alpha
[] =
260 R200_TXA_ARG_A_DIFFUSE_ALPHA
,
261 R200_TXA_ARG_A_DIFFUSE_ALPHA
| R200_TXA_COMP_ARG_A
264 /* GL_ZERO table - indices 0-1
265 * GL_ONE table - indices 1-2
267 static GLuint r200_zero_alpha
[] =
270 R200_TXA_ARG_A_ZERO
| R200_TXA_COMP_ARG_A
,
275 /* Extract the arg from slot A, shift it into the correct argument slot
276 * and set the corresponding complement bit.
278 #define R200_COLOR_ARG( n, arg ) \
281 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
282 << R200_TXC_ARG_##arg##_SHIFT); \
284 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
285 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
288 #define R200_ALPHA_ARG( n, arg ) \
291 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
292 << R200_TXA_ARG_##arg##_SHIFT); \
294 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
295 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
299 /* ================================================================
300 * Texture unit state management
303 static GLboolean
r200UpdateTextureEnv( struct gl_context
*ctx
, int unit
, int slot
, GLuint replaceargs
)
305 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
306 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
307 GLuint color_combine
, alpha_combine
;
308 GLuint color_scale
= rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] &
309 ~(R200_TXC_SCALE_MASK
| R200_TXC_OUTPUT_REG_MASK
| R200_TXC_TFACTOR_SEL_MASK
|
310 R200_TXC_TFACTOR1_SEL_MASK
);
311 GLuint alpha_scale
= rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] &
312 ~(R200_TXA_DOT_ALPHA
| R200_TXA_SCALE_MASK
| R200_TXA_OUTPUT_REG_MASK
|
313 R200_TXA_TFACTOR_SEL_MASK
| R200_TXA_TFACTOR1_SEL_MASK
);
315 /* texUnit->_Current can be NULL if and only if the texture unit is
316 * not actually enabled.
318 assert( (texUnit
->_ReallyEnabled
== 0)
319 || (texUnit
->_Current
!= NULL
) );
321 if ( R200_DEBUG
& RADEON_TEXTURE
) {
322 fprintf( stderr
, "%s( %p, %d )\n", __FUNCTION__
, (void *)ctx
, unit
);
325 /* Set the texture environment state. Isn't this nice and clean?
326 * The chip will automagically set the texture alpha to 0xff when
327 * the texture format does not include an alpha component. This
328 * reduces the amount of special-casing we have to do, alpha-only
329 * textures being a notable exception.
332 color_scale
|= ((rmesa
->state
.texture
.unit
[unit
].outputreg
+ 1) << R200_TXC_OUTPUT_REG_SHIFT
) |
333 (unit
<< R200_TXC_TFACTOR_SEL_SHIFT
) |
334 (replaceargs
<< R200_TXC_TFACTOR1_SEL_SHIFT
);
335 alpha_scale
|= ((rmesa
->state
.texture
.unit
[unit
].outputreg
+ 1) << R200_TXA_OUTPUT_REG_SHIFT
) |
336 (unit
<< R200_TXA_TFACTOR_SEL_SHIFT
) |
337 (replaceargs
<< R200_TXA_TFACTOR1_SEL_SHIFT
);
339 if ( !texUnit
->_ReallyEnabled
) {
341 color_combine
= R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
342 | R200_TXC_ARG_C_DIFFUSE_COLOR
| R200_TXC_OP_MADD
;
343 alpha_combine
= R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
344 | R200_TXA_ARG_C_DIFFUSE_ALPHA
| R200_TXA_OP_MADD
;
347 GLuint color_arg
[3], alpha_arg
[3];
349 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
350 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
351 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
352 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
355 const GLint replaceoprgb
=
356 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->OperandRGB
[0] - GL_SRC_COLOR
;
357 const GLint replaceopa
=
358 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->OperandA
[0] - GL_SRC_ALPHA
;
361 * Extract the color and alpha combine function arguments.
363 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
364 GLint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
] - GL_SRC_COLOR
;
365 const GLint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
370 color_arg
[i
] = r200_register_color
[op
][unit
];
373 color_arg
[i
] = r200_tfactor_color
[op
];
375 case GL_PRIMARY_COLOR
:
376 color_arg
[i
] = r200_primary_color
[op
];
379 if (replaceargs
!= unit
) {
380 const GLint srcRGBreplace
=
381 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->SourceRGB
[0];
383 op
= op
^ replaceopa
;
386 op
= op
^ replaceoprgb
;
388 switch (srcRGBreplace
) {
390 color_arg
[i
] = r200_register_color
[op
][replaceargs
];
393 color_arg
[i
] = r200_tfactor1_color
[op
];
395 case GL_PRIMARY_COLOR
:
396 color_arg
[i
] = r200_primary_color
[op
];
400 color_arg
[i
] = r200_primary_color
[op
];
402 color_arg
[i
] = r200_register_color
[op
]
403 [rmesa
->state
.texture
.unit
[replaceargs
- 1].outputreg
];
406 color_arg
[i
] = r200_zero_color
[op
];
409 color_arg
[i
] = r200_zero_color
[op
+1];
417 color_arg
[i
] = r200_register_color
[op
][srcRGBreplace
- GL_TEXTURE0
];
425 color_arg
[i
] = r200_primary_color
[op
];
427 color_arg
[i
] = r200_register_color
[op
]
428 [rmesa
->state
.texture
.unit
[unit
- 1].outputreg
];
432 color_arg
[i
] = r200_zero_color
[op
];
435 color_arg
[i
] = r200_zero_color
[op
+1];
443 color_arg
[i
] = r200_register_color
[op
][srcRGBi
- GL_TEXTURE0
];
450 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
451 GLint op
= texUnit
->_CurrentCombine
->OperandA
[i
] - GL_SRC_ALPHA
;
452 const GLint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
457 alpha_arg
[i
] = r200_register_alpha
[op
][unit
];
460 alpha_arg
[i
] = r200_tfactor_alpha
[op
];
462 case GL_PRIMARY_COLOR
:
463 alpha_arg
[i
] = r200_primary_alpha
[op
];
466 if (replaceargs
!= unit
) {
467 const GLint srcAreplace
=
468 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->SourceA
[0];
469 op
= op
^ replaceopa
;
470 switch (srcAreplace
) {
472 alpha_arg
[i
] = r200_register_alpha
[op
][replaceargs
];
475 alpha_arg
[i
] = r200_tfactor1_alpha
[op
];
477 case GL_PRIMARY_COLOR
:
478 alpha_arg
[i
] = r200_primary_alpha
[op
];
482 alpha_arg
[i
] = r200_primary_alpha
[op
];
484 alpha_arg
[i
] = r200_register_alpha
[op
]
485 [rmesa
->state
.texture
.unit
[replaceargs
- 1].outputreg
];
488 alpha_arg
[i
] = r200_zero_alpha
[op
];
491 alpha_arg
[i
] = r200_zero_alpha
[op
+1];
499 alpha_arg
[i
] = r200_register_alpha
[op
][srcAreplace
- GL_TEXTURE0
];
507 alpha_arg
[i
] = r200_primary_alpha
[op
];
509 alpha_arg
[i
] = r200_register_alpha
[op
]
510 [rmesa
->state
.texture
.unit
[unit
- 1].outputreg
];
514 alpha_arg
[i
] = r200_zero_alpha
[op
];
517 alpha_arg
[i
] = r200_zero_alpha
[op
+1];
525 alpha_arg
[i
] = r200_register_alpha
[op
][srcAi
- GL_TEXTURE0
];
533 * Build up the color and alpha combine functions.
535 switch ( texUnit
->_CurrentCombine
->ModeRGB
) {
537 color_combine
= (R200_TXC_ARG_A_ZERO
|
538 R200_TXC_ARG_B_ZERO
|
540 R200_COLOR_ARG( 0, C
);
543 color_combine
= (R200_TXC_ARG_C_ZERO
|
545 R200_COLOR_ARG( 0, A
);
546 R200_COLOR_ARG( 1, B
);
549 color_combine
= (R200_TXC_ARG_B_ZERO
|
550 R200_TXC_COMP_ARG_B
|
552 R200_COLOR_ARG( 0, A
);
553 R200_COLOR_ARG( 1, C
);
556 color_combine
= (R200_TXC_ARG_B_ZERO
|
557 R200_TXC_COMP_ARG_B
|
558 R200_TXC_BIAS_ARG_C
| /* new */
559 R200_TXC_OP_MADD
); /* was ADDSIGNED */
560 R200_COLOR_ARG( 0, A
);
561 R200_COLOR_ARG( 1, C
);
564 color_combine
= (R200_TXC_ARG_B_ZERO
|
565 R200_TXC_COMP_ARG_B
|
568 R200_COLOR_ARG( 0, A
);
569 R200_COLOR_ARG( 1, C
);
572 color_combine
= (R200_TXC_OP_LERP
);
573 R200_COLOR_ARG( 0, B
);
574 R200_COLOR_ARG( 1, A
);
575 R200_COLOR_ARG( 2, C
);
578 case GL_DOT3_RGB_EXT
:
579 case GL_DOT3_RGBA_EXT
:
580 /* The EXT version of the DOT3 extension does not support the
581 * scale factor, but the ARB version (and the version in OpenGL
589 /* DOT3 works differently on R200 than on R100. On R100, just
590 * setting the DOT3 mode did everything for you. On R200, the
591 * driver has to enable the biasing and scale in the inputs to
592 * put them in the proper [-1,1] range. This is what the 4x and
593 * the -0.5 in the DOT3 spec do. The post-scale is then set
597 color_combine
= (R200_TXC_ARG_C_ZERO
|
599 R200_TXC_BIAS_ARG_A
|
600 R200_TXC_BIAS_ARG_B
|
601 R200_TXC_SCALE_ARG_A
|
602 R200_TXC_SCALE_ARG_B
);
603 R200_COLOR_ARG( 0, A
);
604 R200_COLOR_ARG( 1, B
);
607 case GL_MODULATE_ADD_ATI
:
608 color_combine
= (R200_TXC_OP_MADD
);
609 R200_COLOR_ARG( 0, A
);
610 R200_COLOR_ARG( 1, C
);
611 R200_COLOR_ARG( 2, B
);
613 case GL_MODULATE_SIGNED_ADD_ATI
:
614 color_combine
= (R200_TXC_BIAS_ARG_C
| /* new */
615 R200_TXC_OP_MADD
); /* was ADDSIGNED */
616 R200_COLOR_ARG( 0, A
);
617 R200_COLOR_ARG( 1, C
);
618 R200_COLOR_ARG( 2, B
);
620 case GL_MODULATE_SUBTRACT_ATI
:
621 color_combine
= (R200_TXC_NEG_ARG_C
|
623 R200_COLOR_ARG( 0, A
);
624 R200_COLOR_ARG( 1, C
);
625 R200_COLOR_ARG( 2, B
);
631 switch ( texUnit
->_CurrentCombine
->ModeA
) {
633 alpha_combine
= (R200_TXA_ARG_A_ZERO
|
634 R200_TXA_ARG_B_ZERO
|
636 R200_ALPHA_ARG( 0, C
);
639 alpha_combine
= (R200_TXA_ARG_C_ZERO
|
641 R200_ALPHA_ARG( 0, A
);
642 R200_ALPHA_ARG( 1, B
);
645 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
646 R200_TXA_COMP_ARG_B
|
648 R200_ALPHA_ARG( 0, A
);
649 R200_ALPHA_ARG( 1, C
);
652 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
653 R200_TXA_COMP_ARG_B
|
654 R200_TXA_BIAS_ARG_C
| /* new */
655 R200_TXA_OP_MADD
); /* was ADDSIGNED */
656 R200_ALPHA_ARG( 0, A
);
657 R200_ALPHA_ARG( 1, C
);
660 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
661 R200_TXA_COMP_ARG_B
|
664 R200_ALPHA_ARG( 0, A
);
665 R200_ALPHA_ARG( 1, C
);
668 alpha_combine
= (R200_TXA_OP_LERP
);
669 R200_ALPHA_ARG( 0, B
);
670 R200_ALPHA_ARG( 1, A
);
671 R200_ALPHA_ARG( 2, C
);
674 case GL_MODULATE_ADD_ATI
:
675 alpha_combine
= (R200_TXA_OP_MADD
);
676 R200_ALPHA_ARG( 0, A
);
677 R200_ALPHA_ARG( 1, C
);
678 R200_ALPHA_ARG( 2, B
);
680 case GL_MODULATE_SIGNED_ADD_ATI
:
681 alpha_combine
= (R200_TXA_BIAS_ARG_C
| /* new */
682 R200_TXA_OP_MADD
); /* was ADDSIGNED */
683 R200_ALPHA_ARG( 0, A
);
684 R200_ALPHA_ARG( 1, C
);
685 R200_ALPHA_ARG( 2, B
);
687 case GL_MODULATE_SUBTRACT_ATI
:
688 alpha_combine
= (R200_TXA_NEG_ARG_C
|
690 R200_ALPHA_ARG( 0, A
);
691 R200_ALPHA_ARG( 1, C
);
692 R200_ALPHA_ARG( 2, B
);
698 if ( (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
699 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ) {
700 alpha_scale
|= R200_TXA_DOT_ALPHA
;
705 * Apply the scale factor.
707 color_scale
|= (RGBshift
<< R200_TXC_SCALE_SHIFT
);
708 alpha_scale
|= (Ashift
<< R200_TXA_SCALE_SHIFT
);
714 if ( rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND
] != color_combine
||
715 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND
] != alpha_combine
||
716 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] != color_scale
||
717 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] != alpha_scale
) {
718 R200_STATECHANGE( rmesa
, pix
[slot
] );
719 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND
] = color_combine
;
720 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND
] = alpha_combine
;
721 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] = color_scale
;
722 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] = alpha_scale
;
728 void r200SetTexBuffer2(__DRIcontext
*pDRICtx
, GLint target
, GLint texture_format
,
729 __DRIdrawable
*dPriv
)
731 struct gl_texture_unit
*texUnit
;
732 struct gl_texture_object
*texObj
;
733 struct gl_texture_image
*texImage
;
734 struct radeon_renderbuffer
*rb
;
735 radeon_texture_image
*rImage
;
736 radeonContextPtr radeon
;
737 struct radeon_framebuffer
*rfb
;
742 radeon
= pDRICtx
->driverPrivate
;
744 rfb
= dPriv
->driverPrivate
;
745 texUnit
= &radeon
->glCtx
.Texture
.Unit
[radeon
->glCtx
.Texture
.CurrentUnit
];
746 texObj
= _mesa_select_tex_object(&radeon
->glCtx
, texUnit
, target
);
747 texImage
= _mesa_get_tex_image(&radeon
->glCtx
, texObj
, target
, 0);
749 rImage
= get_radeon_texture_image(texImage
);
750 t
= radeon_tex_obj(texObj
);
755 radeon_update_renderbuffers(pDRICtx
, dPriv
, GL_TRUE
);
756 rb
= rfb
->color_rb
[0];
757 if (rb
->bo
== NULL
) {
758 /* Failed to BO for the buffer */
762 _mesa_lock_texture(&radeon
->glCtx
, texObj
);
764 radeon_bo_unref(t
->bo
);
768 radeon_bo_unref(rImage
->bo
);
772 radeon_miptree_unreference(&t
->mt
);
773 radeon_miptree_unreference(&rImage
->mt
);
776 radeon_bo_ref(rImage
->bo
);
778 radeon_bo_ref(t
->bo
);
780 t
->image_override
= GL_TRUE
;
781 t
->override_offset
= 0;
782 t
->pp_txpitch
&= (1 << 13) -1;
783 pitch_val
= rb
->pitch
;
786 if (texture_format
== __DRI_TEXTURE_FORMAT_RGB
) {
787 texFormat
= MESA_FORMAT_RGB888
;
788 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_RGB888
].format
;
791 texFormat
= MESA_FORMAT_ARGB8888
;
792 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_ARGB8888
].format
;
794 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_ARGB8888
].filter
;
798 texFormat
= MESA_FORMAT_RGB888
;
799 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_RGB888
].format
;
800 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_RGB888
].filter
;
803 texFormat
= MESA_FORMAT_RGB565
;
804 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_RGB565
].format
;
805 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_RGB565
].filter
;
809 _mesa_init_teximage_fields(&radeon
->glCtx
, texImage
,
810 rb
->base
.Base
.Width
, rb
->base
.Base
.Height
,
813 rImage
->base
.RowStride
= rb
->pitch
/ rb
->cpp
;
816 t
->pp_txsize
= ((rb
->base
.Base
.Width
- 1) << RADEON_TEX_USIZE_SHIFT
)
817 | ((rb
->base
.Base
.Height
- 1) << RADEON_TEX_VSIZE_SHIFT
);
819 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
820 t
->pp_txformat
|= R200_TXFORMAT_NON_POWER2
;
821 t
->pp_txpitch
= pitch_val
;
824 t
->pp_txformat
&= ~(R200_TXFORMAT_WIDTH_MASK
|
825 R200_TXFORMAT_HEIGHT_MASK
|
826 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
827 R200_TXFORMAT_F5_WIDTH_MASK
|
828 R200_TXFORMAT_F5_HEIGHT_MASK
);
829 t
->pp_txformat
|= ((texImage
->WidthLog2
<< R200_TXFORMAT_WIDTH_SHIFT
) |
830 (texImage
->HeightLog2
<< R200_TXFORMAT_HEIGHT_SHIFT
));
833 t
->validated
= GL_TRUE
;
834 _mesa_unlock_texture(&radeon
->glCtx
, texObj
);
839 void r200SetTexBuffer(__DRIcontext
*pDRICtx
, GLint target
, __DRIdrawable
*dPriv
)
841 r200SetTexBuffer2(pDRICtx
, target
, __DRI_TEXTURE_FORMAT_RGBA
, dPriv
);
848 static GLboolean
r200UpdateAllTexEnv( struct gl_context
*ctx
)
850 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
851 GLint i
, j
, currslot
;
852 GLint maxunitused
= -1;
853 GLboolean texregfree
[6] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
854 GLubyte stageref
[7] = {0, 0, 0, 0, 0, 0, 0};
855 GLint nextunit
[R200_MAX_TEXTURE_UNITS
] = {0, 0, 0, 0, 0, 0};
856 GLint currentnext
= -1;
859 /* find highest used unit */
860 for ( j
= 0; j
< R200_MAX_TEXTURE_UNITS
; j
++) {
861 if (ctx
->Texture
.Unit
[j
]._ReallyEnabled
) {
865 stageref
[maxunitused
+ 1] = REF_COLOR
| REF_ALPHA
;
867 for ( j
= maxunitused
; j
>= 0; j
-- ) {
868 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[j
];
870 rmesa
->state
.texture
.unit
[j
].outputreg
= -1;
872 if (stageref
[j
+ 1]) {
874 /* use the lowest available reg. That gets us automatically reg0 for the last stage.
875 need this even for disabled units, as it may get referenced due to the replace
877 for ( i
= 0 ; i
< R200_MAX_TEXTURE_UNITS
; i
++ ) {
879 rmesa
->state
.texture
.unit
[j
].outputreg
= i
;
883 if (rmesa
->state
.texture
.unit
[j
].outputreg
== -1) {
884 /* no more free regs we can use. Need a fallback :-( */
888 nextunit
[j
] = currentnext
;
890 if (!texUnit
->_ReallyEnabled
) {
891 /* the not enabled stages are referenced "indirectly",
892 must not cut off the lower stages */
893 stageref
[j
] = REF_COLOR
| REF_ALPHA
;
898 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
899 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
900 const GLboolean isdot3rgba
= (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ||
901 (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
);
904 /* check if we need the color part, special case for dot3_rgba
905 as if only the alpha part is referenced later on it still is using the color part */
906 if ((stageref
[j
+ 1] & REF_COLOR
) || isdot3rgba
) {
907 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
908 const GLuint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
909 const GLuint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
];
912 /* op 0/1 are referencing color, op 2/3 alpha */
913 stageref
[j
] |= (op
>> 1) + 1;
916 texregfree
[j
] = GL_FALSE
;
924 texregfree
[srcRGBi
- GL_TEXTURE0
] = GL_FALSE
;
926 default: /* don't care about other sources here */
932 /* alpha args are ignored for dot3_rgba */
933 if ((stageref
[j
+ 1] & REF_ALPHA
) && !isdot3rgba
) {
935 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
936 const GLuint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
939 stageref
[j
] |= REF_ALPHA
;
942 texregfree
[j
] = GL_FALSE
;
950 texregfree
[srcAi
- GL_TEXTURE0
] = GL_FALSE
;
952 default: /* don't care about other sources here */
960 /* don't enable texture sampling for units if the result is not used */
961 for (i
= 0; i
< R200_MAX_TEXTURE_UNITS
; i
++) {
962 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
&& !texregfree
[i
])
963 rmesa
->state
.texture
.unit
[i
].unitneeded
= ctx
->Texture
.Unit
[i
]._ReallyEnabled
;
964 else rmesa
->state
.texture
.unit
[i
].unitneeded
= 0;
969 rmesa
->state
.envneeded
= 1;
972 while ((i
<= maxunitused
) && (i
>= 0)) {
973 /* only output instruction if the results are referenced */
974 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
&& stageref
[i
+1]) {
975 GLuint replaceunit
= i
;
976 /* try to optimize GL_REPLACE away (only one level deep though) */
977 if ( (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ModeRGB
== GL_REPLACE
) &&
978 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ModeA
== GL_REPLACE
) &&
979 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ScaleShiftRGB
== 0) &&
980 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ScaleShiftA
== 0) &&
981 (nextunit
[i
] > 0) ) {
982 /* yippie! can optimize it away! */
987 /* need env instruction slot */
988 rmesa
->state
.envneeded
|= 1 << currslot
;
989 ok
= r200UpdateTextureEnv( ctx
, i
, currslot
, replaceunit
);
990 if (!ok
) return GL_FALSE
;
997 /* need one stage at least */
998 rmesa
->state
.texture
.unit
[0].outputreg
= 0;
999 ok
= r200UpdateTextureEnv( ctx
, 0, 0, 0 );
1002 R200_STATECHANGE( rmesa
, ctx
);
1003 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~(R200_TEX_BLEND_ENABLE_MASK
| R200_MULTI_PASS_ENABLE
);
1004 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= rmesa
->state
.envneeded
<< R200_TEX_BLEND_0_ENABLE_SHIFT
;
1013 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
1014 R200_MIN_FILTER_MASK | \
1015 R200_MAG_FILTER_MASK | \
1016 R200_MAX_ANISO_MASK | \
1018 R200_YUV_TEMPERATURE_MASK | \
1019 R200_CLAMP_S_MASK | \
1020 R200_CLAMP_T_MASK | \
1021 R200_BORDER_MODE_D3D )
1023 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
1024 R200_TXFORMAT_HEIGHT_MASK | \
1025 R200_TXFORMAT_FORMAT_MASK | \
1026 R200_TXFORMAT_F5_WIDTH_MASK | \
1027 R200_TXFORMAT_F5_HEIGHT_MASK | \
1028 R200_TXFORMAT_ALPHA_IN_MAP | \
1029 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
1030 R200_TXFORMAT_NON_POWER2)
1032 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
1033 R200_TEXCOORD_MASK | \
1034 R200_MIN_MIP_LEVEL_MASK | \
1035 R200_CLAMP_Q_MASK | \
1036 R200_VOLUME_FILTER_MASK)
1039 static void disable_tex_obj_state( r200ContextPtr rmesa
,
1043 R200_STATECHANGE( rmesa
, vtx
);
1044 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
1046 R200_STATECHANGE( rmesa
, ctx
);
1047 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~(R200_TEX_0_ENABLE
<< unit
);
1048 if (rmesa
->radeon
.TclFallback
& (R200_TCL_FALLBACK_TEXGEN_0
<<unit
)) {
1049 TCL_FALLBACK( &rmesa
->radeon
.glCtx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), GL_FALSE
);
1052 /* Actually want to keep all units less than max active texture
1053 * enabled, right? Fix this for >2 texunits.
1057 GLuint tmp
= rmesa
->TexGenEnabled
;
1059 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
1060 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
1061 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
1062 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1064 if (tmp
!= rmesa
->TexGenEnabled
) {
1065 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1066 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE_MATRIX
;
1070 static void import_tex_obj_state( r200ContextPtr rmesa
,
1072 radeonTexObjPtr texobj
)
1074 /* do not use RADEON_DB_STATE to avoid stale texture caches */
1075 GLuint
*cmd
= &rmesa
->hw
.tex
[unit
].cmd
[TEX_CMD_0
];
1077 R200_STATECHANGE( rmesa
, tex
[unit
] );
1079 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
1080 cmd
[TEX_PP_TXFILTER
] |= texobj
->pp_txfilter
& TEXOBJ_TXFILTER_MASK
;
1081 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1082 cmd
[TEX_PP_TXFORMAT
] |= texobj
->pp_txformat
& TEXOBJ_TXFORMAT_MASK
;
1083 cmd
[TEX_PP_TXFORMAT_X
] &= ~TEXOBJ_TXFORMAT_X_MASK
;
1084 cmd
[TEX_PP_TXFORMAT_X
] |= texobj
->pp_txformat_x
& TEXOBJ_TXFORMAT_X_MASK
;
1085 cmd
[TEX_PP_TXSIZE
] = texobj
->pp_txsize
; /* NPOT only! */
1086 cmd
[TEX_PP_TXPITCH
] = texobj
->pp_txpitch
; /* NPOT only! */
1087 cmd
[TEX_PP_BORDER_COLOR
] = texobj
->pp_border_color
;
1089 if (texobj
->base
.Target
== GL_TEXTURE_CUBE_MAP
) {
1090 GLuint
*cube_cmd
= &rmesa
->hw
.cube
[unit
].cmd
[CUBE_CMD_0
];
1092 R200_STATECHANGE( rmesa
, cube
[unit
] );
1093 cube_cmd
[CUBE_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
1094 /* that value is submitted twice. could change cube atom
1095 to not include that command when new drm is used */
1096 cmd
[TEX_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
1101 static void set_texgen_matrix( r200ContextPtr rmesa
,
1103 const GLfloat
*s_plane
,
1104 const GLfloat
*t_plane
,
1105 const GLfloat
*r_plane
,
1106 const GLfloat
*q_plane
)
1130 _math_matrix_loadf( &(rmesa
->TexGenMatrix
[unit
]), m
);
1131 _math_matrix_analyse( &(rmesa
->TexGenMatrix
[unit
]) );
1132 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<<unit
;
1136 static GLuint
r200_need_dis_texgen(const GLbitfield texGenEnabled
,
1137 const GLfloat
*planeS
,
1138 const GLfloat
*planeT
,
1139 const GLfloat
*planeR
,
1140 const GLfloat
*planeQ
)
1142 GLuint needtgenable
= 0;
1144 if (!(texGenEnabled
& S_BIT
)) {
1145 if (((texGenEnabled
& T_BIT
) && planeT
[0] != 0.0) ||
1146 ((texGenEnabled
& R_BIT
) && planeR
[0] != 0.0) ||
1147 ((texGenEnabled
& Q_BIT
) && planeQ
[0] != 0.0)) {
1148 needtgenable
|= S_BIT
;
1151 if (!(texGenEnabled
& T_BIT
)) {
1152 if (((texGenEnabled
& S_BIT
) && planeS
[1] != 0.0) ||
1153 ((texGenEnabled
& R_BIT
) && planeR
[1] != 0.0) ||
1154 ((texGenEnabled
& Q_BIT
) && planeQ
[1] != 0.0)) {
1155 needtgenable
|= T_BIT
;
1158 if (!(texGenEnabled
& R_BIT
)) {
1159 if (((texGenEnabled
& S_BIT
) && planeS
[2] != 0.0) ||
1160 ((texGenEnabled
& T_BIT
) && planeT
[2] != 0.0) ||
1161 ((texGenEnabled
& Q_BIT
) && planeQ
[2] != 0.0)) {
1162 needtgenable
|= R_BIT
;
1165 if (!(texGenEnabled
& Q_BIT
)) {
1166 if (((texGenEnabled
& S_BIT
) && planeS
[3] != 0.0) ||
1167 ((texGenEnabled
& T_BIT
) && planeT
[3] != 0.0) ||
1168 ((texGenEnabled
& R_BIT
) && planeR
[3] != 0.0)) {
1169 needtgenable
|= Q_BIT
;
1173 return needtgenable
;
1178 * Returns GL_FALSE if fallback required.
1180 static GLboolean
r200_validate_texgen( struct gl_context
*ctx
, GLuint unit
)
1182 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1183 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1184 GLuint inputshift
= R200_TEXGEN_0_INPUT_SHIFT
+ unit
*4;
1187 GLboolean mixed_fallback
= GL_FALSE
;
1188 static const GLfloat I
[16] = {
1193 static const GLfloat reflect
[16] = {
1199 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1200 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
1201 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
1202 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
1203 tgi
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] & ~(R200_TEXGEN_INPUT_MASK
<<
1205 tgcm
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] & ~(R200_TEXGEN_COMP_MASK
<<
1209 fprintf(stderr
, "%s unit %d\n", __FUNCTION__
, unit
);
1211 if (texUnit
->TexGenEnabled
& S_BIT
) {
1212 mode
= texUnit
->GenS
.Mode
;
1214 tgcm
|= R200_TEXGEN_COMP_S
<< (unit
* 4);
1217 if (texUnit
->TexGenEnabled
& T_BIT
) {
1218 if (texUnit
->GenT
.Mode
!= mode
)
1219 mixed_fallback
= GL_TRUE
;
1221 tgcm
|= R200_TEXGEN_COMP_T
<< (unit
* 4);
1223 if (texUnit
->TexGenEnabled
& R_BIT
) {
1224 if (texUnit
->GenR
.Mode
!= mode
)
1225 mixed_fallback
= GL_TRUE
;
1227 tgcm
|= R200_TEXGEN_COMP_R
<< (unit
* 4);
1230 if (texUnit
->TexGenEnabled
& Q_BIT
) {
1231 if (texUnit
->GenQ
.Mode
!= mode
)
1232 mixed_fallback
= GL_TRUE
;
1234 tgcm
|= R200_TEXGEN_COMP_Q
<< (unit
* 4);
1237 if (mixed_fallback
) {
1238 if (R200_DEBUG
& RADEON_FALLBACKS
)
1239 fprintf(stderr
, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
1240 texUnit
->TexGenEnabled
, texUnit
->GenS
.Mode
, texUnit
->GenT
.Mode
,
1241 texUnit
->GenR
.Mode
, texUnit
->GenQ
.Mode
);
1245 /* we CANNOT do mixed mode if the texgen mode requires a plane where the input
1246 is not enabled for texgen, since the planes are concatenated into texmat,
1247 and thus the input will come from texcoord rather than tex gen equation!
1248 Either fallback or just hope that those texcoords aren't really needed...
1249 Assuming the former will cause lots of unnecessary fallbacks, the latter will
1250 generate bogus results sometimes - it's pretty much impossible to really know
1251 when a fallback is needed, depends on texmat and what sort of texture is bound
1252 etc, - for now fallback if we're missing either S or T bits, there's a high
1253 probability we need the texcoords in that case.
1254 That's a lot of work for some obscure texgen mixed mode fixup - why oh why
1255 doesn't the chip just directly accept the plane parameters :-(. */
1257 case GL_OBJECT_LINEAR
: {
1258 GLuint needtgenable
= r200_need_dis_texgen( texUnit
->TexGenEnabled
,
1259 texUnit
->GenS
.ObjectPlane
,
1260 texUnit
->GenT
.ObjectPlane
,
1261 texUnit
->GenR
.ObjectPlane
,
1262 texUnit
->GenQ
.ObjectPlane
);
1263 if (needtgenable
& (S_BIT
| T_BIT
)) {
1264 if (R200_DEBUG
& RADEON_FALLBACKS
)
1265 fprintf(stderr
, "fallback mixed texgen / obj plane, 0x%x\n",
1266 texUnit
->TexGenEnabled
);
1269 if (needtgenable
& (R_BIT
)) {
1270 tgcm
&= ~(R200_TEXGEN_COMP_R
<< (unit
* 4));
1272 if (needtgenable
& (Q_BIT
)) {
1273 tgcm
&= ~(R200_TEXGEN_COMP_Q
<< (unit
* 4));
1276 tgi
|= R200_TEXGEN_INPUT_OBJ
<< inputshift
;
1277 set_texgen_matrix( rmesa
, unit
,
1278 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->GenS
.ObjectPlane
: I
,
1279 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->GenT
.ObjectPlane
: I
+ 4,
1280 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->GenR
.ObjectPlane
: I
+ 8,
1281 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->GenQ
.ObjectPlane
: I
+ 12);
1285 case GL_EYE_LINEAR
: {
1286 GLuint needtgenable
= r200_need_dis_texgen( texUnit
->TexGenEnabled
,
1287 texUnit
->GenS
.EyePlane
,
1288 texUnit
->GenT
.EyePlane
,
1289 texUnit
->GenR
.EyePlane
,
1290 texUnit
->GenQ
.EyePlane
);
1291 if (needtgenable
& (S_BIT
| T_BIT
)) {
1292 if (R200_DEBUG
& RADEON_FALLBACKS
)
1293 fprintf(stderr
, "fallback mixed texgen / eye plane, 0x%x\n",
1294 texUnit
->TexGenEnabled
);
1297 if (needtgenable
& (R_BIT
)) {
1298 tgcm
&= ~(R200_TEXGEN_COMP_R
<< (unit
* 4));
1300 if (needtgenable
& (Q_BIT
)) {
1301 tgcm
&= ~(R200_TEXGEN_COMP_Q
<< (unit
* 4));
1303 tgi
|= R200_TEXGEN_INPUT_EYE
<< inputshift
;
1304 set_texgen_matrix( rmesa
, unit
,
1305 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->GenS
.EyePlane
: I
,
1306 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->GenT
.EyePlane
: I
+ 4,
1307 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->GenR
.EyePlane
: I
+ 8,
1308 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->GenQ
.EyePlane
: I
+ 12);
1312 case GL_REFLECTION_MAP_NV
:
1313 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1314 tgi
|= R200_TEXGEN_INPUT_EYE_REFLECT
<< inputshift
;
1315 /* pretty weird, must only negate when lighting is enabled? */
1316 if (ctx
->Light
.Enabled
)
1317 set_texgen_matrix( rmesa
, unit
,
1318 (texUnit
->TexGenEnabled
& S_BIT
) ? reflect
: I
,
1319 (texUnit
->TexGenEnabled
& T_BIT
) ? reflect
+ 4 : I
+ 4,
1320 (texUnit
->TexGenEnabled
& R_BIT
) ? reflect
+ 8 : I
+ 8,
1324 case GL_NORMAL_MAP_NV
:
1325 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1326 tgi
|= R200_TEXGEN_INPUT_EYE_NORMAL
<<inputshift
;
1330 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1331 tgi
|= R200_TEXGEN_INPUT_SPHERE
<<inputshift
;
1335 /* All texgen units were disabled, so just pass coords through. */
1336 tgi
|= unit
<< inputshift
;
1340 /* Unsupported mode, fallback:
1342 if (R200_DEBUG
& RADEON_FALLBACKS
)
1343 fprintf(stderr
, "fallback unsupported texgen, %d\n",
1344 texUnit
->GenS
.Mode
);
1348 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
1349 rmesa
->TexGenCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
1351 if (tgi
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] ||
1352 tgcm
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
])
1354 R200_STATECHANGE(rmesa
, tcg
);
1355 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] = tgi
;
1356 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] = tgcm
;
1362 void set_re_cntl_d3d( struct gl_context
*ctx
, int unit
, GLboolean use_d3d
)
1364 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1368 re_cntl
= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] & ~(R200_VTX_STQ0_D3D
<< (2 * unit
));
1370 re_cntl
|= R200_VTX_STQ0_D3D
<< (2 * unit
);
1372 if ( re_cntl
!= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] ) {
1373 R200_STATECHANGE( rmesa
, set
);
1374 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] = re_cntl
;
1379 * Compute the cached hardware register values for the given texture object.
1381 * \param rmesa Context pointer
1382 * \param t the r300 texture object
1384 static void setup_hardware_state(r200ContextPtr rmesa
, radeonTexObj
*t
)
1386 const struct gl_texture_image
*firstImage
= t
->base
.Image
[0][t
->minLod
];
1387 GLint log2Width
, log2Height
, log2Depth
, texelBytes
;
1388 uint extra_size
= 0;
1394 log2Width
= firstImage
->WidthLog2
;
1395 log2Height
= firstImage
->HeightLog2
;
1396 log2Depth
= firstImage
->DepthLog2
;
1397 texelBytes
= _mesa_get_format_bytes(firstImage
->TexFormat
);
1399 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
1400 "%s(%p, tex %p) log2(w %d, h %d, d %d), texelBytes %d. format %d\n",
1401 __func__
, rmesa
, t
, log2Width
, log2Height
,
1402 log2Depth
, texelBytes
, firstImage
->TexFormat
);
1404 if (!t
->image_override
) {
1405 if (VALID_FORMAT(firstImage
->TexFormat
)) {
1406 const struct tx_table
*table
= _mesa_little_endian() ? tx_table_le
:
1409 t
->pp_txformat
&= ~(R200_TXFORMAT_FORMAT_MASK
|
1410 R200_TXFORMAT_ALPHA_IN_MAP
);
1411 t
->pp_txfilter
&= ~R200_YUV_TO_RGB
;
1413 t
->pp_txformat
|= table
[ firstImage
->TexFormat
].format
;
1414 t
->pp_txfilter
|= table
[ firstImage
->TexFormat
].filter
;
1418 _mesa_problem(NULL
, "unexpected texture format in %s",
1424 t
->pp_txfilter
&= ~R200_MAX_MIP_LEVEL_MASK
;
1425 t
->pp_txfilter
|= ((t
->maxLod
) << R200_MAX_MIP_LEVEL_SHIFT
)
1426 & R200_MAX_MIP_LEVEL_MASK
;
1428 if ( t
->pp_txfilter
&
1429 (R200_MIN_FILTER_NEAREST_MIP_NEAREST
1430 | R200_MIN_FILTER_NEAREST_MIP_LINEAR
1431 | R200_MIN_FILTER_LINEAR_MIP_NEAREST
1432 | R200_MIN_FILTER_LINEAR_MIP_LINEAR
1433 | R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
1434 | R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR
))
1435 extra_size
= t
->minLod
;
1437 t
->pp_txformat
&= ~(R200_TXFORMAT_WIDTH_MASK
|
1438 R200_TXFORMAT_HEIGHT_MASK
|
1439 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
1440 R200_TXFORMAT_F5_WIDTH_MASK
|
1441 R200_TXFORMAT_F5_HEIGHT_MASK
);
1442 t
->pp_txformat
|= (((log2Width
+ extra_size
) << R200_TXFORMAT_WIDTH_SHIFT
) |
1443 ((log2Height
+ extra_size
)<< R200_TXFORMAT_HEIGHT_SHIFT
));
1447 t
->pp_txformat_x
&= ~(R200_DEPTH_LOG2_MASK
| R200_TEXCOORD_MASK
1448 | R200_MIN_MIP_LEVEL_MASK
);
1450 t
->pp_txformat_x
|= (t
->minLod
<< R200_MIN_MIP_LEVEL_SHIFT
)
1451 & R200_MIN_MIP_LEVEL_MASK
;
1453 if (t
->base
.Target
== GL_TEXTURE_3D
) {
1454 t
->pp_txformat_x
|= (log2Depth
<< R200_DEPTH_LOG2_SHIFT
);
1455 t
->pp_txformat_x
|= R200_TEXCOORD_VOLUME
;
1458 else if (t
->base
.Target
== GL_TEXTURE_CUBE_MAP
) {
1459 ASSERT(log2Width
== log2Height
);
1460 t
->pp_txformat
|= ((log2Width
<< R200_TXFORMAT_F5_WIDTH_SHIFT
) |
1461 (log2Height
<< R200_TXFORMAT_F5_HEIGHT_SHIFT
) |
1462 /* don't think we need this bit, if it exists at all - fglrx does not set it */
1463 (R200_TXFORMAT_CUBIC_MAP_ENABLE
));
1464 t
->pp_txformat_x
|= R200_TEXCOORD_CUBIC_ENV
;
1465 t
->pp_cubic_faces
= ((log2Width
<< R200_FACE_WIDTH_1_SHIFT
) |
1466 (log2Height
<< R200_FACE_HEIGHT_1_SHIFT
) |
1467 (log2Width
<< R200_FACE_WIDTH_2_SHIFT
) |
1468 (log2Height
<< R200_FACE_HEIGHT_2_SHIFT
) |
1469 (log2Width
<< R200_FACE_WIDTH_3_SHIFT
) |
1470 (log2Height
<< R200_FACE_HEIGHT_3_SHIFT
) |
1471 (log2Width
<< R200_FACE_WIDTH_4_SHIFT
) |
1472 (log2Height
<< R200_FACE_HEIGHT_4_SHIFT
));
1475 /* If we don't in fact send enough texture coordinates, q will be 1,
1476 * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
1478 t
->pp_txformat_x
|= R200_TEXCOORD_PROJ
;
1480 /* FIXME: NPOT sizes, Is it correct realy? */
1481 t
->pp_txsize
= (((firstImage
->Width
- 1) << R200_PP_TX_WIDTHMASK_SHIFT
)
1482 | ((firstImage
->Height
- 1) << R200_PP_TX_HEIGHTMASK_SHIFT
));
1484 if ( !t
->image_override
) {
1485 if (_mesa_is_format_compressed(firstImage
->TexFormat
))
1486 t
->pp_txpitch
= (firstImage
->Width
+ 63) & ~(63);
1488 t
->pp_txpitch
= ((firstImage
->Width
* texelBytes
) + 63) & ~(63);
1489 t
->pp_txpitch
-= 32;
1492 if (t
->base
.Target
== GL_TEXTURE_RECTANGLE_NV
) {
1493 t
->pp_txformat
|= R200_TXFORMAT_NON_POWER2
;
1498 static GLboolean
r200_validate_texture(struct gl_context
*ctx
, struct gl_texture_object
*texObj
, int unit
)
1500 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1501 radeonTexObj
*t
= radeon_tex_obj(texObj
);
1503 if (!radeon_validate_texture_miptree(ctx
, _mesa_get_samplerobj(ctx
, unit
), texObj
))
1506 r200_validate_texgen(ctx
, unit
);
1507 /* Configure the hardware registers (more precisely, the cached version
1508 * of the hardware registers). */
1509 setup_hardware_state(rmesa
, t
);
1511 if (texObj
->Target
== GL_TEXTURE_RECTANGLE_NV
||
1512 texObj
->Target
== GL_TEXTURE_2D
||
1513 texObj
->Target
== GL_TEXTURE_1D
)
1514 set_re_cntl_d3d( ctx
, unit
, GL_FALSE
);
1516 set_re_cntl_d3d( ctx
, unit
, GL_TRUE
);
1517 R200_STATECHANGE( rmesa
, ctx
);
1518 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_0_ENABLE
<< unit
;
1520 R200_STATECHANGE( rmesa
, vtx
);
1521 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
1522 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] |= 4 << (unit
* 3);
1524 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1525 r200TexUpdateParameters(ctx
, unit
);
1526 import_tex_obj_state( rmesa
, unit
, t
);
1528 if (rmesa
->recheck_texgen
[unit
]) {
1529 GLboolean fallback
= !r200_validate_texgen( ctx
, unit
);
1530 TCL_FALLBACK( ctx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), fallback
);
1531 rmesa
->recheck_texgen
[unit
] = 0;
1532 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE_MATRIX
;
1535 t
->validated
= GL_TRUE
;
1537 FALLBACK( rmesa
, RADEON_FALLBACK_BORDER_MODE
, t
->border_fallback
);
1539 return !t
->border_fallback
;
1542 static GLboolean
r200UpdateTextureUnit(struct gl_context
*ctx
, int unit
)
1544 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1545 GLuint unitneeded
= rmesa
->state
.texture
.unit
[unit
].unitneeded
;
1548 /* disable the unit */
1549 disable_tex_obj_state(rmesa
, unit
);
1553 if (!r200_validate_texture(ctx
, ctx
->Texture
.Unit
[unit
]._Current
, unit
)) {
1555 "failed to validate texture for unit %d.\n",
1557 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
1561 rmesa
->state
.texture
.unit
[unit
].texobj
= radeon_tex_obj(ctx
->Texture
.Unit
[unit
]._Current
);
1566 void r200UpdateTextureState( struct gl_context
*ctx
)
1568 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1572 /* NOTE: must not manipulate rmesa->state.texture.unit[].unitneeded or
1573 rmesa->state.envneeded before a R200_STATECHANGE (or R200_NEWPRIM) since
1574 we use these to determine if we want to emit the corresponding state
1576 R200_NEWPRIM( rmesa
);
1578 if (ctx
->ATIFragmentShader
._Enabled
) {
1580 for (i
= 0; i
< R200_MAX_TEXTURE_UNITS
; i
++) {
1581 rmesa
->state
.texture
.unit
[i
].unitneeded
= ctx
->Texture
.Unit
[i
]._ReallyEnabled
;
1586 ok
= r200UpdateAllTexEnv( ctx
);
1589 ok
= (r200UpdateTextureUnit( ctx
, 0 ) &&
1590 r200UpdateTextureUnit( ctx
, 1 ) &&
1591 r200UpdateTextureUnit( ctx
, 2 ) &&
1592 r200UpdateTextureUnit( ctx
, 3 ) &&
1593 r200UpdateTextureUnit( ctx
, 4 ) &&
1594 r200UpdateTextureUnit( ctx
, 5 ));
1597 if (ok
&& ctx
->ATIFragmentShader
._Enabled
) {
1598 r200UpdateFragmentShader(ctx
);
1601 FALLBACK( rmesa
, R200_FALLBACK_TEXTURE
, !ok
);
1603 if (rmesa
->radeon
.TclFallback
)
1604 r200ChooseVertexState( ctx
);
1607 if (rmesa
->radeon
.radeonScreen
->chip_family
== CHIP_FAMILY_R200
) {
1610 * T0 hang workaround -------------
1611 * not needed for r200 derivatives
1613 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_ENABLE_MASK
) == R200_TEX_0_ENABLE
&&
1614 (rmesa
->hw
.tex
[0].cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) > R200_MIN_FILTER_LINEAR
) {
1616 R200_STATECHANGE(rmesa
, ctx
);
1617 R200_STATECHANGE(rmesa
, tex
[1]);
1618 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_1_ENABLE
;
1619 if (!(rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] & R200_PPX_TEX_1_ENABLE
))
1620 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1621 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] |= R200_TXFORMAT_LOOKUP_DISABLE
;
1623 else if (!ctx
->ATIFragmentShader
._Enabled
) {
1624 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
) &&
1625 (rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] & R200_TXFORMAT_LOOKUP_DISABLE
)) {
1626 R200_STATECHANGE(rmesa
, tex
[1]);
1627 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~R200_TXFORMAT_LOOKUP_DISABLE
;
1630 /* do the same workaround for the first pass of a fragment shader.
1631 * completely unknown if necessary / sufficient.
1633 if ((rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] & R200_PPX_TEX_ENABLE_MASK
) == R200_PPX_TEX_0_ENABLE
&&
1634 (rmesa
->hw
.tex
[0].cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) > R200_MIN_FILTER_LINEAR
) {
1636 R200_STATECHANGE(rmesa
, cst
);
1637 R200_STATECHANGE(rmesa
, tex
[1]);
1638 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] |= R200_PPX_TEX_1_ENABLE
;
1639 if (!(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
))
1640 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1641 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXMULTI_CTL
] |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE
;
1644 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1645 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1646 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1647 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1648 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1649 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1650 R200_MIN_FILTER_LINEAR)) {
1651 R200_STATECHANGE(rmesa, ctx);
1652 R200_STATECHANGE(rmesa, tex[i+1]);
1653 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1654 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1655 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1658 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1659 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1660 R200_STATECHANGE(rmesa, tex[i+1]);
1661 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1667 * Texture cache LRU hang workaround -------------
1668 * not needed for r200 derivatives
1669 * hopefully this covers first pass of a shader as well
1672 /* While the cases below attempt to only enable the workaround in the
1673 * specific cases necessary, they were insufficient. See bugzilla #1519,
1674 * #729, #814. Tests with quake3 showed no impact on performance.
1679 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) &&
1680 ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1682 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1683 ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1685 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1686 ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1692 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) &&
1693 ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1695 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1696 ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1698 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1699 ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1705 if (dbg
!= rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
]) {
1706 R200_STATECHANGE( rmesa
, tam
);
1707 rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
] = dbg
;
1708 if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg
);