1 /* $XFree86: xc/lib/GL/mesa/src/drv/r300/r300_texstate.c,v 1.3 2003/02/15 22:18:47 dawes Exp $ */
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
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 * Keith Whitwell <keith@tungstengraphics.com>
40 #include "texformat.h"
43 #include "r300_context.h"
44 #include "r300_state.h"
45 #include "radeon_ioctl.h"
46 //#include "r300_swtcl.h"
48 //#include "r300_tcl.h"
51 #define R200_TXFORMAT_A8 R200_TXFORMAT_I8
52 #define R200_TXFORMAT_L8 R200_TXFORMAT_I8
53 #define R200_TXFORMAT_AL88 R200_TXFORMAT_AI88
54 #define R200_TXFORMAT_YCBCR R200_TXFORMAT_YVYU422
55 #define R200_TXFORMAT_YCBCR_REV R200_TXFORMAT_VYUY422
58 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, 0 }
59 #define _COLOR_REV(f) \
60 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f, 0 }
62 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
63 #define _ALPHA_REV(f) \
64 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
66 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, R200_YUV_TO_RGB }
68 [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
69 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_YCBCR_REV) \
70 && (tx_table[f].format != 0xffffffff) )
73 GLuint format
, filter
;
90 _ALPHA(I8
), _INVALID(CI8
), _YUV(YCBCR
), _YUV(YCBCR_REV
),};
97 * This function computes the number of bytes of storage needed for
98 * the given texture object (all mipmap levels, all cube faces).
99 * The \c image[face][level].x/y/width/height parameters for upload/blitting
100 * are computed here. \c filter, \c format, etc. will be set here
103 * \param rmesa Context pointer
104 * \param tObj GL texture object whose images are to be posted to
107 static void r300SetTexImages(r300ContextPtr rmesa
,
108 struct gl_texture_object
*tObj
)
110 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
111 const struct gl_texture_image
*baseImage
=
112 tObj
->Image
[0][tObj
->BaseLevel
];
116 GLint log2Width
, log2Height
, log2Depth
;
118 /* Set the hardware texture format
121 t
->format
&= ~(R200_TXFORMAT_FORMAT_MASK
|
122 R200_TXFORMAT_ALPHA_IN_MAP
);
124 t
->filter
&= ~R200_YUV_TO_RGB
;
126 if (VALID_FORMAT(baseImage
->TexFormat
->MesaFormat
)) {
128 tx_table
[baseImage
->TexFormat
->MesaFormat
].format
;
131 tx_table
[baseImage
->TexFormat
->MesaFormat
].filter
;
134 _mesa_problem(NULL
, "unexpected texture format in %s",
139 /* Compute which mipmap levels we really want to send to the hardware.
142 driCalculateTextureFirstLastLevel((driTextureObject
*) t
);
143 log2Width
= tObj
->Image
[0][t
->base
.firstLevel
]->WidthLog2
;
144 log2Height
= tObj
->Image
[0][t
->base
.firstLevel
]->HeightLog2
;
145 log2Depth
= tObj
->Image
[0][t
->base
.firstLevel
]->DepthLog2
;
147 numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
149 assert(numLevels
<= RADEON_MAX_TEXTURE_LEVELS
);
151 /* Calculate mipmap offsets and dimensions for blitting (uploading)
152 * The idea is that we lay out the mipmap levels within a block of
153 * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
157 for (i
= 0; i
< numLevels
; i
++) {
158 const struct gl_texture_image
*texImage
;
161 texImage
= tObj
->Image
[0][i
+ t
->base
.firstLevel
];
165 /* find image size in bytes */
166 if (texImage
->IsCompressed
) {
167 size
= texImage
->CompressedSize
;
168 } else if (tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
) {
171 texImage
->TexFormat
->TexelBytes
+ 63)
172 & ~63) * texImage
->Height
;
175 texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
178 size
= w
* texImage
->Height
* texImage
->Depth
;
183 fprintf(stderr
, "w=%d h=%d d=%d tb=%d intFormat=%d\n", texImage
->Width
, texImage
->Height
,
184 texImage
->Depth
, texImage
->TexFormat
->TexelBytes
,
185 texImage
->IntFormat
);
187 /* Align to 32-byte offset. It is faster to do this unconditionally
188 * (no branch penalty).
191 curOffset
= (curOffset
+ 0x1f) & ~0x1f;
193 t
->image
[0][i
].x
= curOffset
% BLIT_WIDTH_BYTES
;
194 t
->image
[0][i
].y
= curOffset
/ BLIT_WIDTH_BYTES
;
195 t
->image
[0][i
].width
= MIN2(size
, BLIT_WIDTH_BYTES
);
196 t
->image
[0][i
].height
= size
/ t
->image
[0][i
].width
;
199 /* for debugging only and only applicable to non-rectangle targets */
200 assert(size
% t
->image
[0][i
].width
== 0);
201 assert(t
->image
[0][i
].x
== 0
202 || (size
< BLIT_WIDTH_BYTES
203 && t
->image
[0][i
].height
== 1));
208 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
209 i
, texImage
->Width
, texImage
->Height
,
210 t
->image
[0][i
].x
, t
->image
[0][i
].y
,
211 t
->image
[0][i
].width
, t
->image
[0][i
].height
,
218 /* Align the total size of texture memory block.
221 (curOffset
+ RADEON_OFFSET_MASK
) & ~RADEON_OFFSET_MASK
;
223 /* Setup remaining cube face blits, if needed */
224 if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
225 /* Round totalSize up to multiple of BLIT_WIDTH_BYTES */
226 const GLuint faceSize
=
227 (t
->base
.totalSize
+ BLIT_WIDTH_BYTES
- 1)
228 & ~(BLIT_WIDTH_BYTES
- 1);
229 const GLuint lines
= faceSize
/ BLIT_WIDTH_BYTES
;
231 /* reuse face 0 x/y/width/height - just adjust y */
232 for (face
= 1; face
< 6; face
++) {
233 for (i
= 0; i
< numLevels
; i
++) {
234 t
->image
[face
][i
].x
= t
->image
[0][i
].x
;
235 t
->image
[face
][i
].y
=
236 t
->image
[0][i
].y
+ face
* lines
;
237 t
->image
[face
][i
].width
= t
->image
[0][i
].width
;
238 t
->image
[face
][i
].height
=
239 t
->image
[0][i
].height
;
242 t
->base
.totalSize
= 6 * faceSize
; /* total texmem needed */
248 t
->filter
&= ~R200_MAX_MIP_LEVEL_MASK
;
249 t
->filter
|= (numLevels
- 1) << R200_MAX_MIP_LEVEL_SHIFT
;
251 t
->format
&= ~(R300_TX_FORMAT_WIDTH_MASK
|
252 R300_TX_FORMAT_HEIGHT_MASK
|
253 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
254 R200_TXFORMAT_F5_WIDTH_MASK
|
255 R200_TXFORMAT_F5_HEIGHT_MASK
);
256 t
->format
|= ((log2Width
<< R300_TX_FORMAT_WIDTH_SHIFT
) |
257 (log2Height
<< R300_TX_FORMAT_HEIGHT_SHIFT
));
259 t
->format_x
&= ~(R200_DEPTH_LOG2_MASK
| R200_TEXCOORD_MASK
);
260 if (tObj
->Target
== GL_TEXTURE_3D
) {
261 t
->format_x
|= (log2Depth
<< R200_DEPTH_LOG2_SHIFT
);
262 t
->format_x
|= R200_TEXCOORD_VOLUME
;
263 } else if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
264 ASSERT(log2Width
== log2height
);
265 t
->format
|= ((log2Width
<< R200_TXFORMAT_F5_WIDTH_SHIFT
) |
266 (log2Height
<< R200_TXFORMAT_F5_HEIGHT_SHIFT
)
267 | (R200_TXFORMAT_CUBIC_MAP_ENABLE
));
268 t
->format_x
|= R200_TEXCOORD_CUBIC_ENV
;
269 t
->pp_cubic_faces
= ((log2Width
<< R200_FACE_WIDTH_1_SHIFT
) |
270 (log2Height
<< R200_FACE_HEIGHT_1_SHIFT
) |
271 (log2Width
<< R200_FACE_WIDTH_2_SHIFT
) |
272 (log2Height
<< R200_FACE_HEIGHT_2_SHIFT
) |
273 (log2Width
<< R200_FACE_WIDTH_3_SHIFT
) |
274 (log2Height
<< R200_FACE_HEIGHT_3_SHIFT
) |
275 (log2Width
<< R200_FACE_WIDTH_4_SHIFT
) |
276 (log2Height
<< R200_FACE_HEIGHT_4_SHIFT
));
279 t
->size
= (((tObj
->Image
[0][t
->base
.firstLevel
]->Width
- 1) << R300_TX_WIDTHMASK_SHIFT
)
280 |((tObj
->Image
[0][t
->base
.firstLevel
]->Height
- 1) << R300_TX_HEIGHTMASK_SHIFT
)
281 |((log2Width
>log2Height
)?log2Width
:log2Height
)<<R300_TX_SIZE_SHIFT
);
283 /* Only need to round to nearest 32 for textures, but the blitter
284 * requires 64-byte aligned pitches, and we may/may not need the
285 * blitter. NPOT only!
287 if (baseImage
->IsCompressed
)
289 (tObj
->Image
[0][t
->base
.firstLevel
]->Width
+ 63) & ~(63);
292 ((tObj
->Image
[0][t
->base
.firstLevel
]->Width
*
293 baseImage
->TexFormat
->TexelBytes
) + 63) & ~(63);
296 t
->dirty_state
= TEX_ALL
;
298 /* FYI: r300UploadTexImages( rmesa, t ) used to be called here */
301 /* ================================================================
302 * Texture combine functions
305 /* GL_ARB_texture_env_combine support
308 /* The color tables have combine functions for GL_SRC_COLOR,
309 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
311 static GLuint r300_register_color
[][R200_MAX_TEXTURE_UNITS
] = {
313 R200_TXC_ARG_A_R0_COLOR
,
314 R200_TXC_ARG_A_R1_COLOR
,
315 R200_TXC_ARG_A_R2_COLOR
,
316 R200_TXC_ARG_A_R3_COLOR
,
317 R200_TXC_ARG_A_R4_COLOR
,
318 R200_TXC_ARG_A_R5_COLOR
},
320 R200_TXC_ARG_A_R0_COLOR
| R200_TXC_COMP_ARG_A
,
321 R200_TXC_ARG_A_R1_COLOR
| R200_TXC_COMP_ARG_A
,
322 R200_TXC_ARG_A_R2_COLOR
| R200_TXC_COMP_ARG_A
,
323 R200_TXC_ARG_A_R3_COLOR
| R200_TXC_COMP_ARG_A
,
324 R200_TXC_ARG_A_R4_COLOR
| R200_TXC_COMP_ARG_A
,
325 R200_TXC_ARG_A_R5_COLOR
| R200_TXC_COMP_ARG_A
},
327 R200_TXC_ARG_A_R0_ALPHA
,
328 R200_TXC_ARG_A_R1_ALPHA
,
329 R200_TXC_ARG_A_R2_ALPHA
,
330 R200_TXC_ARG_A_R3_ALPHA
,
331 R200_TXC_ARG_A_R4_ALPHA
,
332 R200_TXC_ARG_A_R5_ALPHA
},
334 R200_TXC_ARG_A_R0_ALPHA
| R200_TXC_COMP_ARG_A
,
335 R200_TXC_ARG_A_R1_ALPHA
| R200_TXC_COMP_ARG_A
,
336 R200_TXC_ARG_A_R2_ALPHA
| R200_TXC_COMP_ARG_A
,
337 R200_TXC_ARG_A_R3_ALPHA
| R200_TXC_COMP_ARG_A
,
338 R200_TXC_ARG_A_R4_ALPHA
| R200_TXC_COMP_ARG_A
,
339 R200_TXC_ARG_A_R5_ALPHA
| R200_TXC_COMP_ARG_A
},
342 static GLuint r300_tfactor_color
[] = {
343 R200_TXC_ARG_A_TFACTOR_COLOR
,
344 R200_TXC_ARG_A_TFACTOR_COLOR
| R200_TXC_COMP_ARG_A
,
345 R200_TXC_ARG_A_TFACTOR_ALPHA
,
346 R200_TXC_ARG_A_TFACTOR_ALPHA
| R200_TXC_COMP_ARG_A
349 static GLuint r300_primary_color
[] = {
350 R200_TXC_ARG_A_DIFFUSE_COLOR
,
351 R200_TXC_ARG_A_DIFFUSE_COLOR
| R200_TXC_COMP_ARG_A
,
352 R200_TXC_ARG_A_DIFFUSE_ALPHA
,
353 R200_TXC_ARG_A_DIFFUSE_ALPHA
| R200_TXC_COMP_ARG_A
356 /* GL_ZERO table - indices 0-3
357 * GL_ONE table - indices 1-4
359 static GLuint r300_zero_color
[] = {
361 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
363 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
367 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
369 static GLuint r300_register_alpha
[][R200_MAX_TEXTURE_UNITS
] = {
371 R200_TXA_ARG_A_R0_ALPHA
,
372 R200_TXA_ARG_A_R1_ALPHA
,
373 R200_TXA_ARG_A_R2_ALPHA
,
374 R200_TXA_ARG_A_R3_ALPHA
,
375 R200_TXA_ARG_A_R4_ALPHA
,
376 R200_TXA_ARG_A_R5_ALPHA
},
378 R200_TXA_ARG_A_R0_ALPHA
| R200_TXA_COMP_ARG_A
,
379 R200_TXA_ARG_A_R1_ALPHA
| R200_TXA_COMP_ARG_A
,
380 R200_TXA_ARG_A_R2_ALPHA
| R200_TXA_COMP_ARG_A
,
381 R200_TXA_ARG_A_R3_ALPHA
| R200_TXA_COMP_ARG_A
,
382 R200_TXA_ARG_A_R4_ALPHA
| R200_TXA_COMP_ARG_A
,
383 R200_TXA_ARG_A_R5_ALPHA
| R200_TXA_COMP_ARG_A
},
386 static GLuint r300_tfactor_alpha
[] = {
387 R200_TXA_ARG_A_TFACTOR_ALPHA
,
388 R200_TXA_ARG_A_TFACTOR_ALPHA
| R200_TXA_COMP_ARG_A
391 static GLuint r300_primary_alpha
[] = {
392 R200_TXA_ARG_A_DIFFUSE_ALPHA
,
393 R200_TXA_ARG_A_DIFFUSE_ALPHA
| R200_TXA_COMP_ARG_A
396 /* GL_ZERO table - indices 0-1
397 * GL_ONE table - indices 1-2
399 static GLuint r300_zero_alpha
[] = {
401 R200_TXA_ARG_A_ZERO
| R200_TXA_COMP_ARG_A
,
405 /* Extract the arg from slot A, shift it into the correct argument slot
406 * and set the corresponding complement bit.
408 #define R200_COLOR_ARG( n, arg ) \
411 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
412 << R200_TXC_ARG_##arg##_SHIFT); \
414 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
415 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
418 #define R200_ALPHA_ARG( n, arg ) \
421 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
422 << R200_TXA_ARG_##arg##_SHIFT); \
424 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
425 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
428 /* ================================================================
429 * Texture unit state management
432 static GLboolean
r300UpdateTextureEnv(GLcontext
* ctx
, int unit
)
434 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
435 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
436 GLuint color_combine
, alpha_combine
;
438 #if 0 /* disable for now.. */
439 GLuint color_scale
= rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] &
440 ~(R200_TXC_SCALE_MASK
);
441 GLuint alpha_scale
= rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] &
442 ~(R200_TXA_DOT_ALPHA
| R200_TXA_SCALE_MASK
);
444 /* texUnit->_Current can be NULL if and only if the texture unit is
445 * not actually enabled.
447 assert((texUnit
->_ReallyEnabled
== 0)
448 || (texUnit
->_Current
!= NULL
));
450 if (RADEON_DEBUG
& DEBUG_TEXTURE
) {
451 fprintf(stderr
, "%s( %p, %d )\n", __FUNCTION__
, (void *)ctx
,
455 /* Set the texture environment state. Isn't this nice and clean?
456 * The chip will automagically set the texture alpha to 0xff when
457 * the texture format does not include an alpha component. This
458 * reduces the amount of special-casing we have to do, alpha-only
459 * textures being a notable exception.
461 /* Don't cache these results.
463 rmesa
->state
.texture
.unit
[unit
].format
= 0;
464 rmesa
->state
.texture
.unit
[unit
].envMode
= 0;
466 if (!texUnit
->_ReallyEnabled
) {
469 R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
|
470 R200_TXC_ARG_C_DIFFUSE_COLOR
| R200_TXC_OP_MADD
;
472 R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
|
473 R200_TXA_ARG_C_DIFFUSE_ALPHA
| R200_TXA_OP_MADD
;
476 R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
|
477 R200_TXC_ARG_C_R0_COLOR
| R200_TXC_OP_MADD
;
479 R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
|
480 R200_TXA_ARG_C_R0_ALPHA
| R200_TXA_OP_MADD
;
483 GLuint color_arg
[3], alpha_arg
[3];
485 const GLuint numColorArgs
=
486 texUnit
->_CurrentCombine
->_NumArgsRGB
;
487 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
488 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
489 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
492 * Extract the color and alpha combine function arguments.
494 for (i
= 0; i
< numColorArgs
; i
++) {
496 texUnit
->_CurrentCombine
->OperandRGB
[i
] -
500 switch (texUnit
->_CurrentCombine
->SourceRGB
[i
]) {
502 color_arg
[i
] = r300_register_color
[op
][unit
];
505 color_arg
[i
] = r300_tfactor_color
[op
];
507 case GL_PRIMARY_COLOR
:
508 color_arg
[i
] = r300_primary_color
[op
];
512 color_arg
[i
] = r300_primary_color
[op
];
515 r300_register_color
[op
][0];
518 color_arg
[i
] = r300_zero_color
[op
];
521 color_arg
[i
] = r300_zero_color
[op
+ 1];
528 for (i
= 0; i
< numAlphaArgs
; i
++) {
530 texUnit
->_CurrentCombine
->OperandA
[i
] -
534 switch (texUnit
->_CurrentCombine
->SourceA
[i
]) {
536 alpha_arg
[i
] = r300_register_alpha
[op
][unit
];
539 alpha_arg
[i
] = r300_tfactor_alpha
[op
];
541 case GL_PRIMARY_COLOR
:
542 alpha_arg
[i
] = r300_primary_alpha
[op
];
546 alpha_arg
[i
] = r300_primary_alpha
[op
];
549 r300_register_alpha
[op
][0];
552 alpha_arg
[i
] = r300_zero_alpha
[op
];
555 alpha_arg
[i
] = r300_zero_alpha
[op
+ 1];
563 * Build up the color and alpha combine functions.
565 switch (texUnit
->_CurrentCombine
->ModeRGB
) {
567 color_combine
= (R200_TXC_ARG_A_ZERO
|
568 R200_TXC_ARG_B_ZERO
|
570 R200_COLOR_ARG(0, C
);
573 color_combine
= (R200_TXC_ARG_C_ZERO
|
575 R200_COLOR_ARG(0, A
);
576 R200_COLOR_ARG(1, B
);
579 color_combine
= (R200_TXC_ARG_B_ZERO
|
580 R200_TXC_COMP_ARG_B
|
582 R200_COLOR_ARG(0, A
);
583 R200_COLOR_ARG(1, C
);
586 color_combine
= (R200_TXC_ARG_B_ZERO
| R200_TXC_COMP_ARG_B
| R200_TXC_BIAS_ARG_C
| /* new */
587 R200_TXC_OP_MADD
); /* was ADDSIGNED */
588 R200_COLOR_ARG(0, A
);
589 R200_COLOR_ARG(1, C
);
592 color_combine
= (R200_TXC_ARG_B_ZERO
|
593 R200_TXC_COMP_ARG_B
|
594 R200_TXC_NEG_ARG_C
| R200_TXC_OP_MADD
);
595 R200_COLOR_ARG(0, A
);
596 R200_COLOR_ARG(1, C
);
599 color_combine
= (R200_TXC_OP_LERP
);
600 R200_COLOR_ARG(0, B
);
601 R200_COLOR_ARG(1, A
);
602 R200_COLOR_ARG(2, C
);
605 case GL_DOT3_RGB_EXT
:
606 case GL_DOT3_RGBA_EXT
:
607 /* The EXT version of the DOT3 extension does not support the
608 * scale factor, but the ARB version (and the version in OpenGL
616 /* DOT3 works differently on R200 than on R100. On R100, just
617 * setting the DOT3 mode did everything for you. On R200, the
618 * driver has to enable the biasing and scale in the inputs to
619 * put them in the proper [-1,1] range. This is what the 4x and
620 * the -0.5 in the DOT3 spec do. The post-scale is then set
624 color_combine
= (R200_TXC_ARG_C_ZERO
|
626 R200_TXC_BIAS_ARG_A
|
627 R200_TXC_BIAS_ARG_B
|
628 R200_TXC_SCALE_ARG_A
|
629 R200_TXC_SCALE_ARG_B
);
630 R200_COLOR_ARG(0, A
);
631 R200_COLOR_ARG(1, B
);
634 case GL_MODULATE_ADD_ATI
:
635 color_combine
= (R200_TXC_OP_MADD
);
636 R200_COLOR_ARG(0, A
);
637 R200_COLOR_ARG(1, C
);
638 R200_COLOR_ARG(2, B
);
640 case GL_MODULATE_SIGNED_ADD_ATI
:
641 color_combine
= (R200_TXC_BIAS_ARG_C
| /* new */
642 R200_TXC_OP_MADD
); /* was ADDSIGNED */
643 R200_COLOR_ARG(0, A
);
644 R200_COLOR_ARG(1, C
);
645 R200_COLOR_ARG(2, B
);
647 case GL_MODULATE_SUBTRACT_ATI
:
648 color_combine
= (R200_TXC_NEG_ARG_C
| R200_TXC_OP_MADD
);
649 R200_COLOR_ARG(0, A
);
650 R200_COLOR_ARG(1, C
);
651 R200_COLOR_ARG(2, B
);
657 switch (texUnit
->_CurrentCombine
->ModeA
) {
659 alpha_combine
= (R200_TXA_ARG_A_ZERO
|
660 R200_TXA_ARG_B_ZERO
|
662 R200_ALPHA_ARG(0, C
);
665 alpha_combine
= (R200_TXA_ARG_C_ZERO
|
667 R200_ALPHA_ARG(0, A
);
668 R200_ALPHA_ARG(1, B
);
671 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
672 R200_TXA_COMP_ARG_B
|
674 R200_ALPHA_ARG(0, A
);
675 R200_ALPHA_ARG(1, C
);
678 alpha_combine
= (R200_TXA_ARG_B_ZERO
| R200_TXA_COMP_ARG_B
| R200_TXA_BIAS_ARG_C
| /* new */
679 R200_TXA_OP_MADD
); /* was ADDSIGNED */
680 R200_ALPHA_ARG(0, A
);
681 R200_ALPHA_ARG(1, C
);
684 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
685 R200_TXA_COMP_ARG_B
|
686 R200_TXA_NEG_ARG_C
| R200_TXA_OP_MADD
);
687 R200_ALPHA_ARG(0, A
);
688 R200_ALPHA_ARG(1, C
);
691 alpha_combine
= (R200_TXA_OP_LERP
);
692 R200_ALPHA_ARG(0, B
);
693 R200_ALPHA_ARG(1, A
);
694 R200_ALPHA_ARG(2, C
);
697 case GL_MODULATE_ADD_ATI
:
698 alpha_combine
= (R200_TXA_OP_MADD
);
699 R200_ALPHA_ARG(0, A
);
700 R200_ALPHA_ARG(1, C
);
701 R200_ALPHA_ARG(2, B
);
703 case GL_MODULATE_SIGNED_ADD_ATI
:
704 alpha_combine
= (R200_TXA_BIAS_ARG_C
| /* new */
705 R200_TXA_OP_MADD
); /* was ADDSIGNED */
706 R200_ALPHA_ARG(0, A
);
707 R200_ALPHA_ARG(1, C
);
708 R200_ALPHA_ARG(2, B
);
710 case GL_MODULATE_SUBTRACT_ATI
:
711 alpha_combine
= (R200_TXA_NEG_ARG_C
| R200_TXA_OP_MADD
);
712 R200_ALPHA_ARG(0, A
);
713 R200_ALPHA_ARG(1, C
);
714 R200_ALPHA_ARG(2, B
);
720 if ((texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
721 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
)) {
722 alpha_scale
|= R200_TXA_DOT_ALPHA
;
727 * Apply the scale factor.
729 color_scale
|= (RGBshift
<< R200_TXC_SCALE_SHIFT
);
730 alpha_scale
|= (Ashift
<< R200_TXA_SCALE_SHIFT
);
736 if (rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND
] != color_combine
||
737 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND
] != alpha_combine
||
738 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] != color_scale
||
739 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] != alpha_scale
) {
740 R300_STATECHANGE(rmesa
, pix
[unit
]);
741 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND
] = color_combine
;
742 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND
] = alpha_combine
;
743 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] = color_scale
;
744 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] = alpha_scale
;
752 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
753 R200_MIN_FILTER_MASK | \
754 R200_MAG_FILTER_MASK | \
755 R200_MAX_ANISO_MASK | \
757 R200_YUV_TEMPERATURE_MASK | \
758 R200_CLAMP_S_MASK | \
759 R200_CLAMP_T_MASK | \
760 R200_BORDER_MODE_D3D )
762 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
763 R200_TXFORMAT_HEIGHT_MASK | \
764 R200_TXFORMAT_FORMAT_MASK | \
765 R200_TXFORMAT_F5_WIDTH_MASK | \
766 R200_TXFORMAT_F5_HEIGHT_MASK | \
767 R200_TXFORMAT_ALPHA_IN_MAP | \
768 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
769 R200_TXFORMAT_NON_POWER2)
771 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
772 R200_TEXCOORD_MASK | \
773 R200_CLAMP_Q_MASK | \
774 R200_VOLUME_FILTER_MASK)
776 static void import_tex_obj_state(r300ContextPtr rmesa
,
777 int unit
, r300TexObjPtr texobj
)
779 #if 0 /* needs fixing.. or should be done elsewhere */
780 GLuint
*cmd
= R300_DB_STATE(tex
[unit
]);
782 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
783 cmd
[TEX_PP_TXFILTER
] |= texobj
->filter
& TEXOBJ_TXFILTER_MASK
;
784 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
785 cmd
[TEX_PP_TXFORMAT
] |= texobj
->format
& TEXOBJ_TXFORMAT_MASK
;
786 cmd
[TEX_PP_TXFORMAT_X
] &= ~TEXOBJ_TXFORMAT_X_MASK
;
787 cmd
[TEX_PP_TXFORMAT_X
] |=
788 texobj
->format_x
& TEXOBJ_TXFORMAT_X_MASK
;
789 cmd
[TEX_PP_TXSIZE
] = texobj
->size
; /* NPOT only! */
790 cmd
[TEX_PP_TXPITCH
] = texobj
->pitch
; /* NPOT only! */
791 cmd
[TEX_PP_TXOFFSET
] = texobj
->pp_txoffset
;
792 cmd
[TEX_PP_BORDER_COLOR
] = texobj
->pp_border_color
;
793 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.tex
[unit
]);
795 if (texobj
->base
.tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
796 GLuint
*cube_cmd
= R200_DB_STATE(cube
[unit
]);
797 GLuint bytesPerFace
= texobj
->base
.totalSize
/ 6;
798 ASSERT(texobj
->totalSize
% 6 == 0);
799 cube_cmd
[CUBE_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
800 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F1
] =
801 texobj
->pp_txoffset
+ 1 * bytesPerFace
;
802 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F2
] =
803 texobj
->pp_txoffset
+ 2 * bytesPerFace
;
804 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F3
] =
805 texobj
->pp_txoffset
+ 3 * bytesPerFace
;
806 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F4
] =
807 texobj
->pp_txoffset
+ 4 * bytesPerFace
;
808 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F5
] =
809 texobj
->pp_txoffset
+ 5 * bytesPerFace
;
810 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.cube
[unit
]);
813 texobj
->dirty_state
&= ~(1 << unit
);
817 static void set_texgen_matrix(r300ContextPtr rmesa
,
819 const GLfloat
* s_plane
,
820 const GLfloat
* t_plane
, const GLfloat
* r_plane
)
822 static const GLfloat scale_identity
[4] = { 1, 1, 1, 1 };
824 if (!TEST_EQ_4V(s_plane
, scale_identity
) ||
825 !TEST_EQ_4V(t_plane
, scale_identity
) ||
826 !TEST_EQ_4V(r_plane
, scale_identity
)) {
827 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<< unit
;
828 rmesa
->TexGenMatrix
[unit
].m
[0] = s_plane
[0];
829 rmesa
->TexGenMatrix
[unit
].m
[4] = s_plane
[1];
830 rmesa
->TexGenMatrix
[unit
].m
[8] = s_plane
[2];
831 rmesa
->TexGenMatrix
[unit
].m
[12] = s_plane
[3];
833 rmesa
->TexGenMatrix
[unit
].m
[1] = t_plane
[0];
834 rmesa
->TexGenMatrix
[unit
].m
[5] = t_plane
[1];
835 rmesa
->TexGenMatrix
[unit
].m
[9] = t_plane
[2];
836 rmesa
->TexGenMatrix
[unit
].m
[13] = t_plane
[3];
838 /* NOTE: r_plane goes in the 4th row, not 3rd! */
839 rmesa
->TexGenMatrix
[unit
].m
[3] = r_plane
[0];
840 rmesa
->TexGenMatrix
[unit
].m
[7] = r_plane
[1];
841 rmesa
->TexGenMatrix
[unit
].m
[11] = r_plane
[2];
842 rmesa
->TexGenMatrix
[unit
].m
[15] = r_plane
[3];
844 //rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
848 /* Need this special matrix to get correct reflection map coords */
849 static void set_texgen_reflection_matrix(r300ContextPtr rmesa
, GLuint unit
)
851 static const GLfloat m
[16] = {
857 _math_matrix_loadf(&(rmesa
->TexGenMatrix
[unit
]), m
);
858 _math_matrix_analyse(&(rmesa
->TexGenMatrix
[unit
]));
859 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<< unit
;
862 /* Need this special matrix to get correct normal map coords */
863 static void set_texgen_normal_map_matrix(r300ContextPtr rmesa
, GLuint unit
)
865 static const GLfloat m
[16] = {
871 _math_matrix_loadf(&(rmesa
->TexGenMatrix
[unit
]), m
);
872 _math_matrix_analyse(&(rmesa
->TexGenMatrix
[unit
]));
873 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<< unit
;
876 /* Ignoring the Q texcoord for now.
878 * Returns GL_FALSE if fallback required.
880 static GLboolean
r300_validate_texgen(GLcontext
* ctx
, GLuint unit
)
882 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
883 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
884 GLuint inputshift
= R200_TEXGEN_0_INPUT_SHIFT
+ unit
* 4;
885 GLuint tmp
= rmesa
->TexGenEnabled
;
887 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
888 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
);
889 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<< unit
);
890 rmesa
->TexGenInputs
&= ~(R200_TEXGEN_INPUT_MASK
<< inputshift
);
891 rmesa
->TexGenNeedNormals
[unit
] = 0;
894 fprintf(stderr
, "%s unit %d\n", __FUNCTION__
, unit
);
896 if ((texUnit
->TexGenEnabled
& (S_BIT
| T_BIT
| R_BIT
)) == 0) {
897 /* Disabled, no fallback:
899 rmesa
->TexGenInputs
|=
900 (R200_TEXGEN_INPUT_TEXCOORD_0
+ unit
) << inputshift
;
902 } else if (texUnit
->TexGenEnabled
& Q_BIT
) {
903 /* Very easy to do this, in fact would remove a fallback case
904 * elsewhere, but I haven't done it yet... Fallback:
906 /*fprintf(stderr, "fallback Q_BIT\n"); */
908 } else if (texUnit
->TexGenEnabled
== (S_BIT
| T_BIT
) &&
909 texUnit
->GenModeS
== texUnit
->GenModeT
) {
911 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
913 } else if (texUnit
->TexGenEnabled
== (S_BIT
| T_BIT
| R_BIT
) &&
914 texUnit
->GenModeS
== texUnit
->GenModeT
&&
915 texUnit
->GenModeT
== texUnit
->GenModeR
) {
917 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
920 /* Mixed modes, fallback:
922 /* fprintf(stderr, "fallback mixed texgen\n"); */
926 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
928 switch (texUnit
->GenModeS
) {
929 case GL_OBJECT_LINEAR
:
930 rmesa
->TexGenInputs
|= R200_TEXGEN_INPUT_OBJ
<< inputshift
;
931 set_texgen_matrix(rmesa
, unit
,
932 texUnit
->ObjectPlaneS
,
933 texUnit
->ObjectPlaneT
, texUnit
->ObjectPlaneR
);
937 rmesa
->TexGenInputs
|= R200_TEXGEN_INPUT_EYE
<< inputshift
;
938 set_texgen_matrix(rmesa
, unit
,
940 texUnit
->EyePlaneT
, texUnit
->EyePlaneR
);
943 case GL_REFLECTION_MAP_NV
:
944 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
945 rmesa
->TexGenInputs
|=
946 R200_TEXGEN_INPUT_EYE_REFLECT
<< inputshift
;
947 set_texgen_reflection_matrix(rmesa
, unit
);
950 case GL_NORMAL_MAP_NV
:
951 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
952 rmesa
->TexGenInputs
|=
953 R200_TEXGEN_INPUT_EYE_NORMAL
<< inputshift
;
954 set_texgen_normal_map_matrix(rmesa
, unit
);
958 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
959 rmesa
->TexGenInputs
|= R200_TEXGEN_INPUT_SPHERE
<< inputshift
;
963 /* Unsupported mode, fallback:
965 /* fprintf(stderr, "fallback unsupported texgen\n"); */
969 rmesa
->TexGenCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
971 if (tmp
!= rmesa
->TexGenEnabled
) {
972 //rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
978 static void disable_tex(GLcontext
* ctx
, int unit
)
980 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
982 #if 0 /* This needs to be redone.. or done elsewhere */
983 if (rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<< unit
)) {
984 /* Texture unit disabled */
985 if (rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
986 /* The old texture is no longer bound to this texture unit.
990 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&=
992 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
995 R300_STATECHANGE(rmesa
, ctx
);
996 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~((R200_TEX_0_ENABLE
|
997 R200_TEX_BLEND_0_ENABLE
) <<
999 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_BLEND_0_ENABLE
;
1001 R300_STATECHANGE(rmesa
, tcl
);
1002 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &=
1005 if (rmesa
->radeon
.TclFallback
& (RADEON_TCL_FALLBACK_TEXGEN_0
<< unit
)) {
1006 TCL_FALLBACK(ctx
, (RADEON_TCL_FALLBACK_TEXGEN_0
<< unit
),
1010 /* Actually want to keep all units less than max active texture
1011 * enabled, right? Fix this for >2 texunits.
1013 /* FIXME: What should happen here if r300UpdateTextureEnv fails? */
1015 r300UpdateTextureEnv(ctx
, unit
);
1019 R200_TEXGEN_0_INPUT_SHIFT
+ unit
* 4;
1020 GLuint tmp
= rmesa
->TexGenEnabled
;
1022 rmesa
->TexGenEnabled
&=
1023 ~(R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
);
1024 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<< unit
);
1025 rmesa
->TexGenEnabled
&=
1026 ~(R200_TEXGEN_INPUT_MASK
<< inputshift
);
1027 rmesa
->TexGenNeedNormals
[unit
] = 0;
1028 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1029 rmesa
->TexGenInputs
&=
1030 ~(R200_TEXGEN_INPUT_MASK
<< inputshift
);
1032 if (tmp
!= rmesa
->TexGenEnabled
) {
1033 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1034 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1041 static GLboolean
enable_tex_2d(GLcontext
* ctx
, int unit
)
1043 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1044 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1045 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1046 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1048 /* Need to load the 2d images associated with this unit.
1050 if (t
->format
& R200_TXFORMAT_NON_POWER2
) {
1051 t
->format
&= ~R200_TXFORMAT_NON_POWER2
;
1052 t
->base
.dirty_images
[0] = ~0;
1055 ASSERT(tObj
->Target
== GL_TEXTURE_2D
|| tObj
->Target
== GL_TEXTURE_1D
);
1057 if (t
->base
.dirty_images
[0]) {
1058 R300_FIREVERTICES(rmesa
);
1059 r300SetTexImages(rmesa
, tObj
);
1060 r300UploadTexImages(rmesa
, (r300TexObjPtr
) tObj
->DriverData
, 0);
1061 if (!t
->base
.memBlock
)
1068 #if ENABLE_HW_3D_TEXTURE
1069 static GLboolean
enable_tex_3d(GLcontext
* ctx
, int unit
)
1071 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1072 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1073 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1074 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1076 /* Need to load the 3d images associated with this unit.
1078 if (t
->format
& R200_TXFORMAT_NON_POWER2
) {
1079 t
->format
&= ~R200_TXFORMAT_NON_POWER2
;
1080 t
->base
.dirty_images
[0] = ~0;
1083 ASSERT(tObj
->Target
== GL_TEXTURE_3D
);
1085 /* R100 & R200 do not support mipmaps for 3D textures.
1087 if ((tObj
->MinFilter
!= GL_NEAREST
) && (tObj
->MinFilter
!= GL_LINEAR
)) {
1091 if (t
->base
.dirty_images
[0]) {
1092 R300_FIREVERTICES(rmesa
);
1093 r300SetTexImages(rmesa
, tObj
);
1094 r300UploadTexImages(rmesa
, (r300TexObjPtr
) tObj
->DriverData
, 0);
1095 if (!t
->base
.memBlock
)
1103 static GLboolean
enable_tex_cube(GLcontext
* ctx
, int unit
)
1105 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1106 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1107 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1108 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1111 /* Need to load the 2d images associated with this unit.
1113 if (t
->format
& R200_TXFORMAT_NON_POWER2
) {
1114 t
->format
&= ~R200_TXFORMAT_NON_POWER2
;
1115 for (face
= 0; face
< 6; face
++)
1116 t
->base
.dirty_images
[face
] = ~0;
1119 ASSERT(tObj
->Target
== GL_TEXTURE_CUBE_MAP
);
1121 if (t
->base
.dirty_images
[0] || t
->base
.dirty_images
[1] ||
1122 t
->base
.dirty_images
[2] || t
->base
.dirty_images
[3] ||
1123 t
->base
.dirty_images
[4] || t
->base
.dirty_images
[5]) {
1125 R300_FIREVERTICES(rmesa
);
1126 /* layout memory space, once for all faces */
1127 r300SetTexImages(rmesa
, tObj
);
1130 /* upload (per face) */
1131 for (face
= 0; face
< 6; face
++) {
1132 if (t
->base
.dirty_images
[face
]) {
1133 r300UploadTexImages(rmesa
,
1134 (r300TexObjPtr
) tObj
->DriverData
,
1139 if (!t
->base
.memBlock
) {
1140 /* texmem alloc failed, use s/w fallback */
1147 static GLboolean
enable_tex_rect(GLcontext
* ctx
, int unit
)
1149 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1150 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1151 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1152 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1154 if (!(t
->format
& R200_TXFORMAT_NON_POWER2
)) {
1155 t
->format
|= R200_TXFORMAT_NON_POWER2
;
1156 t
->base
.dirty_images
[0] = ~0;
1159 ASSERT(tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
1161 if (t
->base
.dirty_images
[0]) {
1162 R300_FIREVERTICES(rmesa
);
1163 r300SetTexImages(rmesa
, tObj
);
1164 r300UploadTexImages(rmesa
, (r300TexObjPtr
) tObj
->DriverData
, 0);
1165 if (!t
->base
.memBlock
&& !rmesa
->prefer_gart_client_texturing
)
1172 static GLboolean
update_tex_common(GLcontext
* ctx
, int unit
)
1174 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1175 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1176 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1177 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1180 /* Fallback if there's a texture border */
1181 if (tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0)
1184 /* Update state if this is a different texture object to last
1187 if (rmesa
->state
.texture
.unit
[unit
].texobj
!= t
) {
1188 if (rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
1189 /* The old texture is no longer bound to this texture unit.
1193 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&=
1197 rmesa
->state
.texture
.unit
[unit
].texobj
= t
;
1198 t
->base
.bound
|= (1UL << unit
);
1199 t
->dirty_state
|= 1 << unit
;
1200 driUpdateTextureLRU((driTextureObject
*) t
); /* XXX: should be locked! */
1203 #if 0 /* do elsewhere ? */
1208 cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<< unit
))) {
1209 R300_STATECHANGE(rmesa
, ctx
);
1210 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= (R200_TEX_0_ENABLE
|
1211 R200_TEX_BLEND_0_ENABLE
) <<
1214 R300_STATECHANGE(rmesa
, vtx
);
1215 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] |= 4 << (unit
* 3);
1217 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1220 if (t
->dirty_state
& (1 << unit
)) {
1221 import_tex_obj_state(rmesa
, unit
, t
);
1224 if (rmesa
->recheck_texgen
[unit
]) {
1225 GLboolean fallback
= !r300_validate_texgen(ctx
, unit
);
1226 TCL_FALLBACK(ctx
, (RADEON_TCL_FALLBACK_TEXGEN_0
<< unit
),
1228 rmesa
->recheck_texgen
[unit
] = 0;
1229 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1232 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1233 if (rmesa
->state
.texture
.unit
[unit
].format
!= format
||
1234 rmesa
->state
.texture
.unit
[unit
].envMode
!= texUnit
->EnvMode
) {
1235 rmesa
->state
.texture
.unit
[unit
].format
= format
;
1236 rmesa
->state
.texture
.unit
[unit
].envMode
= texUnit
->EnvMode
;
1237 if (!r300UpdateTextureEnv(ctx
, unit
)) {
1243 FALLBACK(&rmesa
->radeon
, RADEON_FALLBACK_BORDER_MODE
, t
->border_fallback
);
1244 return !t
->border_fallback
;
1247 static GLboolean
r300UpdateTextureUnit(GLcontext
* ctx
, int unit
)
1249 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1251 if (texUnit
->_ReallyEnabled
& (TEXTURE_RECT_BIT
)) {
1252 return (enable_tex_rect(ctx
, unit
) &&
1253 update_tex_common(ctx
, unit
));
1254 } else if (texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
)) {
1255 return (enable_tex_2d(ctx
, unit
) &&
1256 update_tex_common(ctx
, unit
));
1258 #if ENABLE_HW_3D_TEXTURE
1259 else if (texUnit
->_ReallyEnabled
& (TEXTURE_3D_BIT
)) {
1260 return (enable_tex_3d(ctx
, unit
) &&
1261 update_tex_common(ctx
, unit
));
1264 else if (texUnit
->_ReallyEnabled
& (TEXTURE_CUBE_BIT
)) {
1265 return (enable_tex_cube(ctx
, unit
) &&
1266 update_tex_common(ctx
, unit
));
1267 } else if (texUnit
->_ReallyEnabled
) {
1270 disable_tex(ctx
, unit
);
1275 void r300UpdateTextureState(GLcontext
* ctx
)
1277 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1282 ok
= (r300UpdateTextureUnit(ctx
, 0) &&
1283 r300UpdateTextureUnit(ctx
, 1) &&
1284 r300UpdateTextureUnit(ctx
, 2) &&
1285 r300UpdateTextureUnit(ctx
, 3) &&
1286 r300UpdateTextureUnit(ctx
, 4) &&
1287 r300UpdateTextureUnit(ctx
, 5) &&
1288 r300UpdateTextureUnit(ctx
, 6) &&
1289 r300UpdateTextureUnit(ctx
, 7)
1292 FALLBACK(&rmesa
->radeon
, RADEON_FALLBACK_TEXTURE
, !ok
);
1294 /* This needs correction, or just be done elsewhere
1295 if (rmesa->radeon.TclFallback)
1296 r300ChooseVertexState(ctx);
1299 #if 0 /* Workaround - disable.. */
1300 if (GET_CHIP(rmesa
->radeon
.radeonScreen
) == RADEON_CHIP_REAL_R200
) {
1302 * T0 hang workaround -------------
1303 * not needed for r200 derivatives?
1305 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_ENABLE_MASK
) ==
1307 && (rmesa
->hw
.tex
[0].
1308 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) >
1309 R200_MIN_FILTER_LINEAR
) {
1311 R300_STATECHANGE(rmesa
, ctx
);
1312 R300_STATECHANGE(rmesa
, tex
[1]);
1313 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_1_ENABLE
;
1314 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &=
1315 ~TEXOBJ_TXFORMAT_MASK
;
1316 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] |= 0x08000000;
1318 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
)
1319 && (rmesa
->hw
.tex
[1].
1320 cmd
[TEX_PP_TXFORMAT
] & 0x08000000)) {
1321 R300_STATECHANGE(rmesa
, tex
[1]);
1322 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &=
1327 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1328 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1329 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1330 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1331 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1332 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1333 R200_MIN_FILTER_LINEAR)) {
1334 R300_STATECHANGE(rmesa, ctx);
1335 R300_STATECHANGE(rmesa, tex[i+1]);
1336 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1337 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1338 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1341 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1342 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1343 R300_STATECHANGE(rmesa, tex[i+1]);
1344 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1350 * Texture cache LRU hang workaround -------------
1351 * not needed for r200 derivatives?
1355 if (((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
)) &&
1356 ((((rmesa
->hw
.tex
[0].
1357 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) & 0x04)
1359 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_2_ENABLE
)
1361 ((((rmesa
->hw
.tex
[2].
1362 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1364 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_4_ENABLE
)
1366 ((((rmesa
->hw
.tex
[4].
1367 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1372 if (((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_1_ENABLE
)) &&
1373 ((((rmesa
->hw
.tex
[1].
1374 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) & 0x04)
1376 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_3_ENABLE
)
1378 ((((rmesa
->hw
.tex
[3].
1379 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1381 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_5_ENABLE
)
1383 ((((rmesa
->hw
.tex
[5].
1384 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1389 if (dbg
!= rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
]) {
1390 R300_STATECHANGE(rmesa
, tam
);
1391 rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
] = dbg
;
1393 printf("TEXCACHE LRU HANG WORKAROUND %x\n",