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 <keithw@vmware.com>
35 #include "main/glheader.h"
36 #include "main/imports.h"
37 #include "main/context.h"
38 #include "main/macros.h"
39 #include "main/state.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"
53 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
54 && (tx_table_be[f].format != 0xffffffff) )
56 /* ================================================================
57 * Texture combine functions
60 /* GL_ARB_texture_env_combine support
63 /* The color tables have combine functions for GL_SRC_COLOR,
64 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
66 static GLuint r200_register_color
[][R200_MAX_TEXTURE_UNITS
] =
69 R200_TXC_ARG_A_R0_COLOR
,
70 R200_TXC_ARG_A_R1_COLOR
,
71 R200_TXC_ARG_A_R2_COLOR
,
72 R200_TXC_ARG_A_R3_COLOR
,
73 R200_TXC_ARG_A_R4_COLOR
,
74 R200_TXC_ARG_A_R5_COLOR
77 R200_TXC_ARG_A_R0_COLOR
| R200_TXC_COMP_ARG_A
,
78 R200_TXC_ARG_A_R1_COLOR
| R200_TXC_COMP_ARG_A
,
79 R200_TXC_ARG_A_R2_COLOR
| R200_TXC_COMP_ARG_A
,
80 R200_TXC_ARG_A_R3_COLOR
| R200_TXC_COMP_ARG_A
,
81 R200_TXC_ARG_A_R4_COLOR
| R200_TXC_COMP_ARG_A
,
82 R200_TXC_ARG_A_R5_COLOR
| R200_TXC_COMP_ARG_A
85 R200_TXC_ARG_A_R0_ALPHA
,
86 R200_TXC_ARG_A_R1_ALPHA
,
87 R200_TXC_ARG_A_R2_ALPHA
,
88 R200_TXC_ARG_A_R3_ALPHA
,
89 R200_TXC_ARG_A_R4_ALPHA
,
90 R200_TXC_ARG_A_R5_ALPHA
93 R200_TXC_ARG_A_R0_ALPHA
| R200_TXC_COMP_ARG_A
,
94 R200_TXC_ARG_A_R1_ALPHA
| R200_TXC_COMP_ARG_A
,
95 R200_TXC_ARG_A_R2_ALPHA
| R200_TXC_COMP_ARG_A
,
96 R200_TXC_ARG_A_R3_ALPHA
| R200_TXC_COMP_ARG_A
,
97 R200_TXC_ARG_A_R4_ALPHA
| R200_TXC_COMP_ARG_A
,
98 R200_TXC_ARG_A_R5_ALPHA
| R200_TXC_COMP_ARG_A
102 static GLuint r200_tfactor_color
[] =
104 R200_TXC_ARG_A_TFACTOR_COLOR
,
105 R200_TXC_ARG_A_TFACTOR_COLOR
| R200_TXC_COMP_ARG_A
,
106 R200_TXC_ARG_A_TFACTOR_ALPHA
,
107 R200_TXC_ARG_A_TFACTOR_ALPHA
| R200_TXC_COMP_ARG_A
110 static GLuint r200_tfactor1_color
[] =
112 R200_TXC_ARG_A_TFACTOR1_COLOR
,
113 R200_TXC_ARG_A_TFACTOR1_COLOR
| R200_TXC_COMP_ARG_A
,
114 R200_TXC_ARG_A_TFACTOR1_ALPHA
,
115 R200_TXC_ARG_A_TFACTOR1_ALPHA
| R200_TXC_COMP_ARG_A
118 static GLuint r200_primary_color
[] =
120 R200_TXC_ARG_A_DIFFUSE_COLOR
,
121 R200_TXC_ARG_A_DIFFUSE_COLOR
| R200_TXC_COMP_ARG_A
,
122 R200_TXC_ARG_A_DIFFUSE_ALPHA
,
123 R200_TXC_ARG_A_DIFFUSE_ALPHA
| R200_TXC_COMP_ARG_A
126 /* GL_ZERO table - indices 0-3
127 * GL_ONE table - indices 1-4
129 static GLuint r200_zero_color
[] =
132 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
134 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
138 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
140 static GLuint r200_register_alpha
[][R200_MAX_TEXTURE_UNITS
] =
143 R200_TXA_ARG_A_R0_ALPHA
,
144 R200_TXA_ARG_A_R1_ALPHA
,
145 R200_TXA_ARG_A_R2_ALPHA
,
146 R200_TXA_ARG_A_R3_ALPHA
,
147 R200_TXA_ARG_A_R4_ALPHA
,
148 R200_TXA_ARG_A_R5_ALPHA
151 R200_TXA_ARG_A_R0_ALPHA
| R200_TXA_COMP_ARG_A
,
152 R200_TXA_ARG_A_R1_ALPHA
| R200_TXA_COMP_ARG_A
,
153 R200_TXA_ARG_A_R2_ALPHA
| R200_TXA_COMP_ARG_A
,
154 R200_TXA_ARG_A_R3_ALPHA
| R200_TXA_COMP_ARG_A
,
155 R200_TXA_ARG_A_R4_ALPHA
| R200_TXA_COMP_ARG_A
,
156 R200_TXA_ARG_A_R5_ALPHA
| R200_TXA_COMP_ARG_A
160 static GLuint r200_tfactor_alpha
[] =
162 R200_TXA_ARG_A_TFACTOR_ALPHA
,
163 R200_TXA_ARG_A_TFACTOR_ALPHA
| R200_TXA_COMP_ARG_A
166 static GLuint r200_tfactor1_alpha
[] =
168 R200_TXA_ARG_A_TFACTOR1_ALPHA
,
169 R200_TXA_ARG_A_TFACTOR1_ALPHA
| R200_TXA_COMP_ARG_A
172 static GLuint r200_primary_alpha
[] =
174 R200_TXA_ARG_A_DIFFUSE_ALPHA
,
175 R200_TXA_ARG_A_DIFFUSE_ALPHA
| R200_TXA_COMP_ARG_A
178 /* GL_ZERO table - indices 0-1
179 * GL_ONE table - indices 1-2
181 static GLuint r200_zero_alpha
[] =
184 R200_TXA_ARG_A_ZERO
| R200_TXA_COMP_ARG_A
,
189 /* Extract the arg from slot A, shift it into the correct argument slot
190 * and set the corresponding complement bit.
192 #define R200_COLOR_ARG( n, arg ) \
195 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
196 << R200_TXC_ARG_##arg##_SHIFT); \
198 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
199 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
202 #define R200_ALPHA_ARG( n, arg ) \
205 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
206 << R200_TXA_ARG_##arg##_SHIFT); \
208 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
209 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
213 /* ================================================================
214 * Texture unit state management
217 static GLboolean
r200UpdateTextureEnv( struct gl_context
*ctx
, int unit
, int slot
, GLuint replaceargs
)
219 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
220 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
221 GLuint color_combine
, alpha_combine
;
222 GLuint color_scale
= rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] &
223 ~(R200_TXC_SCALE_MASK
| R200_TXC_OUTPUT_REG_MASK
| R200_TXC_TFACTOR_SEL_MASK
|
224 R200_TXC_TFACTOR1_SEL_MASK
);
225 GLuint alpha_scale
= rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] &
226 ~(R200_TXA_DOT_ALPHA
| R200_TXA_SCALE_MASK
| R200_TXA_OUTPUT_REG_MASK
|
227 R200_TXA_TFACTOR_SEL_MASK
| R200_TXA_TFACTOR1_SEL_MASK
);
229 if ( R200_DEBUG
& RADEON_TEXTURE
) {
230 fprintf( stderr
, "%s( %p, %d )\n", __func__
, (void *)ctx
, unit
);
233 /* Set the texture environment state. Isn't this nice and clean?
234 * The chip will automagically set the texture alpha to 0xff when
235 * the texture format does not include an alpha component. This
236 * reduces the amount of special-casing we have to do, alpha-only
237 * textures being a notable exception.
240 color_scale
|= ((rmesa
->state
.texture
.unit
[unit
].outputreg
+ 1) << R200_TXC_OUTPUT_REG_SHIFT
) |
241 (unit
<< R200_TXC_TFACTOR_SEL_SHIFT
) |
242 (replaceargs
<< R200_TXC_TFACTOR1_SEL_SHIFT
);
243 alpha_scale
|= ((rmesa
->state
.texture
.unit
[unit
].outputreg
+ 1) << R200_TXA_OUTPUT_REG_SHIFT
) |
244 (unit
<< R200_TXA_TFACTOR_SEL_SHIFT
) |
245 (replaceargs
<< R200_TXA_TFACTOR1_SEL_SHIFT
);
247 if ( !texUnit
->_Current
) {
249 color_combine
= R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
250 | R200_TXC_ARG_C_DIFFUSE_COLOR
| R200_TXC_OP_MADD
;
251 alpha_combine
= R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
252 | R200_TXA_ARG_C_DIFFUSE_ALPHA
| R200_TXA_OP_MADD
;
255 GLuint color_arg
[3], alpha_arg
[3];
257 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
258 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
259 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
260 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
263 const GLint replaceoprgb
=
264 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->OperandRGB
[0] - GL_SRC_COLOR
;
265 const GLint replaceopa
=
266 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->OperandA
[0] - GL_SRC_ALPHA
;
269 * Extract the color and alpha combine function arguments.
271 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
272 GLint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
] - GL_SRC_COLOR
;
273 const GLint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
278 color_arg
[i
] = r200_register_color
[op
][unit
];
281 color_arg
[i
] = r200_tfactor_color
[op
];
283 case GL_PRIMARY_COLOR
:
284 color_arg
[i
] = r200_primary_color
[op
];
287 if (replaceargs
!= unit
) {
288 const GLint srcRGBreplace
=
289 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->SourceRGB
[0];
291 op
= op
^ replaceopa
;
294 op
= op
^ replaceoprgb
;
296 switch (srcRGBreplace
) {
298 color_arg
[i
] = r200_register_color
[op
][replaceargs
];
301 color_arg
[i
] = r200_tfactor1_color
[op
];
303 case GL_PRIMARY_COLOR
:
304 color_arg
[i
] = r200_primary_color
[op
];
308 color_arg
[i
] = r200_primary_color
[op
];
310 color_arg
[i
] = r200_register_color
[op
]
311 [rmesa
->state
.texture
.unit
[replaceargs
- 1].outputreg
];
314 color_arg
[i
] = r200_zero_color
[op
];
317 color_arg
[i
] = r200_zero_color
[op
+1];
325 color_arg
[i
] = r200_register_color
[op
][srcRGBreplace
- GL_TEXTURE0
];
333 color_arg
[i
] = r200_primary_color
[op
];
335 color_arg
[i
] = r200_register_color
[op
]
336 [rmesa
->state
.texture
.unit
[unit
- 1].outputreg
];
340 color_arg
[i
] = r200_zero_color
[op
];
343 color_arg
[i
] = r200_zero_color
[op
+1];
351 color_arg
[i
] = r200_register_color
[op
][srcRGBi
- GL_TEXTURE0
];
358 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
359 GLint op
= texUnit
->_CurrentCombine
->OperandA
[i
] - GL_SRC_ALPHA
;
360 const GLint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
365 alpha_arg
[i
] = r200_register_alpha
[op
][unit
];
368 alpha_arg
[i
] = r200_tfactor_alpha
[op
];
370 case GL_PRIMARY_COLOR
:
371 alpha_arg
[i
] = r200_primary_alpha
[op
];
374 if (replaceargs
!= unit
) {
375 const GLint srcAreplace
=
376 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->SourceA
[0];
377 op
= op
^ replaceopa
;
378 switch (srcAreplace
) {
380 alpha_arg
[i
] = r200_register_alpha
[op
][replaceargs
];
383 alpha_arg
[i
] = r200_tfactor1_alpha
[op
];
385 case GL_PRIMARY_COLOR
:
386 alpha_arg
[i
] = r200_primary_alpha
[op
];
390 alpha_arg
[i
] = r200_primary_alpha
[op
];
392 alpha_arg
[i
] = r200_register_alpha
[op
]
393 [rmesa
->state
.texture
.unit
[replaceargs
- 1].outputreg
];
396 alpha_arg
[i
] = r200_zero_alpha
[op
];
399 alpha_arg
[i
] = r200_zero_alpha
[op
+1];
407 alpha_arg
[i
] = r200_register_alpha
[op
][srcAreplace
- GL_TEXTURE0
];
415 alpha_arg
[i
] = r200_primary_alpha
[op
];
417 alpha_arg
[i
] = r200_register_alpha
[op
]
418 [rmesa
->state
.texture
.unit
[unit
- 1].outputreg
];
422 alpha_arg
[i
] = r200_zero_alpha
[op
];
425 alpha_arg
[i
] = r200_zero_alpha
[op
+1];
433 alpha_arg
[i
] = r200_register_alpha
[op
][srcAi
- GL_TEXTURE0
];
441 * Build up the color and alpha combine functions.
443 switch ( texUnit
->_CurrentCombine
->ModeRGB
) {
445 color_combine
= (R200_TXC_ARG_A_ZERO
|
446 R200_TXC_ARG_B_ZERO
|
448 R200_COLOR_ARG( 0, C
);
451 color_combine
= (R200_TXC_ARG_C_ZERO
|
453 R200_COLOR_ARG( 0, A
);
454 R200_COLOR_ARG( 1, B
);
457 color_combine
= (R200_TXC_ARG_B_ZERO
|
458 R200_TXC_COMP_ARG_B
|
460 R200_COLOR_ARG( 0, A
);
461 R200_COLOR_ARG( 1, C
);
464 color_combine
= (R200_TXC_ARG_B_ZERO
|
465 R200_TXC_COMP_ARG_B
|
466 R200_TXC_BIAS_ARG_C
| /* new */
467 R200_TXC_OP_MADD
); /* was ADDSIGNED */
468 R200_COLOR_ARG( 0, A
);
469 R200_COLOR_ARG( 1, C
);
472 color_combine
= (R200_TXC_ARG_B_ZERO
|
473 R200_TXC_COMP_ARG_B
|
476 R200_COLOR_ARG( 0, A
);
477 R200_COLOR_ARG( 1, C
);
480 color_combine
= (R200_TXC_OP_LERP
);
481 R200_COLOR_ARG( 0, B
);
482 R200_COLOR_ARG( 1, A
);
483 R200_COLOR_ARG( 2, C
);
486 case GL_DOT3_RGB_EXT
:
487 case GL_DOT3_RGBA_EXT
:
488 /* The EXT version of the DOT3 extension does not support the
489 * scale factor, but the ARB version (and the version in OpenGL
497 /* DOT3 works differently on R200 than on R100. On R100, just
498 * setting the DOT3 mode did everything for you. On R200, the
499 * driver has to enable the biasing and scale in the inputs to
500 * put them in the proper [-1,1] range. This is what the 4x and
501 * the -0.5 in the DOT3 spec do. The post-scale is then set
505 color_combine
= (R200_TXC_ARG_C_ZERO
|
507 R200_TXC_BIAS_ARG_A
|
508 R200_TXC_BIAS_ARG_B
|
509 R200_TXC_SCALE_ARG_A
|
510 R200_TXC_SCALE_ARG_B
);
511 R200_COLOR_ARG( 0, A
);
512 R200_COLOR_ARG( 1, B
);
515 case GL_MODULATE_ADD_ATI
:
516 color_combine
= (R200_TXC_OP_MADD
);
517 R200_COLOR_ARG( 0, A
);
518 R200_COLOR_ARG( 1, C
);
519 R200_COLOR_ARG( 2, B
);
521 case GL_MODULATE_SIGNED_ADD_ATI
:
522 color_combine
= (R200_TXC_BIAS_ARG_C
| /* new */
523 R200_TXC_OP_MADD
); /* was ADDSIGNED */
524 R200_COLOR_ARG( 0, A
);
525 R200_COLOR_ARG( 1, C
);
526 R200_COLOR_ARG( 2, B
);
528 case GL_MODULATE_SUBTRACT_ATI
:
529 color_combine
= (R200_TXC_NEG_ARG_C
|
531 R200_COLOR_ARG( 0, A
);
532 R200_COLOR_ARG( 1, C
);
533 R200_COLOR_ARG( 2, B
);
539 switch ( texUnit
->_CurrentCombine
->ModeA
) {
541 alpha_combine
= (R200_TXA_ARG_A_ZERO
|
542 R200_TXA_ARG_B_ZERO
|
544 R200_ALPHA_ARG( 0, C
);
547 alpha_combine
= (R200_TXA_ARG_C_ZERO
|
549 R200_ALPHA_ARG( 0, A
);
550 R200_ALPHA_ARG( 1, B
);
553 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
554 R200_TXA_COMP_ARG_B
|
556 R200_ALPHA_ARG( 0, A
);
557 R200_ALPHA_ARG( 1, C
);
560 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
561 R200_TXA_COMP_ARG_B
|
562 R200_TXA_BIAS_ARG_C
| /* new */
563 R200_TXA_OP_MADD
); /* was ADDSIGNED */
564 R200_ALPHA_ARG( 0, A
);
565 R200_ALPHA_ARG( 1, C
);
568 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
569 R200_TXA_COMP_ARG_B
|
572 R200_ALPHA_ARG( 0, A
);
573 R200_ALPHA_ARG( 1, C
);
576 alpha_combine
= (R200_TXA_OP_LERP
);
577 R200_ALPHA_ARG( 0, B
);
578 R200_ALPHA_ARG( 1, A
);
579 R200_ALPHA_ARG( 2, C
);
582 case GL_MODULATE_ADD_ATI
:
583 alpha_combine
= (R200_TXA_OP_MADD
);
584 R200_ALPHA_ARG( 0, A
);
585 R200_ALPHA_ARG( 1, C
);
586 R200_ALPHA_ARG( 2, B
);
588 case GL_MODULATE_SIGNED_ADD_ATI
:
589 alpha_combine
= (R200_TXA_BIAS_ARG_C
| /* new */
590 R200_TXA_OP_MADD
); /* was ADDSIGNED */
591 R200_ALPHA_ARG( 0, A
);
592 R200_ALPHA_ARG( 1, C
);
593 R200_ALPHA_ARG( 2, B
);
595 case GL_MODULATE_SUBTRACT_ATI
:
596 alpha_combine
= (R200_TXA_NEG_ARG_C
|
598 R200_ALPHA_ARG( 0, A
);
599 R200_ALPHA_ARG( 1, C
);
600 R200_ALPHA_ARG( 2, B
);
606 if ( (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
607 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ) {
608 alpha_scale
|= R200_TXA_DOT_ALPHA
;
613 * Apply the scale factor.
615 color_scale
|= (RGBshift
<< R200_TXC_SCALE_SHIFT
);
616 alpha_scale
|= (Ashift
<< R200_TXA_SCALE_SHIFT
);
622 if ( rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND
] != color_combine
||
623 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND
] != alpha_combine
||
624 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] != color_scale
||
625 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] != alpha_scale
) {
626 R200_STATECHANGE( rmesa
, pix
[slot
] );
627 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND
] = color_combine
;
628 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND
] = alpha_combine
;
629 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] = color_scale
;
630 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] = alpha_scale
;
636 void r200SetTexBuffer2(__DRIcontext
*pDRICtx
, GLint target
, GLint texture_format
,
637 __DRIdrawable
*dPriv
)
639 struct gl_texture_object
*texObj
;
640 struct gl_texture_image
*texImage
;
641 struct radeon_renderbuffer
*rb
;
642 radeon_texture_image
*rImage
;
643 radeonContextPtr radeon
;
644 struct radeon_framebuffer
*rfb
;
647 mesa_format texFormat
;
649 radeon
= pDRICtx
->driverPrivate
;
651 rfb
= dPriv
->driverPrivate
;
652 texObj
= _mesa_get_current_tex_object(&radeon
->glCtx
, target
);
653 texImage
= _mesa_get_tex_image(&radeon
->glCtx
, texObj
, target
, 0);
655 rImage
= get_radeon_texture_image(texImage
);
656 t
= radeon_tex_obj(texObj
);
661 radeon_update_renderbuffers(pDRICtx
, dPriv
, GL_TRUE
);
662 rb
= rfb
->color_rb
[0];
663 if (rb
->bo
== NULL
) {
664 /* Failed to BO for the buffer */
668 _mesa_lock_texture(&radeon
->glCtx
, texObj
);
670 radeon_bo_unref(t
->bo
);
674 radeon_bo_unref(rImage
->bo
);
678 radeon_miptree_unreference(&t
->mt
);
679 radeon_miptree_unreference(&rImage
->mt
);
682 radeon_bo_ref(rImage
->bo
);
684 radeon_bo_ref(t
->bo
);
686 t
->image_override
= GL_TRUE
;
687 t
->override_offset
= 0;
688 t
->pp_txpitch
&= (1 << 13) -1;
689 pitch_val
= rb
->pitch
;
692 if (texture_format
== __DRI_TEXTURE_FORMAT_RGB
) {
693 texFormat
= MESA_FORMAT_BGR_UNORM8
;
694 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_BGR_UNORM8
].format
;
697 texFormat
= MESA_FORMAT_B8G8R8A8_UNORM
;
698 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_B8G8R8A8_UNORM
].format
;
700 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_B8G8R8A8_UNORM
].filter
;
704 texFormat
= MESA_FORMAT_BGR_UNORM8
;
705 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_BGR_UNORM8
].format
;
706 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_BGR_UNORM8
].filter
;
709 texFormat
= MESA_FORMAT_B5G6R5_UNORM
;
710 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_B5G6R5_UNORM
].format
;
711 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_B5G6R5_UNORM
].filter
;
715 _mesa_init_teximage_fields(&radeon
->glCtx
, texImage
,
716 rb
->base
.Base
.Width
, rb
->base
.Base
.Height
,
719 rImage
->base
.RowStride
= rb
->pitch
/ rb
->cpp
;
722 t
->pp_txsize
= ((rb
->base
.Base
.Width
- 1) << RADEON_TEX_USIZE_SHIFT
)
723 | ((rb
->base
.Base
.Height
- 1) << RADEON_TEX_VSIZE_SHIFT
);
725 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
726 t
->pp_txformat
|= R200_TXFORMAT_NON_POWER2
;
727 t
->pp_txpitch
= pitch_val
;
730 t
->pp_txformat
&= ~(R200_TXFORMAT_WIDTH_MASK
|
731 R200_TXFORMAT_HEIGHT_MASK
|
732 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
733 R200_TXFORMAT_F5_WIDTH_MASK
|
734 R200_TXFORMAT_F5_HEIGHT_MASK
);
735 t
->pp_txformat
|= ((texImage
->WidthLog2
<< R200_TXFORMAT_WIDTH_SHIFT
) |
736 (texImage
->HeightLog2
<< R200_TXFORMAT_HEIGHT_SHIFT
));
739 t
->validated
= GL_TRUE
;
740 _mesa_unlock_texture(&radeon
->glCtx
, texObj
);
745 void r200SetTexBuffer(__DRIcontext
*pDRICtx
, GLint target
, __DRIdrawable
*dPriv
)
747 r200SetTexBuffer2(pDRICtx
, target
, __DRI_TEXTURE_FORMAT_RGBA
, dPriv
);
754 static GLboolean
r200UpdateAllTexEnv( struct gl_context
*ctx
)
756 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
757 GLint i
, j
, currslot
;
758 GLint maxunitused
= -1;
759 GLboolean texregfree
[6] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
760 GLubyte stageref
[7] = {0, 0, 0, 0, 0, 0, 0};
761 GLint nextunit
[R200_MAX_TEXTURE_UNITS
] = {0, 0, 0, 0, 0, 0};
762 GLint currentnext
= -1;
765 /* find highest used unit */
766 for ( j
= 0; j
< R200_MAX_TEXTURE_UNITS
; j
++) {
767 if (ctx
->Texture
.Unit
[j
]._Current
) {
771 stageref
[maxunitused
+ 1] = REF_COLOR
| REF_ALPHA
;
773 for ( j
= maxunitused
; j
>= 0; j
-- ) {
774 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[j
];
776 rmesa
->state
.texture
.unit
[j
].outputreg
= -1;
778 if (stageref
[j
+ 1]) {
780 /* use the lowest available reg. That gets us automatically reg0 for the last stage.
781 need this even for disabled units, as it may get referenced due to the replace
783 for ( i
= 0 ; i
< R200_MAX_TEXTURE_UNITS
; i
++ ) {
785 rmesa
->state
.texture
.unit
[j
].outputreg
= i
;
789 if (rmesa
->state
.texture
.unit
[j
].outputreg
== -1) {
790 /* no more free regs we can use. Need a fallback :-( */
794 nextunit
[j
] = currentnext
;
796 if (!texUnit
->_Current
) {
797 /* the not enabled stages are referenced "indirectly",
798 must not cut off the lower stages */
799 stageref
[j
] = REF_COLOR
| REF_ALPHA
;
804 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
805 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
806 const GLboolean isdot3rgba
= (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ||
807 (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
);
810 /* check if we need the color part, special case for dot3_rgba
811 as if only the alpha part is referenced later on it still is using the color part */
812 if ((stageref
[j
+ 1] & REF_COLOR
) || isdot3rgba
) {
813 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
814 const GLuint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
815 const GLuint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
];
818 /* op 0/1 are referencing color, op 2/3 alpha */
819 stageref
[j
] |= (op
>> 1) + 1;
822 texregfree
[j
] = GL_FALSE
;
830 texregfree
[srcRGBi
- GL_TEXTURE0
] = GL_FALSE
;
832 default: /* don't care about other sources here */
838 /* alpha args are ignored for dot3_rgba */
839 if ((stageref
[j
+ 1] & REF_ALPHA
) && !isdot3rgba
) {
841 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
842 const GLuint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
845 stageref
[j
] |= REF_ALPHA
;
848 texregfree
[j
] = GL_FALSE
;
856 texregfree
[srcAi
- GL_TEXTURE0
] = GL_FALSE
;
858 default: /* don't care about other sources here */
866 /* don't enable texture sampling for units if the result is not used */
867 for (i
= 0; i
< R200_MAX_TEXTURE_UNITS
; i
++) {
868 if (ctx
->Texture
.Unit
[i
]._Current
&& !texregfree
[i
])
869 rmesa
->state
.texture
.unit
[i
].unitneeded
= 1 << _mesa_tex_target_to_index(ctx
, ctx
->Texture
.Unit
[i
]._Current
->Target
);
870 else rmesa
->state
.texture
.unit
[i
].unitneeded
= 0;
875 rmesa
->state
.envneeded
= 1;
878 while ((i
<= maxunitused
) && (i
>= 0)) {
879 /* only output instruction if the results are referenced */
880 if (ctx
->Texture
.Unit
[i
]._Current
&& stageref
[i
+1]) {
881 GLuint replaceunit
= i
;
882 /* try to optimize GL_REPLACE away (only one level deep though) */
883 if ( (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ModeRGB
== GL_REPLACE
) &&
884 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ModeA
== GL_REPLACE
) &&
885 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ScaleShiftRGB
== 0) &&
886 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ScaleShiftA
== 0) &&
887 (nextunit
[i
] > 0) ) {
888 /* yippie! can optimize it away! */
893 /* need env instruction slot */
894 rmesa
->state
.envneeded
|= 1 << currslot
;
895 ok
= r200UpdateTextureEnv( ctx
, i
, currslot
, replaceunit
);
896 if (!ok
) return GL_FALSE
;
903 /* need one stage at least */
904 rmesa
->state
.texture
.unit
[0].outputreg
= 0;
905 ok
= r200UpdateTextureEnv( ctx
, 0, 0, 0 );
908 R200_STATECHANGE( rmesa
, ctx
);
909 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~(R200_TEX_BLEND_ENABLE_MASK
| R200_MULTI_PASS_ENABLE
);
910 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= rmesa
->state
.envneeded
<< R200_TEX_BLEND_0_ENABLE_SHIFT
;
919 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
920 R200_MIN_FILTER_MASK | \
921 R200_MAG_FILTER_MASK | \
922 R200_MAX_ANISO_MASK | \
924 R200_YUV_TEMPERATURE_MASK | \
925 R200_CLAMP_S_MASK | \
926 R200_CLAMP_T_MASK | \
927 R200_BORDER_MODE_D3D )
929 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
930 R200_TXFORMAT_HEIGHT_MASK | \
931 R200_TXFORMAT_FORMAT_MASK | \
932 R200_TXFORMAT_F5_WIDTH_MASK | \
933 R200_TXFORMAT_F5_HEIGHT_MASK | \
934 R200_TXFORMAT_ALPHA_IN_MAP | \
935 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
936 R200_TXFORMAT_NON_POWER2)
938 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
939 R200_TEXCOORD_MASK | \
940 R200_MIN_MIP_LEVEL_MASK | \
941 R200_CLAMP_Q_MASK | \
942 R200_VOLUME_FILTER_MASK)
945 static void disable_tex_obj_state( r200ContextPtr rmesa
,
949 R200_STATECHANGE( rmesa
, vtx
);
950 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
952 R200_STATECHANGE( rmesa
, ctx
);
953 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~(R200_TEX_0_ENABLE
<< unit
);
954 if (rmesa
->radeon
.TclFallback
& (R200_TCL_FALLBACK_TEXGEN_0
<<unit
)) {
955 TCL_FALLBACK( &rmesa
->radeon
.glCtx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), GL_FALSE
);
958 /* Actually want to keep all units less than max active texture
959 * enabled, right? Fix this for >2 texunits.
963 GLuint tmp
= rmesa
->TexGenEnabled
;
965 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
966 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
967 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
968 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
970 if (tmp
!= rmesa
->TexGenEnabled
) {
971 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
972 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE_MATRIX
;
976 static void import_tex_obj_state( r200ContextPtr rmesa
,
978 radeonTexObjPtr texobj
)
980 /* do not use RADEON_DB_STATE to avoid stale texture caches */
981 GLuint
*cmd
= &rmesa
->hw
.tex
[unit
].cmd
[TEX_CMD_0
];
983 R200_STATECHANGE( rmesa
, tex
[unit
] );
985 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
986 cmd
[TEX_PP_TXFILTER
] |= texobj
->pp_txfilter
& TEXOBJ_TXFILTER_MASK
;
987 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
988 cmd
[TEX_PP_TXFORMAT
] |= texobj
->pp_txformat
& TEXOBJ_TXFORMAT_MASK
;
989 cmd
[TEX_PP_TXFORMAT_X
] &= ~TEXOBJ_TXFORMAT_X_MASK
;
990 cmd
[TEX_PP_TXFORMAT_X
] |= texobj
->pp_txformat_x
& TEXOBJ_TXFORMAT_X_MASK
;
991 cmd
[TEX_PP_TXSIZE
] = texobj
->pp_txsize
; /* NPOT only! */
992 cmd
[TEX_PP_TXPITCH
] = texobj
->pp_txpitch
; /* NPOT only! */
993 cmd
[TEX_PP_BORDER_COLOR
] = texobj
->pp_border_color
;
995 if (texobj
->base
.Target
== GL_TEXTURE_CUBE_MAP
) {
996 GLuint
*cube_cmd
= &rmesa
->hw
.cube
[unit
].cmd
[CUBE_CMD_0
];
998 R200_STATECHANGE( rmesa
, cube
[unit
] );
999 cube_cmd
[CUBE_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
1000 /* that value is submitted twice. could change cube atom
1001 to not include that command when new drm is used */
1002 cmd
[TEX_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
1007 static void set_texgen_matrix( r200ContextPtr rmesa
,
1009 const GLfloat
*s_plane
,
1010 const GLfloat
*t_plane
,
1011 const GLfloat
*r_plane
,
1012 const GLfloat
*q_plane
)
1036 _math_matrix_loadf( &(rmesa
->TexGenMatrix
[unit
]), m
);
1037 _math_matrix_analyse( &(rmesa
->TexGenMatrix
[unit
]) );
1038 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<<unit
;
1042 static GLuint
r200_need_dis_texgen(const GLbitfield texGenEnabled
,
1043 const GLfloat
*planeS
,
1044 const GLfloat
*planeT
,
1045 const GLfloat
*planeR
,
1046 const GLfloat
*planeQ
)
1048 GLuint needtgenable
= 0;
1050 if (!(texGenEnabled
& S_BIT
)) {
1051 if (((texGenEnabled
& T_BIT
) && planeT
[0] != 0.0) ||
1052 ((texGenEnabled
& R_BIT
) && planeR
[0] != 0.0) ||
1053 ((texGenEnabled
& Q_BIT
) && planeQ
[0] != 0.0)) {
1054 needtgenable
|= S_BIT
;
1057 if (!(texGenEnabled
& T_BIT
)) {
1058 if (((texGenEnabled
& S_BIT
) && planeS
[1] != 0.0) ||
1059 ((texGenEnabled
& R_BIT
) && planeR
[1] != 0.0) ||
1060 ((texGenEnabled
& Q_BIT
) && planeQ
[1] != 0.0)) {
1061 needtgenable
|= T_BIT
;
1064 if (!(texGenEnabled
& R_BIT
)) {
1065 if (((texGenEnabled
& S_BIT
) && planeS
[2] != 0.0) ||
1066 ((texGenEnabled
& T_BIT
) && planeT
[2] != 0.0) ||
1067 ((texGenEnabled
& Q_BIT
) && planeQ
[2] != 0.0)) {
1068 needtgenable
|= R_BIT
;
1071 if (!(texGenEnabled
& Q_BIT
)) {
1072 if (((texGenEnabled
& S_BIT
) && planeS
[3] != 0.0) ||
1073 ((texGenEnabled
& T_BIT
) && planeT
[3] != 0.0) ||
1074 ((texGenEnabled
& R_BIT
) && planeR
[3] != 0.0)) {
1075 needtgenable
|= Q_BIT
;
1079 return needtgenable
;
1084 * Returns GL_FALSE if fallback required.
1086 static GLboolean
r200_validate_texgen( struct gl_context
*ctx
, GLuint unit
)
1088 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1089 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1090 GLuint inputshift
= R200_TEXGEN_0_INPUT_SHIFT
+ unit
*4;
1093 GLboolean mixed_fallback
= GL_FALSE
;
1094 static const GLfloat I
[16] = {
1099 static const GLfloat reflect
[16] = {
1105 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1106 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
1107 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
1108 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
1109 tgi
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] & ~(R200_TEXGEN_INPUT_MASK
<<
1111 tgcm
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] & ~(R200_TEXGEN_COMP_MASK
<<
1115 fprintf(stderr
, "%s unit %d\n", __func__
, unit
);
1117 if (texUnit
->TexGenEnabled
& S_BIT
) {
1118 mode
= texUnit
->GenS
.Mode
;
1120 tgcm
|= R200_TEXGEN_COMP_S
<< (unit
* 4);
1123 if (texUnit
->TexGenEnabled
& T_BIT
) {
1124 if (texUnit
->GenT
.Mode
!= mode
)
1125 mixed_fallback
= GL_TRUE
;
1127 tgcm
|= R200_TEXGEN_COMP_T
<< (unit
* 4);
1129 if (texUnit
->TexGenEnabled
& R_BIT
) {
1130 if (texUnit
->GenR
.Mode
!= mode
)
1131 mixed_fallback
= GL_TRUE
;
1133 tgcm
|= R200_TEXGEN_COMP_R
<< (unit
* 4);
1136 if (texUnit
->TexGenEnabled
& Q_BIT
) {
1137 if (texUnit
->GenQ
.Mode
!= mode
)
1138 mixed_fallback
= GL_TRUE
;
1140 tgcm
|= R200_TEXGEN_COMP_Q
<< (unit
* 4);
1143 if (mixed_fallback
) {
1144 if (R200_DEBUG
& RADEON_FALLBACKS
)
1145 fprintf(stderr
, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
1146 texUnit
->TexGenEnabled
, texUnit
->GenS
.Mode
, texUnit
->GenT
.Mode
,
1147 texUnit
->GenR
.Mode
, texUnit
->GenQ
.Mode
);
1151 /* we CANNOT do mixed mode if the texgen mode requires a plane where the input
1152 is not enabled for texgen, since the planes are concatenated into texmat,
1153 and thus the input will come from texcoord rather than tex gen equation!
1154 Either fallback or just hope that those texcoords aren't really needed...
1155 Assuming the former will cause lots of unnecessary fallbacks, the latter will
1156 generate bogus results sometimes - it's pretty much impossible to really know
1157 when a fallback is needed, depends on texmat and what sort of texture is bound
1158 etc, - for now fallback if we're missing either S or T bits, there's a high
1159 probability we need the texcoords in that case.
1160 That's a lot of work for some obscure texgen mixed mode fixup - why oh why
1161 doesn't the chip just directly accept the plane parameters :-(. */
1163 case GL_OBJECT_LINEAR
: {
1164 GLuint needtgenable
= r200_need_dis_texgen( texUnit
->TexGenEnabled
,
1165 texUnit
->GenS
.ObjectPlane
,
1166 texUnit
->GenT
.ObjectPlane
,
1167 texUnit
->GenR
.ObjectPlane
,
1168 texUnit
->GenQ
.ObjectPlane
);
1169 if (needtgenable
& (S_BIT
| T_BIT
)) {
1170 if (R200_DEBUG
& RADEON_FALLBACKS
)
1171 fprintf(stderr
, "fallback mixed texgen / obj plane, 0x%x\n",
1172 texUnit
->TexGenEnabled
);
1175 if (needtgenable
& (R_BIT
)) {
1176 tgcm
&= ~(R200_TEXGEN_COMP_R
<< (unit
* 4));
1178 if (needtgenable
& (Q_BIT
)) {
1179 tgcm
&= ~(R200_TEXGEN_COMP_Q
<< (unit
* 4));
1182 tgi
|= R200_TEXGEN_INPUT_OBJ
<< inputshift
;
1183 set_texgen_matrix( rmesa
, unit
,
1184 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->GenS
.ObjectPlane
: I
,
1185 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->GenT
.ObjectPlane
: I
+ 4,
1186 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->GenR
.ObjectPlane
: I
+ 8,
1187 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->GenQ
.ObjectPlane
: I
+ 12);
1191 case GL_EYE_LINEAR
: {
1192 GLuint needtgenable
= r200_need_dis_texgen( texUnit
->TexGenEnabled
,
1193 texUnit
->GenS
.EyePlane
,
1194 texUnit
->GenT
.EyePlane
,
1195 texUnit
->GenR
.EyePlane
,
1196 texUnit
->GenQ
.EyePlane
);
1197 if (needtgenable
& (S_BIT
| T_BIT
)) {
1198 if (R200_DEBUG
& RADEON_FALLBACKS
)
1199 fprintf(stderr
, "fallback mixed texgen / eye plane, 0x%x\n",
1200 texUnit
->TexGenEnabled
);
1203 if (needtgenable
& (R_BIT
)) {
1204 tgcm
&= ~(R200_TEXGEN_COMP_R
<< (unit
* 4));
1206 if (needtgenable
& (Q_BIT
)) {
1207 tgcm
&= ~(R200_TEXGEN_COMP_Q
<< (unit
* 4));
1209 tgi
|= R200_TEXGEN_INPUT_EYE
<< inputshift
;
1210 set_texgen_matrix( rmesa
, unit
,
1211 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->GenS
.EyePlane
: I
,
1212 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->GenT
.EyePlane
: I
+ 4,
1213 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->GenR
.EyePlane
: I
+ 8,
1214 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->GenQ
.EyePlane
: I
+ 12);
1218 case GL_REFLECTION_MAP_NV
:
1219 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1220 tgi
|= R200_TEXGEN_INPUT_EYE_REFLECT
<< inputshift
;
1221 /* pretty weird, must only negate when lighting is enabled? */
1222 if (ctx
->Light
.Enabled
)
1223 set_texgen_matrix( rmesa
, unit
,
1224 (texUnit
->TexGenEnabled
& S_BIT
) ? reflect
: I
,
1225 (texUnit
->TexGenEnabled
& T_BIT
) ? reflect
+ 4 : I
+ 4,
1226 (texUnit
->TexGenEnabled
& R_BIT
) ? reflect
+ 8 : I
+ 8,
1230 case GL_NORMAL_MAP_NV
:
1231 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1232 tgi
|= R200_TEXGEN_INPUT_EYE_NORMAL
<<inputshift
;
1236 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1237 tgi
|= R200_TEXGEN_INPUT_SPHERE
<<inputshift
;
1241 /* All texgen units were disabled, so just pass coords through. */
1242 tgi
|= unit
<< inputshift
;
1246 /* Unsupported mode, fallback:
1248 if (R200_DEBUG
& RADEON_FALLBACKS
)
1249 fprintf(stderr
, "fallback unsupported texgen, %d\n",
1250 texUnit
->GenS
.Mode
);
1254 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
1255 rmesa
->TexGenCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
1257 if (tgi
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] ||
1258 tgcm
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
])
1260 R200_STATECHANGE(rmesa
, tcg
);
1261 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] = tgi
;
1262 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] = tgcm
;
1268 void set_re_cntl_d3d( struct gl_context
*ctx
, int unit
, GLboolean use_d3d
)
1270 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1274 re_cntl
= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] & ~(R200_VTX_STQ0_D3D
<< (2 * unit
));
1276 re_cntl
|= R200_VTX_STQ0_D3D
<< (2 * unit
);
1278 if ( re_cntl
!= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] ) {
1279 R200_STATECHANGE( rmesa
, set
);
1280 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] = re_cntl
;
1285 * Compute the cached hardware register values for the given texture object.
1287 * \param rmesa Context pointer
1288 * \param t the r300 texture object
1290 static void setup_hardware_state(r200ContextPtr rmesa
, radeonTexObj
*t
)
1292 const struct gl_texture_image
*firstImage
= t
->base
.Image
[0][t
->minLod
];
1293 GLint log2Width
, log2Height
, log2Depth
, texelBytes
;
1294 uint extra_size
= 0;
1300 log2Width
= firstImage
->WidthLog2
;
1301 log2Height
= firstImage
->HeightLog2
;
1302 log2Depth
= firstImage
->DepthLog2
;
1303 texelBytes
= _mesa_get_format_bytes(firstImage
->TexFormat
);
1305 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
1306 "%s(%p, tex %p) log2(w %d, h %d, d %d), texelBytes %d. format %d\n",
1307 __func__
, rmesa
, t
, log2Width
, log2Height
,
1308 log2Depth
, texelBytes
, firstImage
->TexFormat
);
1310 if (!t
->image_override
) {
1311 if (VALID_FORMAT(firstImage
->TexFormat
)) {
1312 const struct tx_table
*table
= _mesa_little_endian() ? tx_table_le
:
1315 t
->pp_txformat
&= ~(R200_TXFORMAT_FORMAT_MASK
|
1316 R200_TXFORMAT_ALPHA_IN_MAP
);
1317 t
->pp_txfilter
&= ~R200_YUV_TO_RGB
;
1319 t
->pp_txformat
|= table
[ firstImage
->TexFormat
].format
;
1320 t
->pp_txfilter
|= table
[ firstImage
->TexFormat
].filter
;
1324 _mesa_problem(NULL
, "unexpected texture format in %s",
1330 t
->pp_txfilter
&= ~R200_MAX_MIP_LEVEL_MASK
;
1331 t
->pp_txfilter
|= ((t
->maxLod
) << R200_MAX_MIP_LEVEL_SHIFT
)
1332 & R200_MAX_MIP_LEVEL_MASK
;
1334 if ( t
->pp_txfilter
&
1335 (R200_MIN_FILTER_NEAREST_MIP_NEAREST
1336 | R200_MIN_FILTER_NEAREST_MIP_LINEAR
1337 | R200_MIN_FILTER_LINEAR_MIP_NEAREST
1338 | R200_MIN_FILTER_LINEAR_MIP_LINEAR
1339 | R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
1340 | R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR
))
1341 extra_size
= t
->minLod
;
1343 t
->pp_txformat
&= ~(R200_TXFORMAT_WIDTH_MASK
|
1344 R200_TXFORMAT_HEIGHT_MASK
|
1345 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
1346 R200_TXFORMAT_F5_WIDTH_MASK
|
1347 R200_TXFORMAT_F5_HEIGHT_MASK
);
1348 t
->pp_txformat
|= (((log2Width
+ extra_size
) << R200_TXFORMAT_WIDTH_SHIFT
) |
1349 ((log2Height
+ extra_size
)<< R200_TXFORMAT_HEIGHT_SHIFT
));
1353 t
->pp_txformat_x
&= ~(R200_DEPTH_LOG2_MASK
| R200_TEXCOORD_MASK
1354 | R200_MIN_MIP_LEVEL_MASK
);
1356 t
->pp_txformat_x
|= (t
->minLod
<< R200_MIN_MIP_LEVEL_SHIFT
)
1357 & R200_MIN_MIP_LEVEL_MASK
;
1359 if (t
->base
.Target
== GL_TEXTURE_3D
) {
1360 t
->pp_txformat_x
|= (log2Depth
<< R200_DEPTH_LOG2_SHIFT
);
1361 t
->pp_txformat_x
|= R200_TEXCOORD_VOLUME
;
1364 else if (t
->base
.Target
== GL_TEXTURE_CUBE_MAP
) {
1365 assert(log2Width
== log2Height
);
1366 t
->pp_txformat
|= ((log2Width
<< R200_TXFORMAT_F5_WIDTH_SHIFT
) |
1367 (log2Height
<< R200_TXFORMAT_F5_HEIGHT_SHIFT
) |
1368 /* don't think we need this bit, if it exists at all - fglrx does not set it */
1369 (R200_TXFORMAT_CUBIC_MAP_ENABLE
));
1370 t
->pp_txformat_x
|= R200_TEXCOORD_CUBIC_ENV
;
1371 t
->pp_cubic_faces
= ((log2Width
<< R200_FACE_WIDTH_1_SHIFT
) |
1372 (log2Height
<< R200_FACE_HEIGHT_1_SHIFT
) |
1373 (log2Width
<< R200_FACE_WIDTH_2_SHIFT
) |
1374 (log2Height
<< R200_FACE_HEIGHT_2_SHIFT
) |
1375 (log2Width
<< R200_FACE_WIDTH_3_SHIFT
) |
1376 (log2Height
<< R200_FACE_HEIGHT_3_SHIFT
) |
1377 (log2Width
<< R200_FACE_WIDTH_4_SHIFT
) |
1378 (log2Height
<< R200_FACE_HEIGHT_4_SHIFT
));
1381 /* If we don't in fact send enough texture coordinates, q will be 1,
1382 * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
1384 t
->pp_txformat_x
|= R200_TEXCOORD_PROJ
;
1386 /* FIXME: NPOT sizes, is it correct really? */
1387 t
->pp_txsize
= (((firstImage
->Width
- 1) << R200_PP_TX_WIDTHMASK_SHIFT
)
1388 | ((firstImage
->Height
- 1) << R200_PP_TX_HEIGHTMASK_SHIFT
));
1390 if ( !t
->image_override
) {
1391 if (_mesa_is_format_compressed(firstImage
->TexFormat
))
1392 t
->pp_txpitch
= (firstImage
->Width
+ 63) & ~(63);
1394 t
->pp_txpitch
= ((firstImage
->Width
* texelBytes
) + 63) & ~(63);
1395 t
->pp_txpitch
-= 32;
1398 if (t
->base
.Target
== GL_TEXTURE_RECTANGLE_NV
) {
1399 t
->pp_txformat
|= R200_TXFORMAT_NON_POWER2
;
1404 static GLboolean
r200_validate_texture(struct gl_context
*ctx
, struct gl_texture_object
*texObj
, int unit
)
1406 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1407 radeonTexObj
*t
= radeon_tex_obj(texObj
);
1409 if (!radeon_validate_texture_miptree(ctx
, _mesa_get_samplerobj(ctx
, unit
), texObj
))
1412 r200_validate_texgen(ctx
, unit
);
1413 /* Configure the hardware registers (more precisely, the cached version
1414 * of the hardware registers). */
1415 setup_hardware_state(rmesa
, t
);
1417 if (texObj
->Target
== GL_TEXTURE_RECTANGLE_NV
||
1418 texObj
->Target
== GL_TEXTURE_2D
||
1419 texObj
->Target
== GL_TEXTURE_1D
)
1420 set_re_cntl_d3d( ctx
, unit
, GL_FALSE
);
1422 set_re_cntl_d3d( ctx
, unit
, GL_TRUE
);
1423 R200_STATECHANGE( rmesa
, ctx
);
1424 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_0_ENABLE
<< unit
;
1426 R200_STATECHANGE( rmesa
, vtx
);
1427 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
1428 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] |= 4 << (unit
* 3);
1430 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1431 r200TexUpdateParameters(ctx
, unit
);
1432 import_tex_obj_state( rmesa
, unit
, t
);
1434 if (rmesa
->recheck_texgen
[unit
]) {
1435 GLboolean fallback
= !r200_validate_texgen( ctx
, unit
);
1436 TCL_FALLBACK( ctx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), fallback
);
1437 rmesa
->recheck_texgen
[unit
] = 0;
1438 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE_MATRIX
;
1441 t
->validated
= GL_TRUE
;
1443 FALLBACK( rmesa
, RADEON_FALLBACK_BORDER_MODE
, t
->border_fallback
);
1445 return !t
->border_fallback
;
1448 static GLboolean
r200UpdateTextureUnit(struct gl_context
*ctx
, int unit
)
1450 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1451 GLuint unitneeded
= rmesa
->state
.texture
.unit
[unit
].unitneeded
;
1454 /* disable the unit */
1455 disable_tex_obj_state(rmesa
, unit
);
1459 if (!r200_validate_texture(ctx
, ctx
->Texture
.Unit
[unit
]._Current
, unit
)) {
1461 "failed to validate texture for unit %d.\n",
1463 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
1467 rmesa
->state
.texture
.unit
[unit
].texobj
= radeon_tex_obj(ctx
->Texture
.Unit
[unit
]._Current
);
1472 void r200UpdateTextureState( struct gl_context
*ctx
)
1474 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1478 /* NOTE: must not manipulate rmesa->state.texture.unit[].unitneeded or
1479 rmesa->state.envneeded before a R200_STATECHANGE (or R200_NEWPRIM) since
1480 we use these to determine if we want to emit the corresponding state
1482 R200_NEWPRIM( rmesa
);
1484 if (_mesa_ati_fragment_shader_enabled(ctx
)) {
1486 for (i
= 0; i
< R200_MAX_TEXTURE_UNITS
; i
++) {
1487 if (ctx
->Texture
.Unit
[i
]._Current
)
1488 rmesa
->state
.texture
.unit
[i
].unitneeded
= 1 << _mesa_tex_target_to_index(ctx
, ctx
->Texture
.Unit
[i
]._Current
->Target
);
1490 rmesa
->state
.texture
.unit
[i
].unitneeded
= 0;
1495 ok
= r200UpdateAllTexEnv( ctx
);
1498 ok
= (r200UpdateTextureUnit( ctx
, 0 ) &&
1499 r200UpdateTextureUnit( ctx
, 1 ) &&
1500 r200UpdateTextureUnit( ctx
, 2 ) &&
1501 r200UpdateTextureUnit( ctx
, 3 ) &&
1502 r200UpdateTextureUnit( ctx
, 4 ) &&
1503 r200UpdateTextureUnit( ctx
, 5 ));
1506 if (ok
&& _mesa_ati_fragment_shader_enabled(ctx
)) {
1507 r200UpdateFragmentShader(ctx
);
1510 FALLBACK( rmesa
, R200_FALLBACK_TEXTURE
, !ok
);
1512 if (rmesa
->radeon
.TclFallback
)
1513 r200ChooseVertexState( ctx
);
1516 if (rmesa
->radeon
.radeonScreen
->chip_family
== CHIP_FAMILY_R200
) {
1519 * T0 hang workaround -------------
1520 * not needed for r200 derivatives
1522 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_ENABLE_MASK
) == R200_TEX_0_ENABLE
&&
1523 (rmesa
->hw
.tex
[0].cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) > R200_MIN_FILTER_LINEAR
) {
1525 R200_STATECHANGE(rmesa
, ctx
);
1526 R200_STATECHANGE(rmesa
, tex
[1]);
1527 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_1_ENABLE
;
1528 if (!(rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] & R200_PPX_TEX_1_ENABLE
))
1529 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1530 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] |= R200_TXFORMAT_LOOKUP_DISABLE
;
1532 else if (!_mesa_ati_fragment_shader_enabled(ctx
)) {
1533 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
) &&
1534 (rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] & R200_TXFORMAT_LOOKUP_DISABLE
)) {
1535 R200_STATECHANGE(rmesa
, tex
[1]);
1536 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~R200_TXFORMAT_LOOKUP_DISABLE
;
1539 /* do the same workaround for the first pass of a fragment shader.
1540 * completely unknown if necessary / sufficient.
1542 if ((rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] & R200_PPX_TEX_ENABLE_MASK
) == R200_PPX_TEX_0_ENABLE
&&
1543 (rmesa
->hw
.tex
[0].cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) > R200_MIN_FILTER_LINEAR
) {
1545 R200_STATECHANGE(rmesa
, cst
);
1546 R200_STATECHANGE(rmesa
, tex
[1]);
1547 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] |= R200_PPX_TEX_1_ENABLE
;
1548 if (!(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
))
1549 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1550 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXMULTI_CTL
] |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE
;
1553 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1554 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1555 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1556 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1557 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1558 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1559 R200_MIN_FILTER_LINEAR)) {
1560 R200_STATECHANGE(rmesa, ctx);
1561 R200_STATECHANGE(rmesa, tex[i+1]);
1562 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1563 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1564 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1567 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1568 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1569 R200_STATECHANGE(rmesa, tex[i+1]);
1570 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1576 * Texture cache LRU hang workaround -------------
1577 * not needed for r200 derivatives
1578 * hopefully this covers first pass of a shader as well
1581 /* While the cases below attempt to only enable the workaround in the
1582 * specific cases necessary, they were insufficient. See bugzilla #1519,
1583 * #729, #814. Tests with quake3 showed no impact on performance.
1588 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) &&
1589 ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1591 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1592 ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1594 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1595 ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1601 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) &&
1602 ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1604 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1605 ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1607 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1608 ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1614 if (dbg
!= rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
]) {
1615 R200_STATECHANGE( rmesa
, tam
);
1616 rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
] = dbg
;
1617 if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg
);