1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c,v 1.6 2002/12/16 16:18:59 dawes Exp $ */
2 /**************************************************************************
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5 VA Linux Systems Inc., Fremont, California.
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
33 * Kevin E. Martin <martin@valinux.com>
34 * Gareth Hughes <gareth@valinux.com>
42 #include "texformat.h"
45 #include "radeon_context.h"
46 #include "radeon_state.h"
47 #include "radeon_ioctl.h"
48 #include "radeon_swtcl.h"
49 #include "radeon_tex.h"
50 #include "radeon_tcl.h"
53 #define RADEON_TXFORMAT_A8 RADEON_TXFORMAT_I8
54 #define RADEON_TXFORMAT_L8 RADEON_TXFORMAT_I8
55 #define RADEON_TXFORMAT_AL88 RADEON_TXFORMAT_AI88
56 #define RADEON_TXFORMAT_YCBCR RADEON_TXFORMAT_YVYU422
57 #define RADEON_TXFORMAT_YCBCR_REV RADEON_TXFORMAT_VYUY422
58 #define RADEON_TXFORMAT_RGB_DXT1 RADEON_TXFORMAT_DXT1
59 #define RADEON_TXFORMAT_RGBA_DXT1 RADEON_TXFORMAT_DXT1
60 #define RADEON_TXFORMAT_RGBA_DXT3 RADEON_TXFORMAT_DXT23
61 #define RADEON_TXFORMAT_RGBA_DXT5 RADEON_TXFORMAT_DXT45
64 [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, 0 }
65 #define _COLOR_REV(f) \
66 [ MESA_FORMAT_ ## f ## _REV ] = { RADEON_TXFORMAT_ ## f, 0 }
68 [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f | RADEON_TXFORMAT_ALPHA_IN_MAP, 0 }
69 #define _ALPHA_REV(f) \
70 [ MESA_FORMAT_ ## f ## _REV ] = { RADEON_TXFORMAT_ ## f | RADEON_TXFORMAT_ALPHA_IN_MAP, 0 }
72 [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, RADEON_YUV_TO_RGB }
74 [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
75 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
76 && (tx_table[f].format != 0xffffffff) )
79 GLuint format
, filter
;
115 * This function computes the number of bytes of storage needed for
116 * the given texture object (all mipmap levels, all cube faces).
117 * The \c image[face][level].x/y/width/height parameters for upload/blitting
118 * are computed here. \c pp_txfilter, \c pp_txformat, etc. will be set here
121 * \param rmesa Context pointer
122 * \param tObj GL texture object whose images are to be posted to
125 static void radeonSetTexImages( radeonContextPtr rmesa
,
126 struct gl_texture_object
*tObj
)
128 radeonTexObjPtr t
= (radeonTexObjPtr
)tObj
->DriverData
;
129 const struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
133 GLint log2Width
, log2Height
, log2Depth
;
135 /* Set the hardware texture format
138 t
->pp_txformat
&= ~(RADEON_TXFORMAT_FORMAT_MASK
|
139 RADEON_TXFORMAT_ALPHA_IN_MAP
);
140 t
->pp_txfilter
&= ~RADEON_YUV_TO_RGB
;
142 if ( VALID_FORMAT( baseImage
->TexFormat
->MesaFormat
) ) {
143 t
->pp_txformat
|= tx_table
[ baseImage
->TexFormat
->MesaFormat
].format
;
144 t
->pp_txfilter
|= tx_table
[ baseImage
->TexFormat
->MesaFormat
].filter
;
147 _mesa_problem(NULL
, "unexpected texture format in %s", __FUNCTION__
);
152 /* Compute which mipmap levels we really want to send to the hardware.
155 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
156 log2Width
= tObj
->Image
[0][t
->base
.firstLevel
]->WidthLog2
;
157 log2Height
= tObj
->Image
[0][t
->base
.firstLevel
]->HeightLog2
;
158 log2Depth
= tObj
->Image
[0][t
->base
.firstLevel
]->DepthLog2
;
160 numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
162 assert(numLevels
<= RADEON_MAX_TEXTURE_LEVELS
);
164 /* Calculate mipmap offsets and dimensions for blitting (uploading)
165 * The idea is that we lay out the mipmap levels within a block of
166 * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
170 for (i
= 0; i
< numLevels
; i
++) {
171 const struct gl_texture_image
*texImage
;
174 texImage
= tObj
->Image
[0][i
+ t
->base
.firstLevel
];
178 /* find image size in bytes */
179 if (texImage
->IsCompressed
) {
180 /* need to calculate the size AFTER padding even though the texture is
181 submitted without padding.
182 Only handle pot textures currently - don't know if npot is even possible,
183 size calculation would certainly need (trivial) adjustments.
184 Align (and later pad) to 32byte, not sure what that 64byte blit width is
186 if ((t
->pp_txformat
& RADEON_TXFORMAT_FORMAT_MASK
) == RADEON_TXFORMAT_DXT1
) {
187 /* RGB_DXT1/RGBA_DXT1, 8 bytes per block */
188 if ((texImage
->Width
+ 3) < 8) /* width one block */
189 size
= texImage
->CompressedSize
* 4;
190 else if ((texImage
->Width
+ 3) < 16)
191 size
= texImage
->CompressedSize
* 2;
192 else size
= texImage
->CompressedSize
;
194 else /* DXT3/5, 16 bytes per block */
195 if ((texImage
->Width
+ 3) < 8)
196 size
= texImage
->CompressedSize
* 2;
197 else size
= texImage
->CompressedSize
;
199 else if (tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
) {
200 size
= ((texImage
->Width
* texImage
->TexFormat
->TexelBytes
+ 63)
201 & ~63) * texImage
->Height
;
204 int w
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
207 size
= w
* texImage
->Height
* texImage
->Depth
;
212 /* Align to 32-byte offset. It is faster to do this unconditionally
213 * (no branch penalty).
216 curOffset
= (curOffset
+ 0x1f) & ~0x1f;
218 t
->image
[0][i
].x
= curOffset
% BLIT_WIDTH_BYTES
;
219 t
->image
[0][i
].y
= curOffset
/ BLIT_WIDTH_BYTES
;
220 t
->image
[0][i
].width
= MIN2(size
, BLIT_WIDTH_BYTES
);
221 t
->image
[0][i
].height
= size
/ t
->image
[0][i
].width
;
224 /* for debugging only and only applicable to non-rectangle targets */
225 assert(size
% t
->image
[0][i
].width
== 0);
226 assert(t
->image
[0][i
].x
== 0
227 || (size
< BLIT_WIDTH_BYTES
&& t
->image
[0][i
].height
== 1));
232 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
233 i
, texImage
->Width
, texImage
->Height
,
234 t
->image
[0][i
].x
, t
->image
[0][i
].y
,
235 t
->image
[0][i
].width
, t
->image
[0][i
].height
, size
, curOffset
);
241 /* Align the total size of texture memory block.
243 t
->base
.totalSize
= (curOffset
+ RADEON_OFFSET_MASK
) & ~RADEON_OFFSET_MASK
;
247 t
->pp_txfilter
&= ~RADEON_MAX_MIP_LEVEL_MASK
;
248 t
->pp_txfilter
|= (numLevels
- 1) << RADEON_MAX_MIP_LEVEL_SHIFT
;
250 t
->pp_txformat
&= ~(RADEON_TXFORMAT_WIDTH_MASK
|
251 RADEON_TXFORMAT_HEIGHT_MASK
|
252 RADEON_TXFORMAT_CUBIC_MAP_ENABLE
);
253 t
->pp_txformat
|= ((log2Width
<< RADEON_TXFORMAT_WIDTH_SHIFT
) |
254 (log2Height
<< RADEON_TXFORMAT_HEIGHT_SHIFT
));
256 t
->pp_txsize
= (((tObj
->Image
[0][t
->base
.firstLevel
]->Width
- 1) << 0) |
257 ((tObj
->Image
[0][t
->base
.firstLevel
]->Height
- 1) << 16));
259 /* Only need to round to nearest 32 for textures, but the blitter
260 * requires 64-byte aligned pitches, and we may/may not need the
261 * blitter. NPOT only!
263 if (baseImage
->IsCompressed
)
264 t
->pp_txpitch
= (tObj
->Image
[0][t
->base
.firstLevel
]->Width
+ 63) & ~(63);
266 t
->pp_txpitch
= ((tObj
->Image
[0][t
->base
.firstLevel
]->Width
* baseImage
->TexFormat
->TexelBytes
) + 63) & ~(63);
269 t
->dirty_state
= TEX_ALL
;
271 /* FYI: radeonUploadTexImages( rmesa, t ); used to be called here */
276 /* ================================================================
277 * Texture combine functions
280 /* GL_ARB_texture_env_combine support
283 /* The color tables have combine functions for GL_SRC_COLOR,
284 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
286 static GLuint radeon_texture_color
[][RADEON_MAX_TEXTURE_UNITS
] =
289 RADEON_COLOR_ARG_A_T0_COLOR
,
290 RADEON_COLOR_ARG_A_T1_COLOR
,
291 RADEON_COLOR_ARG_A_T2_COLOR
294 RADEON_COLOR_ARG_A_T0_COLOR
| RADEON_COMP_ARG_A
,
295 RADEON_COLOR_ARG_A_T1_COLOR
| RADEON_COMP_ARG_A
,
296 RADEON_COLOR_ARG_A_T2_COLOR
| RADEON_COMP_ARG_A
299 RADEON_COLOR_ARG_A_T0_ALPHA
,
300 RADEON_COLOR_ARG_A_T1_ALPHA
,
301 RADEON_COLOR_ARG_A_T2_ALPHA
304 RADEON_COLOR_ARG_A_T0_ALPHA
| RADEON_COMP_ARG_A
,
305 RADEON_COLOR_ARG_A_T1_ALPHA
| RADEON_COMP_ARG_A
,
306 RADEON_COLOR_ARG_A_T2_ALPHA
| RADEON_COMP_ARG_A
310 static GLuint radeon_tfactor_color
[] =
312 RADEON_COLOR_ARG_A_TFACTOR_COLOR
,
313 RADEON_COLOR_ARG_A_TFACTOR_COLOR
| RADEON_COMP_ARG_A
,
314 RADEON_COLOR_ARG_A_TFACTOR_ALPHA
,
315 RADEON_COLOR_ARG_A_TFACTOR_ALPHA
| RADEON_COMP_ARG_A
318 static GLuint radeon_primary_color
[] =
320 RADEON_COLOR_ARG_A_DIFFUSE_COLOR
,
321 RADEON_COLOR_ARG_A_DIFFUSE_COLOR
| RADEON_COMP_ARG_A
,
322 RADEON_COLOR_ARG_A_DIFFUSE_ALPHA
,
323 RADEON_COLOR_ARG_A_DIFFUSE_ALPHA
| RADEON_COMP_ARG_A
326 static GLuint radeon_previous_color
[] =
328 RADEON_COLOR_ARG_A_CURRENT_COLOR
,
329 RADEON_COLOR_ARG_A_CURRENT_COLOR
| RADEON_COMP_ARG_A
,
330 RADEON_COLOR_ARG_A_CURRENT_ALPHA
,
331 RADEON_COLOR_ARG_A_CURRENT_ALPHA
| RADEON_COMP_ARG_A
334 /* GL_ZERO table - indices 0-3
335 * GL_ONE table - indices 1-4
337 static GLuint radeon_zero_color
[] =
339 RADEON_COLOR_ARG_A_ZERO
,
340 RADEON_COLOR_ARG_A_ZERO
| RADEON_COMP_ARG_A
,
341 RADEON_COLOR_ARG_A_ZERO
,
342 RADEON_COLOR_ARG_A_ZERO
| RADEON_COMP_ARG_A
,
343 RADEON_COLOR_ARG_A_ZERO
347 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
349 static GLuint radeon_texture_alpha
[][RADEON_MAX_TEXTURE_UNITS
] =
352 RADEON_ALPHA_ARG_A_T0_ALPHA
,
353 RADEON_ALPHA_ARG_A_T1_ALPHA
,
354 RADEON_ALPHA_ARG_A_T2_ALPHA
357 RADEON_ALPHA_ARG_A_T0_ALPHA
| RADEON_COMP_ARG_A
,
358 RADEON_ALPHA_ARG_A_T1_ALPHA
| RADEON_COMP_ARG_A
,
359 RADEON_ALPHA_ARG_A_T2_ALPHA
| RADEON_COMP_ARG_A
363 static GLuint radeon_tfactor_alpha
[] =
365 RADEON_ALPHA_ARG_A_TFACTOR_ALPHA
,
366 RADEON_ALPHA_ARG_A_TFACTOR_ALPHA
| RADEON_COMP_ARG_A
369 static GLuint radeon_primary_alpha
[] =
371 RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA
,
372 RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA
| RADEON_COMP_ARG_A
375 static GLuint radeon_previous_alpha
[] =
377 RADEON_ALPHA_ARG_A_CURRENT_ALPHA
,
378 RADEON_ALPHA_ARG_A_CURRENT_ALPHA
| RADEON_COMP_ARG_A
381 /* GL_ZERO table - indices 0-1
382 * GL_ONE table - indices 1-2
384 static GLuint radeon_zero_alpha
[] =
386 RADEON_ALPHA_ARG_A_ZERO
,
387 RADEON_ALPHA_ARG_A_ZERO
| RADEON_COMP_ARG_A
,
388 RADEON_ALPHA_ARG_A_ZERO
392 /* Extract the arg from slot A, shift it into the correct argument slot
393 * and set the corresponding complement bit.
395 #define RADEON_COLOR_ARG( n, arg ) \
398 ((color_arg[n] & RADEON_COLOR_ARG_MASK) \
399 << RADEON_COLOR_ARG_##arg##_SHIFT); \
401 ((color_arg[n] >> RADEON_COMP_ARG_SHIFT) \
402 << RADEON_COMP_ARG_##arg##_SHIFT); \
405 #define RADEON_ALPHA_ARG( n, arg ) \
408 ((alpha_arg[n] & RADEON_ALPHA_ARG_MASK) \
409 << RADEON_ALPHA_ARG_##arg##_SHIFT); \
411 ((alpha_arg[n] >> RADEON_COMP_ARG_SHIFT) \
412 << RADEON_COMP_ARG_##arg##_SHIFT); \
416 /* ================================================================
417 * Texture unit state management
420 static GLboolean
radeonUpdateTextureEnv( GLcontext
*ctx
, int unit
)
422 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
423 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
424 GLuint color_combine
, alpha_combine
;
425 const GLuint color_combine0
= RADEON_COLOR_ARG_A_ZERO
| RADEON_COLOR_ARG_B_ZERO
426 | RADEON_COLOR_ARG_C_CURRENT_COLOR
| RADEON_BLEND_CTL_ADD
427 | RADEON_SCALE_1X
| RADEON_CLAMP_TX
;
428 const GLuint alpha_combine0
= RADEON_ALPHA_ARG_A_ZERO
| RADEON_ALPHA_ARG_B_ZERO
429 | RADEON_ALPHA_ARG_C_CURRENT_ALPHA
| RADEON_BLEND_CTL_ADD
430 | RADEON_SCALE_1X
| RADEON_CLAMP_TX
;
433 /* texUnit->_Current can be NULL if and only if the texture unit is
434 * not actually enabled.
436 assert( (texUnit
->_ReallyEnabled
== 0)
437 || (texUnit
->_Current
!= NULL
) );
439 if ( RADEON_DEBUG
& DEBUG_TEXTURE
) {
440 fprintf( stderr
, "%s( %p, %d )\n", __FUNCTION__
, (void *)ctx
, unit
);
443 /* Set the texture environment state. Isn't this nice and clean?
444 * The chip will automagically set the texture alpha to 0xff when
445 * the texture format does not include an alpha component. This
446 * reduces the amount of special-casing we have to do, alpha-only
447 * textures being a notable exception.
449 /* Don't cache these results.
451 rmesa
->state
.texture
.unit
[unit
].format
= 0;
452 rmesa
->state
.texture
.unit
[unit
].envMode
= 0;
454 if ( !texUnit
->_ReallyEnabled
) {
455 color_combine
= color_combine0
;
456 alpha_combine
= alpha_combine0
;
459 GLuint color_arg
[3], alpha_arg
[3];
461 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
462 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
463 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
464 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
468 * Extract the color and alpha combine function arguments.
470 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
471 const GLint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
] - GL_SRC_COLOR
;
472 const GLuint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
477 color_arg
[i
] = radeon_texture_color
[op
][unit
];
480 color_arg
[i
] = radeon_tfactor_color
[op
];
482 case GL_PRIMARY_COLOR
:
483 color_arg
[i
] = radeon_primary_color
[op
];
486 color_arg
[i
] = radeon_previous_color
[op
];
489 color_arg
[i
] = radeon_zero_color
[op
];
492 color_arg
[i
] = radeon_zero_color
[op
+1];
497 /* implement ogl 1.4/1.5 core spec here, not specification of
498 * GL_ARB_texture_env_crossbar (which would require disabling blending
499 * instead of undefined results when referencing not enabled texunit) */
500 color_arg
[i
] = radeon_texture_color
[op
][srcRGBi
- GL_TEXTURE0
];
507 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
508 const GLint op
= texUnit
->_CurrentCombine
->OperandA
[i
] - GL_SRC_ALPHA
;
509 const GLuint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
514 alpha_arg
[i
] = radeon_texture_alpha
[op
][unit
];
517 alpha_arg
[i
] = radeon_tfactor_alpha
[op
];
519 case GL_PRIMARY_COLOR
:
520 alpha_arg
[i
] = radeon_primary_alpha
[op
];
523 alpha_arg
[i
] = radeon_previous_alpha
[op
];
526 alpha_arg
[i
] = radeon_zero_alpha
[op
];
529 alpha_arg
[i
] = radeon_zero_alpha
[op
+1];
534 alpha_arg
[i
] = radeon_texture_alpha
[op
][srcAi
- GL_TEXTURE0
];
542 * Build up the color and alpha combine functions.
544 switch ( texUnit
->_CurrentCombine
->ModeRGB
) {
546 color_combine
= (RADEON_COLOR_ARG_A_ZERO
|
547 RADEON_COLOR_ARG_B_ZERO
|
548 RADEON_BLEND_CTL_ADD
|
550 RADEON_COLOR_ARG( 0, C
);
553 color_combine
= (RADEON_COLOR_ARG_C_ZERO
|
554 RADEON_BLEND_CTL_ADD
|
556 RADEON_COLOR_ARG( 0, A
);
557 RADEON_COLOR_ARG( 1, B
);
560 color_combine
= (RADEON_COLOR_ARG_B_ZERO
|
562 RADEON_BLEND_CTL_ADD
|
564 RADEON_COLOR_ARG( 0, A
);
565 RADEON_COLOR_ARG( 1, C
);
568 color_combine
= (RADEON_COLOR_ARG_B_ZERO
|
570 RADEON_BLEND_CTL_ADDSIGNED
|
572 RADEON_COLOR_ARG( 0, A
);
573 RADEON_COLOR_ARG( 1, C
);
576 color_combine
= (RADEON_COLOR_ARG_B_ZERO
|
578 RADEON_BLEND_CTL_SUBTRACT
|
580 RADEON_COLOR_ARG( 0, A
);
581 RADEON_COLOR_ARG( 1, C
);
584 color_combine
= (RADEON_BLEND_CTL_BLEND
|
586 RADEON_COLOR_ARG( 0, B
);
587 RADEON_COLOR_ARG( 1, A
);
588 RADEON_COLOR_ARG( 2, C
);
591 case GL_DOT3_RGB_EXT
:
592 case GL_DOT3_RGBA_EXT
:
593 /* The EXT version of the DOT3 extension does not support the
594 * scale factor, but the ARB version (and the version in OpenGL
602 /* The R100 / RV200 only support a 1X multiplier in hardware
605 if ( RGBshift
!= (RADEON_SCALE_1X
>> RADEON_SCALE_SHIFT
) ) {
610 if ( (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
611 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ) {
612 /* is it necessary to set this or will it be ignored anyway? */
616 color_combine
= (RADEON_COLOR_ARG_C_ZERO
|
617 RADEON_BLEND_CTL_DOT3
|
619 RADEON_COLOR_ARG( 0, A
);
620 RADEON_COLOR_ARG( 1, B
);
623 case GL_MODULATE_ADD_ATI
:
624 color_combine
= (RADEON_BLEND_CTL_ADD
|
626 RADEON_COLOR_ARG( 0, A
);
627 RADEON_COLOR_ARG( 1, C
);
628 RADEON_COLOR_ARG( 2, B
);
630 case GL_MODULATE_SIGNED_ADD_ATI
:
631 color_combine
= (RADEON_BLEND_CTL_ADDSIGNED
|
633 RADEON_COLOR_ARG( 0, A
);
634 RADEON_COLOR_ARG( 1, C
);
635 RADEON_COLOR_ARG( 2, B
);
637 case GL_MODULATE_SUBTRACT_ATI
:
638 color_combine
= (RADEON_BLEND_CTL_SUBTRACT
|
640 RADEON_COLOR_ARG( 0, A
);
641 RADEON_COLOR_ARG( 1, C
);
642 RADEON_COLOR_ARG( 2, B
);
648 switch ( texUnit
->_CurrentCombine
->ModeA
) {
650 alpha_combine
= (RADEON_ALPHA_ARG_A_ZERO
|
651 RADEON_ALPHA_ARG_B_ZERO
|
652 RADEON_BLEND_CTL_ADD
|
654 RADEON_ALPHA_ARG( 0, C
);
657 alpha_combine
= (RADEON_ALPHA_ARG_C_ZERO
|
658 RADEON_BLEND_CTL_ADD
|
660 RADEON_ALPHA_ARG( 0, A
);
661 RADEON_ALPHA_ARG( 1, B
);
664 alpha_combine
= (RADEON_ALPHA_ARG_B_ZERO
|
666 RADEON_BLEND_CTL_ADD
|
668 RADEON_ALPHA_ARG( 0, A
);
669 RADEON_ALPHA_ARG( 1, C
);
672 alpha_combine
= (RADEON_ALPHA_ARG_B_ZERO
|
674 RADEON_BLEND_CTL_ADDSIGNED
|
676 RADEON_ALPHA_ARG( 0, A
);
677 RADEON_ALPHA_ARG( 1, C
);
680 alpha_combine
= (RADEON_COLOR_ARG_B_ZERO
|
682 RADEON_BLEND_CTL_SUBTRACT
|
684 RADEON_ALPHA_ARG( 0, A
);
685 RADEON_ALPHA_ARG( 1, C
);
688 alpha_combine
= (RADEON_BLEND_CTL_BLEND
|
690 RADEON_ALPHA_ARG( 0, B
);
691 RADEON_ALPHA_ARG( 1, A
);
692 RADEON_ALPHA_ARG( 2, C
);
695 case GL_MODULATE_ADD_ATI
:
696 alpha_combine
= (RADEON_BLEND_CTL_ADD
|
698 RADEON_ALPHA_ARG( 0, A
);
699 RADEON_ALPHA_ARG( 1, C
);
700 RADEON_ALPHA_ARG( 2, B
);
702 case GL_MODULATE_SIGNED_ADD_ATI
:
703 alpha_combine
= (RADEON_BLEND_CTL_ADDSIGNED
|
705 RADEON_ALPHA_ARG( 0, A
);
706 RADEON_ALPHA_ARG( 1, C
);
707 RADEON_ALPHA_ARG( 2, B
);
709 case GL_MODULATE_SUBTRACT_ATI
:
710 alpha_combine
= (RADEON_BLEND_CTL_SUBTRACT
|
712 RADEON_ALPHA_ARG( 0, A
);
713 RADEON_ALPHA_ARG( 1, C
);
714 RADEON_ALPHA_ARG( 2, B
);
720 if ( (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGB_EXT
)
721 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGB
) ) {
722 alpha_combine
|= RADEON_DOT_ALPHA_DONT_REPLICATE
;
726 * Apply the scale factor.
728 color_combine
|= (RGBshift
<< RADEON_SCALE_SHIFT
);
729 alpha_combine
|= (Ashift
<< RADEON_SCALE_SHIFT
);
735 if ( rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXCBLEND
] != color_combine
||
736 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXABLEND
] != alpha_combine
) {
737 RADEON_STATECHANGE( rmesa
, tex
[unit
] );
738 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXCBLEND
] = color_combine
;
739 rmesa
->hw
.tex
[unit
].cmd
[TEX_PP_TXABLEND
] = alpha_combine
;
745 #define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK | \
746 RADEON_MIN_FILTER_MASK | \
747 RADEON_MAG_FILTER_MASK | \
748 RADEON_MAX_ANISO_MASK | \
749 RADEON_YUV_TO_RGB | \
750 RADEON_YUV_TEMPERATURE_MASK | \
751 RADEON_CLAMP_S_MASK | \
752 RADEON_CLAMP_T_MASK | \
753 RADEON_BORDER_MODE_D3D )
755 #define TEXOBJ_TXFORMAT_MASK (RADEON_TXFORMAT_WIDTH_MASK | \
756 RADEON_TXFORMAT_HEIGHT_MASK | \
757 RADEON_TXFORMAT_FORMAT_MASK | \
758 RADEON_TXFORMAT_F5_WIDTH_MASK | \
759 RADEON_TXFORMAT_F5_HEIGHT_MASK | \
760 RADEON_TXFORMAT_ALPHA_IN_MAP | \
761 RADEON_TXFORMAT_CUBIC_MAP_ENABLE | \
762 RADEON_TXFORMAT_NON_POWER2)
765 static void import_tex_obj_state( radeonContextPtr rmesa
,
767 radeonTexObjPtr texobj
)
769 GLuint
*cmd
= RADEON_DB_STATE( tex
[unit
] );
771 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
772 cmd
[TEX_PP_TXFILTER
] |= texobj
->pp_txfilter
& TEXOBJ_TXFILTER_MASK
;
773 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
774 cmd
[TEX_PP_TXFORMAT
] |= texobj
->pp_txformat
& TEXOBJ_TXFORMAT_MASK
;
775 cmd
[TEX_PP_TXOFFSET
] = texobj
->pp_txoffset
;
776 cmd
[TEX_PP_BORDER_COLOR
] = texobj
->pp_border_color
;
777 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tex
[unit
] );
779 if (texobj
->base
.tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
) {
780 GLuint
*txr_cmd
= RADEON_DB_STATE( txr
[unit
] );
781 txr_cmd
[TXR_PP_TEX_SIZE
] = texobj
->pp_txsize
; /* NPOT only! */
782 txr_cmd
[TXR_PP_TEX_PITCH
] = texobj
->pp_txpitch
; /* NPOT only! */
783 RADEON_DB_STATECHANGE( rmesa
, &rmesa
->hw
.txr
[unit
] );
786 texobj
->dirty_state
&= ~(1<<unit
);
792 static void set_texgen_matrix( radeonContextPtr rmesa
,
794 const GLfloat
*s_plane
,
795 const GLfloat
*t_plane
)
797 static const GLfloat scale_identity
[4] = { 1,1,1,1 };
799 if (!TEST_EQ_4V( s_plane
, scale_identity
) ||
800 !TEST_EQ_4V( t_plane
, scale_identity
)) {
801 rmesa
->TexGenEnabled
|= RADEON_TEXMAT_0_ENABLE
<<unit
;
802 rmesa
->TexGenMatrix
[unit
].m
[0] = s_plane
[0];
803 rmesa
->TexGenMatrix
[unit
].m
[4] = s_plane
[1];
804 rmesa
->TexGenMatrix
[unit
].m
[8] = s_plane
[2];
805 rmesa
->TexGenMatrix
[unit
].m
[12] = s_plane
[3];
807 rmesa
->TexGenMatrix
[unit
].m
[1] = t_plane
[0];
808 rmesa
->TexGenMatrix
[unit
].m
[5] = t_plane
[1];
809 rmesa
->TexGenMatrix
[unit
].m
[9] = t_plane
[2];
810 rmesa
->TexGenMatrix
[unit
].m
[13] = t_plane
[3];
811 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
815 /* Ignoring the Q texcoord for now.
817 * Returns GL_FALSE if fallback required.
819 static GLboolean
radeon_validate_texgen( GLcontext
*ctx
, GLuint unit
)
821 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
822 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
823 GLuint inputshift
= RADEON_TEXGEN_0_INPUT_SHIFT
+ unit
*4;
824 GLuint tmp
= rmesa
->TexGenEnabled
;
826 rmesa
->TexGenEnabled
&= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
827 rmesa
->TexGenEnabled
&= ~(RADEON_TEXMAT_0_ENABLE
<<unit
);
828 rmesa
->TexGenEnabled
&= ~(RADEON_TEXGEN_INPUT_MASK
<<inputshift
);
829 rmesa
->TexGenNeedNormals
[unit
] = 0;
831 if ((texUnit
->TexGenEnabled
& (S_BIT
|T_BIT
)) == 0) {
832 /* Disabled, no fallback:
834 rmesa
->TexGenEnabled
|=
835 (RADEON_TEXGEN_INPUT_TEXCOORD_0
+unit
) << inputshift
;
838 else if (texUnit
->TexGenEnabled
& Q_BIT
) {
839 /* Very easy to do this, in fact would remove a fallback case
840 * elsewhere, but I haven't done it yet... Fallback:
842 fprintf(stderr
, "fallback Q_BIT\n");
845 else if ((texUnit
->TexGenEnabled
& (S_BIT
|T_BIT
)) != (S_BIT
|T_BIT
) ||
846 texUnit
->GenModeS
!= texUnit
->GenModeT
) {
847 /* Mixed modes, fallback:
849 /* fprintf(stderr, "fallback mixed texgen\n"); */
853 rmesa
->TexGenEnabled
|= RADEON_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
855 switch (texUnit
->GenModeS
) {
856 case GL_OBJECT_LINEAR
:
857 rmesa
->TexGenEnabled
|= RADEON_TEXGEN_INPUT_OBJ
<< inputshift
;
858 set_texgen_matrix( rmesa
, unit
,
859 texUnit
->ObjectPlaneS
,
860 texUnit
->ObjectPlaneT
);
864 rmesa
->TexGenEnabled
|= RADEON_TEXGEN_INPUT_EYE
<< inputshift
;
865 set_texgen_matrix( rmesa
, unit
,
870 case GL_REFLECTION_MAP_NV
:
871 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
872 rmesa
->TexGenEnabled
|= RADEON_TEXGEN_INPUT_EYE_REFLECT
<<inputshift
;
875 case GL_NORMAL_MAP_NV
:
876 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
877 rmesa
->TexGenEnabled
|= RADEON_TEXGEN_INPUT_EYE_NORMAL
<<inputshift
;
882 /* Unsupported mode, fallback:
884 /* fprintf(stderr, "fallback unsupported texgen\n"); */
888 if (tmp
!= rmesa
->TexGenEnabled
) {
889 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
896 static void disable_tex( GLcontext
*ctx
, int unit
)
898 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
900 if (rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (RADEON_TEX_0_ENABLE
<<unit
)) {
901 /* Texture unit disabled */
902 if ( rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
903 /* The old texture is no longer bound to this texture unit.
907 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&= ~(1UL << unit
);
908 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
911 RADEON_STATECHANGE( rmesa
, ctx
);
912 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &=
913 ~((RADEON_TEX_0_ENABLE
| RADEON_TEX_BLEND_0_ENABLE
) << unit
);
915 RADEON_STATECHANGE( rmesa
, tcl
);
918 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] &= ~(RADEON_TCL_VTX_ST0
|
922 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] &= ~(RADEON_TCL_VTX_ST1
|
930 if (rmesa
->TclFallback
& (RADEON_TCL_FALLBACK_TEXGEN_0
<<unit
)) {
931 TCL_FALLBACK( ctx
, (RADEON_TCL_FALLBACK_TEXGEN_0
<<unit
), GL_FALSE
);
932 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
938 GLuint inputshift
= RADEON_TEXGEN_0_INPUT_SHIFT
+ unit
*4;
939 GLuint tmp
= rmesa
->TexGenEnabled
;
941 rmesa
->TexGenEnabled
&= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
942 rmesa
->TexGenEnabled
&= ~(RADEON_TEXMAT_0_ENABLE
<<unit
);
943 rmesa
->TexGenEnabled
&= ~(RADEON_TEXGEN_INPUT_MASK
<<inputshift
);
944 rmesa
->TexGenNeedNormals
[unit
] = 0;
945 rmesa
->TexGenEnabled
|=
946 (RADEON_TEXGEN_INPUT_TEXCOORD_0
+unit
) << inputshift
;
948 if (tmp
!= rmesa
->TexGenEnabled
) {
949 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
950 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
956 static GLboolean
enable_tex_2d( GLcontext
*ctx
, int unit
)
958 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
959 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
960 struct gl_texture_object
*tObj
= texUnit
->_Current
;
961 radeonTexObjPtr t
= (radeonTexObjPtr
) tObj
->DriverData
;
963 /* Need to load the 2d images associated with this unit.
965 if (t
->pp_txformat
& RADEON_TXFORMAT_NON_POWER2
) {
966 t
->pp_txformat
&= ~RADEON_TXFORMAT_NON_POWER2
;
967 t
->base
.dirty_images
[0] = ~0;
970 ASSERT(tObj
->Target
== GL_TEXTURE_2D
|| tObj
->Target
== GL_TEXTURE_1D
);
972 if ( t
->base
.dirty_images
[0] ) {
973 RADEON_FIREVERTICES( rmesa
);
974 radeonSetTexImages( rmesa
, tObj
);
975 radeonUploadTexImages( rmesa
, (radeonTexObjPtr
) tObj
->DriverData
, 0 );
976 if ( !t
->base
.memBlock
)
983 static GLboolean
enable_tex_rect( GLcontext
*ctx
, int unit
)
985 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
986 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
987 struct gl_texture_object
*tObj
= texUnit
->_Current
;
988 radeonTexObjPtr t
= (radeonTexObjPtr
) tObj
->DriverData
;
990 if (!(t
->pp_txformat
& RADEON_TXFORMAT_NON_POWER2
)) {
991 t
->pp_txformat
|= RADEON_TXFORMAT_NON_POWER2
;
992 t
->base
.dirty_images
[0] = ~0;
995 ASSERT(tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
997 if ( t
->base
.dirty_images
[0] ) {
998 RADEON_FIREVERTICES( rmesa
);
999 radeonSetTexImages( rmesa
, tObj
);
1000 radeonUploadTexImages( rmesa
, (radeonTexObjPtr
) tObj
->DriverData
, 0 );
1001 if ( !t
->base
.memBlock
/* && !rmesa->prefer_gart_client_texturing FIXME */ ) {
1002 fprintf(stderr
, "%s: upload failed\n", __FUNCTION__
);
1011 static GLboolean
update_tex_common( GLcontext
*ctx
, int unit
)
1013 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1014 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1015 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1016 radeonTexObjPtr t
= (radeonTexObjPtr
) tObj
->DriverData
;
1019 /* Fallback if there's a texture border */
1020 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 ) {
1021 fprintf(stderr
, "%s: border\n", __FUNCTION__
);
1025 /* Update state if this is a different texture object to last
1028 if ( rmesa
->state
.texture
.unit
[unit
].texobj
!= t
) {
1029 if ( rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
1030 /* The old texture is no longer bound to this texture unit.
1034 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&=
1038 rmesa
->state
.texture
.unit
[unit
].texobj
= t
;
1039 t
->base
.bound
|= (1UL << unit
);
1040 t
->dirty_state
|= 1<<unit
;
1041 driUpdateTextureLRU( (driTextureObject
*) t
); /* XXX: should be locked! */
1047 if ( !(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (RADEON_TEX_0_ENABLE
<<unit
))) {
1048 RADEON_STATECHANGE( rmesa
, ctx
);
1049 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |=
1050 (RADEON_TEX_0_ENABLE
| RADEON_TEX_BLEND_0_ENABLE
) << unit
;
1052 RADEON_STATECHANGE( rmesa
, tcl
);
1055 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_ST0
;
1057 rmesa
->hw
.tcl
.cmd
[TCL_OUTPUT_VTXFMT
] |= RADEON_TCL_VTX_ST1
;
1059 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1062 if (t
->dirty_state
& (1<<unit
)) {
1063 import_tex_obj_state( rmesa
, unit
, t
);
1066 if (rmesa
->recheck_texgen
[unit
]) {
1067 GLboolean fallback
= !radeon_validate_texgen( ctx
, unit
);
1068 TCL_FALLBACK( ctx
, (RADEON_TCL_FALLBACK_TEXGEN_0
<<unit
), fallback
);
1069 rmesa
->recheck_texgen
[unit
] = 0;
1070 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1073 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1074 if ( rmesa
->state
.texture
.unit
[unit
].format
!= format
||
1075 rmesa
->state
.texture
.unit
[unit
].envMode
!= texUnit
->EnvMode
) {
1076 rmesa
->state
.texture
.unit
[unit
].format
= format
;
1077 rmesa
->state
.texture
.unit
[unit
].envMode
= texUnit
->EnvMode
;
1078 if ( ! radeonUpdateTextureEnv( ctx
, unit
) ) {
1083 FALLBACK( rmesa
, RADEON_FALLBACK_BORDER_MODE
, t
->border_fallback
);
1084 return !t
->border_fallback
;
1089 static GLboolean
radeonUpdateTextureUnit( GLcontext
*ctx
, int unit
)
1091 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1093 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_TEXRECT_0
<< unit
, 0 );
1095 if ( texUnit
->_ReallyEnabled
& (TEXTURE_RECT_BIT
) ) {
1096 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_TEXRECT_0
<< unit
, 1 );
1098 return (enable_tex_rect( ctx
, unit
) &&
1099 update_tex_common( ctx
, unit
));
1101 else if ( texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
) ) {
1102 return (enable_tex_2d( ctx
, unit
) &&
1103 update_tex_common( ctx
, unit
));
1105 else if ( texUnit
->_ReallyEnabled
) {
1109 disable_tex( ctx
, unit
);
1114 void radeonUpdateTextureState( GLcontext
*ctx
)
1116 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1119 ok
= (radeonUpdateTextureUnit( ctx
, 0 ) &&
1120 radeonUpdateTextureUnit( ctx
, 1 ));
1122 FALLBACK( rmesa
, RADEON_FALLBACK_TEXTURE
, !ok
);
1124 if (rmesa
->TclFallback
)
1125 radeonChooseVertexState( ctx
);