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/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"
52 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
53 && (tx_table_be[f].format != 0xffffffff) )
55 /* ================================================================
56 * Texture combine functions
59 /* GL_ARB_texture_env_combine support
62 /* The color tables have combine functions for GL_SRC_COLOR,
63 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
65 static GLuint r200_register_color
[][R200_MAX_TEXTURE_UNITS
] =
68 R200_TXC_ARG_A_R0_COLOR
,
69 R200_TXC_ARG_A_R1_COLOR
,
70 R200_TXC_ARG_A_R2_COLOR
,
71 R200_TXC_ARG_A_R3_COLOR
,
72 R200_TXC_ARG_A_R4_COLOR
,
73 R200_TXC_ARG_A_R5_COLOR
76 R200_TXC_ARG_A_R0_COLOR
| R200_TXC_COMP_ARG_A
,
77 R200_TXC_ARG_A_R1_COLOR
| R200_TXC_COMP_ARG_A
,
78 R200_TXC_ARG_A_R2_COLOR
| R200_TXC_COMP_ARG_A
,
79 R200_TXC_ARG_A_R3_COLOR
| R200_TXC_COMP_ARG_A
,
80 R200_TXC_ARG_A_R4_COLOR
| R200_TXC_COMP_ARG_A
,
81 R200_TXC_ARG_A_R5_COLOR
| R200_TXC_COMP_ARG_A
84 R200_TXC_ARG_A_R0_ALPHA
,
85 R200_TXC_ARG_A_R1_ALPHA
,
86 R200_TXC_ARG_A_R2_ALPHA
,
87 R200_TXC_ARG_A_R3_ALPHA
,
88 R200_TXC_ARG_A_R4_ALPHA
,
89 R200_TXC_ARG_A_R5_ALPHA
92 R200_TXC_ARG_A_R0_ALPHA
| R200_TXC_COMP_ARG_A
,
93 R200_TXC_ARG_A_R1_ALPHA
| R200_TXC_COMP_ARG_A
,
94 R200_TXC_ARG_A_R2_ALPHA
| R200_TXC_COMP_ARG_A
,
95 R200_TXC_ARG_A_R3_ALPHA
| R200_TXC_COMP_ARG_A
,
96 R200_TXC_ARG_A_R4_ALPHA
| R200_TXC_COMP_ARG_A
,
97 R200_TXC_ARG_A_R5_ALPHA
| R200_TXC_COMP_ARG_A
101 static GLuint r200_tfactor_color
[] =
103 R200_TXC_ARG_A_TFACTOR_COLOR
,
104 R200_TXC_ARG_A_TFACTOR_COLOR
| R200_TXC_COMP_ARG_A
,
105 R200_TXC_ARG_A_TFACTOR_ALPHA
,
106 R200_TXC_ARG_A_TFACTOR_ALPHA
| R200_TXC_COMP_ARG_A
109 static GLuint r200_tfactor1_color
[] =
111 R200_TXC_ARG_A_TFACTOR1_COLOR
,
112 R200_TXC_ARG_A_TFACTOR1_COLOR
| R200_TXC_COMP_ARG_A
,
113 R200_TXC_ARG_A_TFACTOR1_ALPHA
,
114 R200_TXC_ARG_A_TFACTOR1_ALPHA
| R200_TXC_COMP_ARG_A
117 static GLuint r200_primary_color
[] =
119 R200_TXC_ARG_A_DIFFUSE_COLOR
,
120 R200_TXC_ARG_A_DIFFUSE_COLOR
| R200_TXC_COMP_ARG_A
,
121 R200_TXC_ARG_A_DIFFUSE_ALPHA
,
122 R200_TXC_ARG_A_DIFFUSE_ALPHA
| R200_TXC_COMP_ARG_A
125 /* GL_ZERO table - indices 0-3
126 * GL_ONE table - indices 1-4
128 static GLuint r200_zero_color
[] =
131 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
133 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
137 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
139 static GLuint r200_register_alpha
[][R200_MAX_TEXTURE_UNITS
] =
142 R200_TXA_ARG_A_R0_ALPHA
,
143 R200_TXA_ARG_A_R1_ALPHA
,
144 R200_TXA_ARG_A_R2_ALPHA
,
145 R200_TXA_ARG_A_R3_ALPHA
,
146 R200_TXA_ARG_A_R4_ALPHA
,
147 R200_TXA_ARG_A_R5_ALPHA
150 R200_TXA_ARG_A_R0_ALPHA
| R200_TXA_COMP_ARG_A
,
151 R200_TXA_ARG_A_R1_ALPHA
| R200_TXA_COMP_ARG_A
,
152 R200_TXA_ARG_A_R2_ALPHA
| R200_TXA_COMP_ARG_A
,
153 R200_TXA_ARG_A_R3_ALPHA
| R200_TXA_COMP_ARG_A
,
154 R200_TXA_ARG_A_R4_ALPHA
| R200_TXA_COMP_ARG_A
,
155 R200_TXA_ARG_A_R5_ALPHA
| R200_TXA_COMP_ARG_A
159 static GLuint r200_tfactor_alpha
[] =
161 R200_TXA_ARG_A_TFACTOR_ALPHA
,
162 R200_TXA_ARG_A_TFACTOR_ALPHA
| R200_TXA_COMP_ARG_A
165 static GLuint r200_tfactor1_alpha
[] =
167 R200_TXA_ARG_A_TFACTOR1_ALPHA
,
168 R200_TXA_ARG_A_TFACTOR1_ALPHA
| R200_TXA_COMP_ARG_A
171 static GLuint r200_primary_alpha
[] =
173 R200_TXA_ARG_A_DIFFUSE_ALPHA
,
174 R200_TXA_ARG_A_DIFFUSE_ALPHA
| R200_TXA_COMP_ARG_A
177 /* GL_ZERO table - indices 0-1
178 * GL_ONE table - indices 1-2
180 static GLuint r200_zero_alpha
[] =
183 R200_TXA_ARG_A_ZERO
| R200_TXA_COMP_ARG_A
,
188 /* Extract the arg from slot A, shift it into the correct argument slot
189 * and set the corresponding complement bit.
191 #define R200_COLOR_ARG( n, arg ) \
194 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
195 << R200_TXC_ARG_##arg##_SHIFT); \
197 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
198 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
201 #define R200_ALPHA_ARG( n, arg ) \
204 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
205 << R200_TXA_ARG_##arg##_SHIFT); \
207 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
208 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
212 /* ================================================================
213 * Texture unit state management
216 static GLboolean
r200UpdateTextureEnv( struct gl_context
*ctx
, int unit
, int slot
, GLuint replaceargs
)
218 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
219 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
220 GLuint color_combine
, alpha_combine
;
221 GLuint color_scale
= rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] &
222 ~(R200_TXC_SCALE_MASK
| R200_TXC_OUTPUT_REG_MASK
| R200_TXC_TFACTOR_SEL_MASK
|
223 R200_TXC_TFACTOR1_SEL_MASK
);
224 GLuint alpha_scale
= rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] &
225 ~(R200_TXA_DOT_ALPHA
| R200_TXA_SCALE_MASK
| R200_TXA_OUTPUT_REG_MASK
|
226 R200_TXA_TFACTOR_SEL_MASK
| R200_TXA_TFACTOR1_SEL_MASK
);
228 if ( R200_DEBUG
& RADEON_TEXTURE
) {
229 fprintf( stderr
, "%s( %p, %d )\n", __func__
, (void *)ctx
, unit
);
232 /* Set the texture environment state. Isn't this nice and clean?
233 * The chip will automagically set the texture alpha to 0xff when
234 * the texture format does not include an alpha component. This
235 * reduces the amount of special-casing we have to do, alpha-only
236 * textures being a notable exception.
239 color_scale
|= ((rmesa
->state
.texture
.unit
[unit
].outputreg
+ 1) << R200_TXC_OUTPUT_REG_SHIFT
) |
240 (unit
<< R200_TXC_TFACTOR_SEL_SHIFT
) |
241 (replaceargs
<< R200_TXC_TFACTOR1_SEL_SHIFT
);
242 alpha_scale
|= ((rmesa
->state
.texture
.unit
[unit
].outputreg
+ 1) << R200_TXA_OUTPUT_REG_SHIFT
) |
243 (unit
<< R200_TXA_TFACTOR_SEL_SHIFT
) |
244 (replaceargs
<< R200_TXA_TFACTOR1_SEL_SHIFT
);
246 if ( !texUnit
->_Current
) {
248 color_combine
= R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
249 | R200_TXC_ARG_C_DIFFUSE_COLOR
| R200_TXC_OP_MADD
;
250 alpha_combine
= R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
251 | R200_TXA_ARG_C_DIFFUSE_ALPHA
| R200_TXA_OP_MADD
;
254 GLuint color_arg
[3], alpha_arg
[3];
256 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
257 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
258 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
259 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
262 const GLint replaceoprgb
=
263 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->OperandRGB
[0] - GL_SRC_COLOR
;
264 const GLint replaceopa
=
265 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->OperandA
[0] - GL_SRC_ALPHA
;
268 * Extract the color and alpha combine function arguments.
270 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
271 GLint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
] - GL_SRC_COLOR
;
272 const GLint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
277 color_arg
[i
] = r200_register_color
[op
][unit
];
280 color_arg
[i
] = r200_tfactor_color
[op
];
282 case GL_PRIMARY_COLOR
:
283 color_arg
[i
] = r200_primary_color
[op
];
286 if (replaceargs
!= unit
) {
287 const GLint srcRGBreplace
=
288 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->SourceRGB
[0];
290 op
= op
^ replaceopa
;
293 op
= op
^ replaceoprgb
;
295 switch (srcRGBreplace
) {
297 color_arg
[i
] = r200_register_color
[op
][replaceargs
];
300 color_arg
[i
] = r200_tfactor1_color
[op
];
302 case GL_PRIMARY_COLOR
:
303 color_arg
[i
] = r200_primary_color
[op
];
307 color_arg
[i
] = r200_primary_color
[op
];
309 color_arg
[i
] = r200_register_color
[op
]
310 [rmesa
->state
.texture
.unit
[replaceargs
- 1].outputreg
];
313 color_arg
[i
] = r200_zero_color
[op
];
316 color_arg
[i
] = r200_zero_color
[op
+1];
324 color_arg
[i
] = r200_register_color
[op
][srcRGBreplace
- GL_TEXTURE0
];
332 color_arg
[i
] = r200_primary_color
[op
];
334 color_arg
[i
] = r200_register_color
[op
]
335 [rmesa
->state
.texture
.unit
[unit
- 1].outputreg
];
339 color_arg
[i
] = r200_zero_color
[op
];
342 color_arg
[i
] = r200_zero_color
[op
+1];
350 color_arg
[i
] = r200_register_color
[op
][srcRGBi
- GL_TEXTURE0
];
357 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
358 GLint op
= texUnit
->_CurrentCombine
->OperandA
[i
] - GL_SRC_ALPHA
;
359 const GLint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
364 alpha_arg
[i
] = r200_register_alpha
[op
][unit
];
367 alpha_arg
[i
] = r200_tfactor_alpha
[op
];
369 case GL_PRIMARY_COLOR
:
370 alpha_arg
[i
] = r200_primary_alpha
[op
];
373 if (replaceargs
!= unit
) {
374 const GLint srcAreplace
=
375 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->SourceA
[0];
376 op
= op
^ replaceopa
;
377 switch (srcAreplace
) {
379 alpha_arg
[i
] = r200_register_alpha
[op
][replaceargs
];
382 alpha_arg
[i
] = r200_tfactor1_alpha
[op
];
384 case GL_PRIMARY_COLOR
:
385 alpha_arg
[i
] = r200_primary_alpha
[op
];
389 alpha_arg
[i
] = r200_primary_alpha
[op
];
391 alpha_arg
[i
] = r200_register_alpha
[op
]
392 [rmesa
->state
.texture
.unit
[replaceargs
- 1].outputreg
];
395 alpha_arg
[i
] = r200_zero_alpha
[op
];
398 alpha_arg
[i
] = r200_zero_alpha
[op
+1];
406 alpha_arg
[i
] = r200_register_alpha
[op
][srcAreplace
- GL_TEXTURE0
];
414 alpha_arg
[i
] = r200_primary_alpha
[op
];
416 alpha_arg
[i
] = r200_register_alpha
[op
]
417 [rmesa
->state
.texture
.unit
[unit
- 1].outputreg
];
421 alpha_arg
[i
] = r200_zero_alpha
[op
];
424 alpha_arg
[i
] = r200_zero_alpha
[op
+1];
432 alpha_arg
[i
] = r200_register_alpha
[op
][srcAi
- GL_TEXTURE0
];
440 * Build up the color and alpha combine functions.
442 switch ( texUnit
->_CurrentCombine
->ModeRGB
) {
444 color_combine
= (R200_TXC_ARG_A_ZERO
|
445 R200_TXC_ARG_B_ZERO
|
447 R200_COLOR_ARG( 0, C
);
450 color_combine
= (R200_TXC_ARG_C_ZERO
|
452 R200_COLOR_ARG( 0, A
);
453 R200_COLOR_ARG( 1, B
);
456 color_combine
= (R200_TXC_ARG_B_ZERO
|
457 R200_TXC_COMP_ARG_B
|
459 R200_COLOR_ARG( 0, A
);
460 R200_COLOR_ARG( 1, C
);
463 color_combine
= (R200_TXC_ARG_B_ZERO
|
464 R200_TXC_COMP_ARG_B
|
465 R200_TXC_BIAS_ARG_C
| /* new */
466 R200_TXC_OP_MADD
); /* was ADDSIGNED */
467 R200_COLOR_ARG( 0, A
);
468 R200_COLOR_ARG( 1, C
);
471 color_combine
= (R200_TXC_ARG_B_ZERO
|
472 R200_TXC_COMP_ARG_B
|
475 R200_COLOR_ARG( 0, A
);
476 R200_COLOR_ARG( 1, C
);
479 color_combine
= (R200_TXC_OP_LERP
);
480 R200_COLOR_ARG( 0, B
);
481 R200_COLOR_ARG( 1, A
);
482 R200_COLOR_ARG( 2, C
);
485 case GL_DOT3_RGB_EXT
:
486 case GL_DOT3_RGBA_EXT
:
487 /* The EXT version of the DOT3 extension does not support the
488 * scale factor, but the ARB version (and the version in OpenGL
496 /* DOT3 works differently on R200 than on R100. On R100, just
497 * setting the DOT3 mode did everything for you. On R200, the
498 * driver has to enable the biasing and scale in the inputs to
499 * put them in the proper [-1,1] range. This is what the 4x and
500 * the -0.5 in the DOT3 spec do. The post-scale is then set
504 color_combine
= (R200_TXC_ARG_C_ZERO
|
506 R200_TXC_BIAS_ARG_A
|
507 R200_TXC_BIAS_ARG_B
|
508 R200_TXC_SCALE_ARG_A
|
509 R200_TXC_SCALE_ARG_B
);
510 R200_COLOR_ARG( 0, A
);
511 R200_COLOR_ARG( 1, B
);
514 case GL_MODULATE_ADD_ATI
:
515 color_combine
= (R200_TXC_OP_MADD
);
516 R200_COLOR_ARG( 0, A
);
517 R200_COLOR_ARG( 1, C
);
518 R200_COLOR_ARG( 2, B
);
520 case GL_MODULATE_SIGNED_ADD_ATI
:
521 color_combine
= (R200_TXC_BIAS_ARG_C
| /* new */
522 R200_TXC_OP_MADD
); /* was ADDSIGNED */
523 R200_COLOR_ARG( 0, A
);
524 R200_COLOR_ARG( 1, C
);
525 R200_COLOR_ARG( 2, B
);
527 case GL_MODULATE_SUBTRACT_ATI
:
528 color_combine
= (R200_TXC_NEG_ARG_C
|
530 R200_COLOR_ARG( 0, A
);
531 R200_COLOR_ARG( 1, C
);
532 R200_COLOR_ARG( 2, B
);
538 switch ( texUnit
->_CurrentCombine
->ModeA
) {
540 alpha_combine
= (R200_TXA_ARG_A_ZERO
|
541 R200_TXA_ARG_B_ZERO
|
543 R200_ALPHA_ARG( 0, C
);
546 alpha_combine
= (R200_TXA_ARG_C_ZERO
|
548 R200_ALPHA_ARG( 0, A
);
549 R200_ALPHA_ARG( 1, B
);
552 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
553 R200_TXA_COMP_ARG_B
|
555 R200_ALPHA_ARG( 0, A
);
556 R200_ALPHA_ARG( 1, C
);
559 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
560 R200_TXA_COMP_ARG_B
|
561 R200_TXA_BIAS_ARG_C
| /* new */
562 R200_TXA_OP_MADD
); /* was ADDSIGNED */
563 R200_ALPHA_ARG( 0, A
);
564 R200_ALPHA_ARG( 1, C
);
567 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
568 R200_TXA_COMP_ARG_B
|
571 R200_ALPHA_ARG( 0, A
);
572 R200_ALPHA_ARG( 1, C
);
575 alpha_combine
= (R200_TXA_OP_LERP
);
576 R200_ALPHA_ARG( 0, B
);
577 R200_ALPHA_ARG( 1, A
);
578 R200_ALPHA_ARG( 2, C
);
581 case GL_MODULATE_ADD_ATI
:
582 alpha_combine
= (R200_TXA_OP_MADD
);
583 R200_ALPHA_ARG( 0, A
);
584 R200_ALPHA_ARG( 1, C
);
585 R200_ALPHA_ARG( 2, B
);
587 case GL_MODULATE_SIGNED_ADD_ATI
:
588 alpha_combine
= (R200_TXA_BIAS_ARG_C
| /* new */
589 R200_TXA_OP_MADD
); /* was ADDSIGNED */
590 R200_ALPHA_ARG( 0, A
);
591 R200_ALPHA_ARG( 1, C
);
592 R200_ALPHA_ARG( 2, B
);
594 case GL_MODULATE_SUBTRACT_ATI
:
595 alpha_combine
= (R200_TXA_NEG_ARG_C
|
597 R200_ALPHA_ARG( 0, A
);
598 R200_ALPHA_ARG( 1, C
);
599 R200_ALPHA_ARG( 2, B
);
605 if ( (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
606 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ) {
607 alpha_scale
|= R200_TXA_DOT_ALPHA
;
612 * Apply the scale factor.
614 color_scale
|= (RGBshift
<< R200_TXC_SCALE_SHIFT
);
615 alpha_scale
|= (Ashift
<< R200_TXA_SCALE_SHIFT
);
621 if ( rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND
] != color_combine
||
622 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND
] != alpha_combine
||
623 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] != color_scale
||
624 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] != alpha_scale
) {
625 R200_STATECHANGE( rmesa
, pix
[slot
] );
626 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND
] = color_combine
;
627 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND
] = alpha_combine
;
628 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] = color_scale
;
629 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] = alpha_scale
;
635 void r200SetTexBuffer2(__DRIcontext
*pDRICtx
, GLint target
, GLint texture_format
,
636 __DRIdrawable
*dPriv
)
638 struct gl_texture_object
*texObj
;
639 struct gl_texture_image
*texImage
;
640 struct radeon_renderbuffer
*rb
;
641 radeon_texture_image
*rImage
;
642 radeonContextPtr radeon
;
643 struct radeon_framebuffer
*rfb
;
646 mesa_format texFormat
;
648 radeon
= pDRICtx
->driverPrivate
;
650 rfb
= dPriv
->driverPrivate
;
651 texObj
= _mesa_get_current_tex_object(&radeon
->glCtx
, target
);
652 texImage
= _mesa_get_tex_image(&radeon
->glCtx
, texObj
, target
, 0);
654 rImage
= get_radeon_texture_image(texImage
);
655 t
= radeon_tex_obj(texObj
);
660 radeon_update_renderbuffers(pDRICtx
, dPriv
, GL_TRUE
);
661 rb
= rfb
->color_rb
[0];
662 if (rb
->bo
== NULL
) {
663 /* Failed to BO for the buffer */
667 _mesa_lock_texture(&radeon
->glCtx
, texObj
);
669 radeon_bo_unref(t
->bo
);
673 radeon_bo_unref(rImage
->bo
);
677 radeon_miptree_unreference(&t
->mt
);
678 radeon_miptree_unreference(&rImage
->mt
);
681 radeon_bo_ref(rImage
->bo
);
683 radeon_bo_ref(t
->bo
);
685 t
->image_override
= GL_TRUE
;
686 t
->override_offset
= 0;
687 t
->pp_txpitch
&= (1 << 13) -1;
688 pitch_val
= rb
->pitch
;
691 if (texture_format
== __DRI_TEXTURE_FORMAT_RGB
) {
692 texFormat
= MESA_FORMAT_BGR_UNORM8
;
693 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_BGR_UNORM8
].format
;
696 texFormat
= MESA_FORMAT_B8G8R8A8_UNORM
;
697 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_B8G8R8A8_UNORM
].format
;
699 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_B8G8R8A8_UNORM
].filter
;
703 texFormat
= MESA_FORMAT_BGR_UNORM8
;
704 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_BGR_UNORM8
].format
;
705 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_BGR_UNORM8
].filter
;
708 texFormat
= MESA_FORMAT_B5G6R5_UNORM
;
709 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_B5G6R5_UNORM
].format
;
710 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_B5G6R5_UNORM
].filter
;
714 _mesa_init_teximage_fields(&radeon
->glCtx
, texImage
,
715 rb
->base
.Base
.Width
, rb
->base
.Base
.Height
,
718 rImage
->base
.RowStride
= rb
->pitch
/ rb
->cpp
;
721 t
->pp_txsize
= ((rb
->base
.Base
.Width
- 1) << RADEON_TEX_USIZE_SHIFT
)
722 | ((rb
->base
.Base
.Height
- 1) << RADEON_TEX_VSIZE_SHIFT
);
724 if (target
== GL_TEXTURE_RECTANGLE_NV
) {
725 t
->pp_txformat
|= R200_TXFORMAT_NON_POWER2
;
726 t
->pp_txpitch
= pitch_val
;
729 t
->pp_txformat
&= ~(R200_TXFORMAT_WIDTH_MASK
|
730 R200_TXFORMAT_HEIGHT_MASK
|
731 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
732 R200_TXFORMAT_F5_WIDTH_MASK
|
733 R200_TXFORMAT_F5_HEIGHT_MASK
);
734 t
->pp_txformat
|= ((texImage
->WidthLog2
<< R200_TXFORMAT_WIDTH_SHIFT
) |
735 (texImage
->HeightLog2
<< R200_TXFORMAT_HEIGHT_SHIFT
));
738 t
->validated
= GL_TRUE
;
739 _mesa_unlock_texture(&radeon
->glCtx
, texObj
);
744 void r200SetTexBuffer(__DRIcontext
*pDRICtx
, GLint target
, __DRIdrawable
*dPriv
)
746 r200SetTexBuffer2(pDRICtx
, target
, __DRI_TEXTURE_FORMAT_RGBA
, dPriv
);
753 static GLboolean
r200UpdateAllTexEnv( struct gl_context
*ctx
)
755 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
756 GLint i
, j
, currslot
;
757 GLint maxunitused
= -1;
758 GLboolean texregfree
[6] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
759 GLubyte stageref
[7] = {0, 0, 0, 0, 0, 0, 0};
760 GLint nextunit
[R200_MAX_TEXTURE_UNITS
] = {0, 0, 0, 0, 0, 0};
761 GLint currentnext
= -1;
764 /* find highest used unit */
765 for ( j
= 0; j
< R200_MAX_TEXTURE_UNITS
; j
++) {
766 if (ctx
->Texture
.Unit
[j
]._Current
) {
770 stageref
[maxunitused
+ 1] = REF_COLOR
| REF_ALPHA
;
772 for ( j
= maxunitused
; j
>= 0; j
-- ) {
773 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[j
];
775 rmesa
->state
.texture
.unit
[j
].outputreg
= -1;
777 if (stageref
[j
+ 1]) {
779 /* use the lowest available reg. That gets us automatically reg0 for the last stage.
780 need this even for disabled units, as it may get referenced due to the replace
782 for ( i
= 0 ; i
< R200_MAX_TEXTURE_UNITS
; i
++ ) {
784 rmesa
->state
.texture
.unit
[j
].outputreg
= i
;
788 if (rmesa
->state
.texture
.unit
[j
].outputreg
== -1) {
789 /* no more free regs we can use. Need a fallback :-( */
793 nextunit
[j
] = currentnext
;
795 if (!texUnit
->_Current
) {
796 /* the not enabled stages are referenced "indirectly",
797 must not cut off the lower stages */
798 stageref
[j
] = REF_COLOR
| REF_ALPHA
;
803 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
804 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
805 const GLboolean isdot3rgba
= (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ||
806 (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
);
809 /* check if we need the color part, special case for dot3_rgba
810 as if only the alpha part is referenced later on it still is using the color part */
811 if ((stageref
[j
+ 1] & REF_COLOR
) || isdot3rgba
) {
812 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
813 const GLuint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
814 const GLuint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
];
817 /* op 0/1 are referencing color, op 2/3 alpha */
818 stageref
[j
] |= (op
>> 1) + 1;
821 texregfree
[j
] = GL_FALSE
;
829 texregfree
[srcRGBi
- GL_TEXTURE0
] = GL_FALSE
;
831 default: /* don't care about other sources here */
837 /* alpha args are ignored for dot3_rgba */
838 if ((stageref
[j
+ 1] & REF_ALPHA
) && !isdot3rgba
) {
840 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
841 const GLuint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
844 stageref
[j
] |= REF_ALPHA
;
847 texregfree
[j
] = GL_FALSE
;
855 texregfree
[srcAi
- GL_TEXTURE0
] = GL_FALSE
;
857 default: /* don't care about other sources here */
865 /* don't enable texture sampling for units if the result is not used */
866 for (i
= 0; i
< R200_MAX_TEXTURE_UNITS
; i
++) {
867 if (ctx
->Texture
.Unit
[i
]._Current
&& !texregfree
[i
])
868 rmesa
->state
.texture
.unit
[i
].unitneeded
= 1 << _mesa_tex_target_to_index(ctx
, ctx
->Texture
.Unit
[i
]._Current
->Target
);
869 else rmesa
->state
.texture
.unit
[i
].unitneeded
= 0;
874 rmesa
->state
.envneeded
= 1;
877 while ((i
<= maxunitused
) && (i
>= 0)) {
878 /* only output instruction if the results are referenced */
879 if (ctx
->Texture
.Unit
[i
]._Current
&& stageref
[i
+1]) {
880 GLuint replaceunit
= i
;
881 /* try to optimize GL_REPLACE away (only one level deep though) */
882 if ( (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ModeRGB
== GL_REPLACE
) &&
883 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ModeA
== GL_REPLACE
) &&
884 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ScaleShiftRGB
== 0) &&
885 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ScaleShiftA
== 0) &&
886 (nextunit
[i
] > 0) ) {
887 /* yippie! can optimize it away! */
892 /* need env instruction slot */
893 rmesa
->state
.envneeded
|= 1 << currslot
;
894 ok
= r200UpdateTextureEnv( ctx
, i
, currslot
, replaceunit
);
895 if (!ok
) return GL_FALSE
;
902 /* need one stage at least */
903 rmesa
->state
.texture
.unit
[0].outputreg
= 0;
904 ok
= r200UpdateTextureEnv( ctx
, 0, 0, 0 );
907 R200_STATECHANGE( rmesa
, ctx
);
908 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~(R200_TEX_BLEND_ENABLE_MASK
| R200_MULTI_PASS_ENABLE
);
909 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= rmesa
->state
.envneeded
<< R200_TEX_BLEND_0_ENABLE_SHIFT
;
918 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
919 R200_MIN_FILTER_MASK | \
920 R200_MAG_FILTER_MASK | \
921 R200_MAX_ANISO_MASK | \
923 R200_YUV_TEMPERATURE_MASK | \
924 R200_CLAMP_S_MASK | \
925 R200_CLAMP_T_MASK | \
926 R200_BORDER_MODE_D3D )
928 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
929 R200_TXFORMAT_HEIGHT_MASK | \
930 R200_TXFORMAT_FORMAT_MASK | \
931 R200_TXFORMAT_F5_WIDTH_MASK | \
932 R200_TXFORMAT_F5_HEIGHT_MASK | \
933 R200_TXFORMAT_ALPHA_IN_MAP | \
934 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
935 R200_TXFORMAT_NON_POWER2)
937 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
938 R200_TEXCOORD_MASK | \
939 R200_MIN_MIP_LEVEL_MASK | \
940 R200_CLAMP_Q_MASK | \
941 R200_VOLUME_FILTER_MASK)
944 static void disable_tex_obj_state( r200ContextPtr rmesa
,
948 R200_STATECHANGE( rmesa
, vtx
);
949 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
951 R200_STATECHANGE( rmesa
, ctx
);
952 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~(R200_TEX_0_ENABLE
<< unit
);
953 if (rmesa
->radeon
.TclFallback
& (R200_TCL_FALLBACK_TEXGEN_0
<<unit
)) {
954 TCL_FALLBACK( &rmesa
->radeon
.glCtx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), GL_FALSE
);
957 /* Actually want to keep all units less than max active texture
958 * enabled, right? Fix this for >2 texunits.
962 GLuint tmp
= rmesa
->TexGenEnabled
;
964 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
965 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
966 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
967 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
969 if (tmp
!= rmesa
->TexGenEnabled
) {
970 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
971 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE_MATRIX
;
975 static void import_tex_obj_state( r200ContextPtr rmesa
,
977 radeonTexObjPtr texobj
)
979 /* do not use RADEON_DB_STATE to avoid stale texture caches */
980 GLuint
*cmd
= &rmesa
->hw
.tex
[unit
].cmd
[TEX_CMD_0
];
982 R200_STATECHANGE( rmesa
, tex
[unit
] );
984 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
985 cmd
[TEX_PP_TXFILTER
] |= texobj
->pp_txfilter
& TEXOBJ_TXFILTER_MASK
;
986 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
987 cmd
[TEX_PP_TXFORMAT
] |= texobj
->pp_txformat
& TEXOBJ_TXFORMAT_MASK
;
988 cmd
[TEX_PP_TXFORMAT_X
] &= ~TEXOBJ_TXFORMAT_X_MASK
;
989 cmd
[TEX_PP_TXFORMAT_X
] |= texobj
->pp_txformat_x
& TEXOBJ_TXFORMAT_X_MASK
;
990 cmd
[TEX_PP_TXSIZE
] = texobj
->pp_txsize
; /* NPOT only! */
991 cmd
[TEX_PP_TXPITCH
] = texobj
->pp_txpitch
; /* NPOT only! */
992 cmd
[TEX_PP_BORDER_COLOR
] = texobj
->pp_border_color
;
994 if (texobj
->base
.Target
== GL_TEXTURE_CUBE_MAP
) {
995 GLuint
*cube_cmd
= &rmesa
->hw
.cube
[unit
].cmd
[CUBE_CMD_0
];
997 R200_STATECHANGE( rmesa
, cube
[unit
] );
998 cube_cmd
[CUBE_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
999 /* that value is submitted twice. could change cube atom
1000 to not include that command when new drm is used */
1001 cmd
[TEX_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
1006 static void set_texgen_matrix( r200ContextPtr rmesa
,
1008 const GLfloat
*s_plane
,
1009 const GLfloat
*t_plane
,
1010 const GLfloat
*r_plane
,
1011 const GLfloat
*q_plane
)
1035 _math_matrix_loadf( &(rmesa
->TexGenMatrix
[unit
]), m
);
1036 _math_matrix_analyse( &(rmesa
->TexGenMatrix
[unit
]) );
1037 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<<unit
;
1041 static GLuint
r200_need_dis_texgen(const GLbitfield texGenEnabled
,
1042 const GLfloat
*planeS
,
1043 const GLfloat
*planeT
,
1044 const GLfloat
*planeR
,
1045 const GLfloat
*planeQ
)
1047 GLuint needtgenable
= 0;
1049 if (!(texGenEnabled
& S_BIT
)) {
1050 if (((texGenEnabled
& T_BIT
) && planeT
[0] != 0.0) ||
1051 ((texGenEnabled
& R_BIT
) && planeR
[0] != 0.0) ||
1052 ((texGenEnabled
& Q_BIT
) && planeQ
[0] != 0.0)) {
1053 needtgenable
|= S_BIT
;
1056 if (!(texGenEnabled
& T_BIT
)) {
1057 if (((texGenEnabled
& S_BIT
) && planeS
[1] != 0.0) ||
1058 ((texGenEnabled
& R_BIT
) && planeR
[1] != 0.0) ||
1059 ((texGenEnabled
& Q_BIT
) && planeQ
[1] != 0.0)) {
1060 needtgenable
|= T_BIT
;
1063 if (!(texGenEnabled
& R_BIT
)) {
1064 if (((texGenEnabled
& S_BIT
) && planeS
[2] != 0.0) ||
1065 ((texGenEnabled
& T_BIT
) && planeT
[2] != 0.0) ||
1066 ((texGenEnabled
& Q_BIT
) && planeQ
[2] != 0.0)) {
1067 needtgenable
|= R_BIT
;
1070 if (!(texGenEnabled
& Q_BIT
)) {
1071 if (((texGenEnabled
& S_BIT
) && planeS
[3] != 0.0) ||
1072 ((texGenEnabled
& T_BIT
) && planeT
[3] != 0.0) ||
1073 ((texGenEnabled
& R_BIT
) && planeR
[3] != 0.0)) {
1074 needtgenable
|= Q_BIT
;
1078 return needtgenable
;
1083 * Returns GL_FALSE if fallback required.
1085 static GLboolean
r200_validate_texgen( struct gl_context
*ctx
, GLuint unit
)
1087 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1088 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1089 GLuint inputshift
= R200_TEXGEN_0_INPUT_SHIFT
+ unit
*4;
1092 GLboolean mixed_fallback
= GL_FALSE
;
1093 static const GLfloat I
[16] = {
1098 static const GLfloat reflect
[16] = {
1104 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1105 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
1106 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
1107 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
1108 tgi
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] & ~(R200_TEXGEN_INPUT_MASK
<<
1110 tgcm
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] & ~(R200_TEXGEN_COMP_MASK
<<
1114 fprintf(stderr
, "%s unit %d\n", __func__
, unit
);
1116 if (texUnit
->TexGenEnabled
& S_BIT
) {
1117 mode
= texUnit
->GenS
.Mode
;
1119 tgcm
|= R200_TEXGEN_COMP_S
<< (unit
* 4);
1122 if (texUnit
->TexGenEnabled
& T_BIT
) {
1123 if (texUnit
->GenT
.Mode
!= mode
)
1124 mixed_fallback
= GL_TRUE
;
1126 tgcm
|= R200_TEXGEN_COMP_T
<< (unit
* 4);
1128 if (texUnit
->TexGenEnabled
& R_BIT
) {
1129 if (texUnit
->GenR
.Mode
!= mode
)
1130 mixed_fallback
= GL_TRUE
;
1132 tgcm
|= R200_TEXGEN_COMP_R
<< (unit
* 4);
1135 if (texUnit
->TexGenEnabled
& Q_BIT
) {
1136 if (texUnit
->GenQ
.Mode
!= mode
)
1137 mixed_fallback
= GL_TRUE
;
1139 tgcm
|= R200_TEXGEN_COMP_Q
<< (unit
* 4);
1142 if (mixed_fallback
) {
1143 if (R200_DEBUG
& RADEON_FALLBACKS
)
1144 fprintf(stderr
, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
1145 texUnit
->TexGenEnabled
, texUnit
->GenS
.Mode
, texUnit
->GenT
.Mode
,
1146 texUnit
->GenR
.Mode
, texUnit
->GenQ
.Mode
);
1150 /* we CANNOT do mixed mode if the texgen mode requires a plane where the input
1151 is not enabled for texgen, since the planes are concatenated into texmat,
1152 and thus the input will come from texcoord rather than tex gen equation!
1153 Either fallback or just hope that those texcoords aren't really needed...
1154 Assuming the former will cause lots of unnecessary fallbacks, the latter will
1155 generate bogus results sometimes - it's pretty much impossible to really know
1156 when a fallback is needed, depends on texmat and what sort of texture is bound
1157 etc, - for now fallback if we're missing either S or T bits, there's a high
1158 probability we need the texcoords in that case.
1159 That's a lot of work for some obscure texgen mixed mode fixup - why oh why
1160 doesn't the chip just directly accept the plane parameters :-(. */
1162 case GL_OBJECT_LINEAR
: {
1163 GLuint needtgenable
= r200_need_dis_texgen( texUnit
->TexGenEnabled
,
1164 texUnit
->GenS
.ObjectPlane
,
1165 texUnit
->GenT
.ObjectPlane
,
1166 texUnit
->GenR
.ObjectPlane
,
1167 texUnit
->GenQ
.ObjectPlane
);
1168 if (needtgenable
& (S_BIT
| T_BIT
)) {
1169 if (R200_DEBUG
& RADEON_FALLBACKS
)
1170 fprintf(stderr
, "fallback mixed texgen / obj plane, 0x%x\n",
1171 texUnit
->TexGenEnabled
);
1174 if (needtgenable
& (R_BIT
)) {
1175 tgcm
&= ~(R200_TEXGEN_COMP_R
<< (unit
* 4));
1177 if (needtgenable
& (Q_BIT
)) {
1178 tgcm
&= ~(R200_TEXGEN_COMP_Q
<< (unit
* 4));
1181 tgi
|= R200_TEXGEN_INPUT_OBJ
<< inputshift
;
1182 set_texgen_matrix( rmesa
, unit
,
1183 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->GenS
.ObjectPlane
: I
,
1184 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->GenT
.ObjectPlane
: I
+ 4,
1185 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->GenR
.ObjectPlane
: I
+ 8,
1186 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->GenQ
.ObjectPlane
: I
+ 12);
1190 case GL_EYE_LINEAR
: {
1191 GLuint needtgenable
= r200_need_dis_texgen( texUnit
->TexGenEnabled
,
1192 texUnit
->GenS
.EyePlane
,
1193 texUnit
->GenT
.EyePlane
,
1194 texUnit
->GenR
.EyePlane
,
1195 texUnit
->GenQ
.EyePlane
);
1196 if (needtgenable
& (S_BIT
| T_BIT
)) {
1197 if (R200_DEBUG
& RADEON_FALLBACKS
)
1198 fprintf(stderr
, "fallback mixed texgen / eye plane, 0x%x\n",
1199 texUnit
->TexGenEnabled
);
1202 if (needtgenable
& (R_BIT
)) {
1203 tgcm
&= ~(R200_TEXGEN_COMP_R
<< (unit
* 4));
1205 if (needtgenable
& (Q_BIT
)) {
1206 tgcm
&= ~(R200_TEXGEN_COMP_Q
<< (unit
* 4));
1208 tgi
|= R200_TEXGEN_INPUT_EYE
<< inputshift
;
1209 set_texgen_matrix( rmesa
, unit
,
1210 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->GenS
.EyePlane
: I
,
1211 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->GenT
.EyePlane
: I
+ 4,
1212 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->GenR
.EyePlane
: I
+ 8,
1213 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->GenQ
.EyePlane
: I
+ 12);
1217 case GL_REFLECTION_MAP_NV
:
1218 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1219 tgi
|= R200_TEXGEN_INPUT_EYE_REFLECT
<< inputshift
;
1220 /* pretty weird, must only negate when lighting is enabled? */
1221 if (ctx
->Light
.Enabled
)
1222 set_texgen_matrix( rmesa
, unit
,
1223 (texUnit
->TexGenEnabled
& S_BIT
) ? reflect
: I
,
1224 (texUnit
->TexGenEnabled
& T_BIT
) ? reflect
+ 4 : I
+ 4,
1225 (texUnit
->TexGenEnabled
& R_BIT
) ? reflect
+ 8 : I
+ 8,
1229 case GL_NORMAL_MAP_NV
:
1230 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1231 tgi
|= R200_TEXGEN_INPUT_EYE_NORMAL
<<inputshift
;
1235 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1236 tgi
|= R200_TEXGEN_INPUT_SPHERE
<<inputshift
;
1240 /* All texgen units were disabled, so just pass coords through. */
1241 tgi
|= unit
<< inputshift
;
1245 /* Unsupported mode, fallback:
1247 if (R200_DEBUG
& RADEON_FALLBACKS
)
1248 fprintf(stderr
, "fallback unsupported texgen, %d\n",
1249 texUnit
->GenS
.Mode
);
1253 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
1254 rmesa
->TexGenCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
1256 if (tgi
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] ||
1257 tgcm
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
])
1259 R200_STATECHANGE(rmesa
, tcg
);
1260 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] = tgi
;
1261 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] = tgcm
;
1267 void set_re_cntl_d3d( struct gl_context
*ctx
, int unit
, GLboolean use_d3d
)
1269 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1273 re_cntl
= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] & ~(R200_VTX_STQ0_D3D
<< (2 * unit
));
1275 re_cntl
|= R200_VTX_STQ0_D3D
<< (2 * unit
);
1277 if ( re_cntl
!= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] ) {
1278 R200_STATECHANGE( rmesa
, set
);
1279 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] = re_cntl
;
1284 * Compute the cached hardware register values for the given texture object.
1286 * \param rmesa Context pointer
1287 * \param t the r300 texture object
1289 static void setup_hardware_state(r200ContextPtr rmesa
, radeonTexObj
*t
)
1291 const struct gl_texture_image
*firstImage
= t
->base
.Image
[0][t
->minLod
];
1292 GLint log2Width
, log2Height
, log2Depth
, texelBytes
;
1293 uint extra_size
= 0;
1299 log2Width
= firstImage
->WidthLog2
;
1300 log2Height
= firstImage
->HeightLog2
;
1301 log2Depth
= firstImage
->DepthLog2
;
1302 texelBytes
= _mesa_get_format_bytes(firstImage
->TexFormat
);
1304 radeon_print(RADEON_TEXTURE
, RADEON_TRACE
,
1305 "%s(%p, tex %p) log2(w %d, h %d, d %d), texelBytes %d. format %d\n",
1306 __func__
, rmesa
, t
, log2Width
, log2Height
,
1307 log2Depth
, texelBytes
, firstImage
->TexFormat
);
1309 if (!t
->image_override
) {
1310 if (VALID_FORMAT(firstImage
->TexFormat
)) {
1311 const struct tx_table
*table
= _mesa_little_endian() ? tx_table_le
:
1314 t
->pp_txformat
&= ~(R200_TXFORMAT_FORMAT_MASK
|
1315 R200_TXFORMAT_ALPHA_IN_MAP
);
1316 t
->pp_txfilter
&= ~R200_YUV_TO_RGB
;
1318 t
->pp_txformat
|= table
[ firstImage
->TexFormat
].format
;
1319 t
->pp_txfilter
|= table
[ firstImage
->TexFormat
].filter
;
1323 _mesa_problem(NULL
, "unexpected texture format in %s",
1329 t
->pp_txfilter
&= ~R200_MAX_MIP_LEVEL_MASK
;
1330 t
->pp_txfilter
|= ((t
->maxLod
) << R200_MAX_MIP_LEVEL_SHIFT
)
1331 & R200_MAX_MIP_LEVEL_MASK
;
1333 if ( t
->pp_txfilter
&
1334 (R200_MIN_FILTER_NEAREST_MIP_NEAREST
1335 | R200_MIN_FILTER_NEAREST_MIP_LINEAR
1336 | R200_MIN_FILTER_LINEAR_MIP_NEAREST
1337 | R200_MIN_FILTER_LINEAR_MIP_LINEAR
1338 | R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
1339 | R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR
))
1340 extra_size
= t
->minLod
;
1342 t
->pp_txformat
&= ~(R200_TXFORMAT_WIDTH_MASK
|
1343 R200_TXFORMAT_HEIGHT_MASK
|
1344 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
1345 R200_TXFORMAT_F5_WIDTH_MASK
|
1346 R200_TXFORMAT_F5_HEIGHT_MASK
);
1347 t
->pp_txformat
|= (((log2Width
+ extra_size
) << R200_TXFORMAT_WIDTH_SHIFT
) |
1348 ((log2Height
+ extra_size
)<< R200_TXFORMAT_HEIGHT_SHIFT
));
1352 t
->pp_txformat_x
&= ~(R200_DEPTH_LOG2_MASK
| R200_TEXCOORD_MASK
1353 | R200_MIN_MIP_LEVEL_MASK
);
1355 t
->pp_txformat_x
|= (t
->minLod
<< R200_MIN_MIP_LEVEL_SHIFT
)
1356 & R200_MIN_MIP_LEVEL_MASK
;
1358 if (t
->base
.Target
== GL_TEXTURE_3D
) {
1359 t
->pp_txformat_x
|= (log2Depth
<< R200_DEPTH_LOG2_SHIFT
);
1360 t
->pp_txformat_x
|= R200_TEXCOORD_VOLUME
;
1363 else if (t
->base
.Target
== GL_TEXTURE_CUBE_MAP
) {
1364 assert(log2Width
== log2Height
);
1365 t
->pp_txformat
|= ((log2Width
<< R200_TXFORMAT_F5_WIDTH_SHIFT
) |
1366 (log2Height
<< R200_TXFORMAT_F5_HEIGHT_SHIFT
) |
1367 /* don't think we need this bit, if it exists at all - fglrx does not set it */
1368 (R200_TXFORMAT_CUBIC_MAP_ENABLE
));
1369 t
->pp_txformat_x
|= R200_TEXCOORD_CUBIC_ENV
;
1370 t
->pp_cubic_faces
= ((log2Width
<< R200_FACE_WIDTH_1_SHIFT
) |
1371 (log2Height
<< R200_FACE_HEIGHT_1_SHIFT
) |
1372 (log2Width
<< R200_FACE_WIDTH_2_SHIFT
) |
1373 (log2Height
<< R200_FACE_HEIGHT_2_SHIFT
) |
1374 (log2Width
<< R200_FACE_WIDTH_3_SHIFT
) |
1375 (log2Height
<< R200_FACE_HEIGHT_3_SHIFT
) |
1376 (log2Width
<< R200_FACE_WIDTH_4_SHIFT
) |
1377 (log2Height
<< R200_FACE_HEIGHT_4_SHIFT
));
1380 /* If we don't in fact send enough texture coordinates, q will be 1,
1381 * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
1383 t
->pp_txformat_x
|= R200_TEXCOORD_PROJ
;
1385 /* FIXME: NPOT sizes, is it correct really? */
1386 t
->pp_txsize
= (((firstImage
->Width
- 1) << R200_PP_TX_WIDTHMASK_SHIFT
)
1387 | ((firstImage
->Height
- 1) << R200_PP_TX_HEIGHTMASK_SHIFT
));
1389 if ( !t
->image_override
) {
1390 if (_mesa_is_format_compressed(firstImage
->TexFormat
))
1391 t
->pp_txpitch
= (firstImage
->Width
+ 63) & ~(63);
1393 t
->pp_txpitch
= ((firstImage
->Width
* texelBytes
) + 63) & ~(63);
1394 t
->pp_txpitch
-= 32;
1397 if (t
->base
.Target
== GL_TEXTURE_RECTANGLE_NV
) {
1398 t
->pp_txformat
|= R200_TXFORMAT_NON_POWER2
;
1403 static GLboolean
r200_validate_texture(struct gl_context
*ctx
, struct gl_texture_object
*texObj
, int unit
)
1405 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1406 radeonTexObj
*t
= radeon_tex_obj(texObj
);
1408 if (!radeon_validate_texture_miptree(ctx
, _mesa_get_samplerobj(ctx
, unit
), texObj
))
1411 r200_validate_texgen(ctx
, unit
);
1412 /* Configure the hardware registers (more precisely, the cached version
1413 * of the hardware registers). */
1414 setup_hardware_state(rmesa
, t
);
1416 if (texObj
->Target
== GL_TEXTURE_RECTANGLE_NV
||
1417 texObj
->Target
== GL_TEXTURE_2D
||
1418 texObj
->Target
== GL_TEXTURE_1D
)
1419 set_re_cntl_d3d( ctx
, unit
, GL_FALSE
);
1421 set_re_cntl_d3d( ctx
, unit
, GL_TRUE
);
1422 R200_STATECHANGE( rmesa
, ctx
);
1423 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_0_ENABLE
<< unit
;
1425 R200_STATECHANGE( rmesa
, vtx
);
1426 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
1427 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] |= 4 << (unit
* 3);
1429 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1430 r200TexUpdateParameters(ctx
, unit
);
1431 import_tex_obj_state( rmesa
, unit
, t
);
1433 if (rmesa
->recheck_texgen
[unit
]) {
1434 GLboolean fallback
= !r200_validate_texgen( ctx
, unit
);
1435 TCL_FALLBACK( ctx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), fallback
);
1436 rmesa
->recheck_texgen
[unit
] = 0;
1437 rmesa
->radeon
.NewGLState
|= _NEW_TEXTURE_MATRIX
;
1440 t
->validated
= GL_TRUE
;
1442 FALLBACK( rmesa
, RADEON_FALLBACK_BORDER_MODE
, t
->border_fallback
);
1444 return !t
->border_fallback
;
1447 static GLboolean
r200UpdateTextureUnit(struct gl_context
*ctx
, int unit
)
1449 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1450 GLuint unitneeded
= rmesa
->state
.texture
.unit
[unit
].unitneeded
;
1453 /* disable the unit */
1454 disable_tex_obj_state(rmesa
, unit
);
1458 if (!r200_validate_texture(ctx
, ctx
->Texture
.Unit
[unit
]._Current
, unit
)) {
1460 "failed to validate texture for unit %d.\n",
1462 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
1466 rmesa
->state
.texture
.unit
[unit
].texobj
= radeon_tex_obj(ctx
->Texture
.Unit
[unit
]._Current
);
1471 void r200UpdateTextureState( struct gl_context
*ctx
)
1473 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1477 /* NOTE: must not manipulate rmesa->state.texture.unit[].unitneeded or
1478 rmesa->state.envneeded before a R200_STATECHANGE (or R200_NEWPRIM) since
1479 we use these to determine if we want to emit the corresponding state
1481 R200_NEWPRIM( rmesa
);
1483 if (ctx
->ATIFragmentShader
._Enabled
) {
1485 for (i
= 0; i
< R200_MAX_TEXTURE_UNITS
; i
++) {
1486 if (ctx
->Texture
.Unit
[i
]._Current
)
1487 rmesa
->state
.texture
.unit
[i
].unitneeded
= 1 << _mesa_tex_target_to_index(ctx
, ctx
->Texture
.Unit
[i
]._Current
->Target
);
1489 rmesa
->state
.texture
.unit
[i
].unitneeded
= 0;
1494 ok
= r200UpdateAllTexEnv( ctx
);
1497 ok
= (r200UpdateTextureUnit( ctx
, 0 ) &&
1498 r200UpdateTextureUnit( ctx
, 1 ) &&
1499 r200UpdateTextureUnit( ctx
, 2 ) &&
1500 r200UpdateTextureUnit( ctx
, 3 ) &&
1501 r200UpdateTextureUnit( ctx
, 4 ) &&
1502 r200UpdateTextureUnit( ctx
, 5 ));
1505 if (ok
&& ctx
->ATIFragmentShader
._Enabled
) {
1506 r200UpdateFragmentShader(ctx
);
1509 FALLBACK( rmesa
, R200_FALLBACK_TEXTURE
, !ok
);
1511 if (rmesa
->radeon
.TclFallback
)
1512 r200ChooseVertexState( ctx
);
1515 if (rmesa
->radeon
.radeonScreen
->chip_family
== CHIP_FAMILY_R200
) {
1518 * T0 hang workaround -------------
1519 * not needed for r200 derivatives
1521 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_ENABLE_MASK
) == R200_TEX_0_ENABLE
&&
1522 (rmesa
->hw
.tex
[0].cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) > R200_MIN_FILTER_LINEAR
) {
1524 R200_STATECHANGE(rmesa
, ctx
);
1525 R200_STATECHANGE(rmesa
, tex
[1]);
1526 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_1_ENABLE
;
1527 if (!(rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] & R200_PPX_TEX_1_ENABLE
))
1528 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1529 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] |= R200_TXFORMAT_LOOKUP_DISABLE
;
1531 else if (!ctx
->ATIFragmentShader
._Enabled
) {
1532 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
) &&
1533 (rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] & R200_TXFORMAT_LOOKUP_DISABLE
)) {
1534 R200_STATECHANGE(rmesa
, tex
[1]);
1535 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~R200_TXFORMAT_LOOKUP_DISABLE
;
1538 /* do the same workaround for the first pass of a fragment shader.
1539 * completely unknown if necessary / sufficient.
1541 if ((rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] & R200_PPX_TEX_ENABLE_MASK
) == R200_PPX_TEX_0_ENABLE
&&
1542 (rmesa
->hw
.tex
[0].cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) > R200_MIN_FILTER_LINEAR
) {
1544 R200_STATECHANGE(rmesa
, cst
);
1545 R200_STATECHANGE(rmesa
, tex
[1]);
1546 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] |= R200_PPX_TEX_1_ENABLE
;
1547 if (!(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
))
1548 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1549 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXMULTI_CTL
] |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE
;
1552 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1553 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1554 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1555 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1556 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1557 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1558 R200_MIN_FILTER_LINEAR)) {
1559 R200_STATECHANGE(rmesa, ctx);
1560 R200_STATECHANGE(rmesa, tex[i+1]);
1561 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1562 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1563 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1566 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1567 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1568 R200_STATECHANGE(rmesa, tex[i+1]);
1569 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1575 * Texture cache LRU hang workaround -------------
1576 * not needed for r200 derivatives
1577 * hopefully this covers first pass of a shader as well
1580 /* While the cases below attempt to only enable the workaround in the
1581 * specific cases necessary, they were insufficient. See bugzilla #1519,
1582 * #729, #814. Tests with quake3 showed no impact on performance.
1587 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) &&
1588 ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1590 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1591 ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1593 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1594 ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1600 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) &&
1601 ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1603 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1604 ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1606 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1607 ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1613 if (dbg
!= rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
]) {
1614 R200_STATECHANGE( rmesa
, tam
);
1615 rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
] = dbg
;
1616 if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg
);