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
);
123 t
->filter
&= ~R200_YUV_TO_RGB
;
125 if (VALID_FORMAT(baseImage
->TexFormat
->MesaFormat
)) {
127 tx_table
[baseImage
->TexFormat
->MesaFormat
].format
;
129 tx_table
[baseImage
->TexFormat
->MesaFormat
].filter
;
131 _mesa_problem(NULL
, "unexpected texture format in %s",
136 /* Compute which mipmap levels we really want to send to the hardware.
139 driCalculateTextureFirstLastLevel((driTextureObject
*) t
);
140 log2Width
= tObj
->Image
[0][t
->base
.firstLevel
]->WidthLog2
;
141 log2Height
= tObj
->Image
[0][t
->base
.firstLevel
]->HeightLog2
;
142 log2Depth
= tObj
->Image
[0][t
->base
.firstLevel
]->DepthLog2
;
144 numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
146 assert(numLevels
<= RADEON_MAX_TEXTURE_LEVELS
);
148 /* Calculate mipmap offsets and dimensions for blitting (uploading)
149 * The idea is that we lay out the mipmap levels within a block of
150 * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
154 for (i
= 0; i
< numLevels
; i
++) {
155 const struct gl_texture_image
*texImage
;
158 texImage
= tObj
->Image
[0][i
+ t
->base
.firstLevel
];
162 /* find image size in bytes */
163 if (texImage
->IsCompressed
) {
164 size
= texImage
->CompressedSize
;
165 } else if (tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
) {
168 texImage
->TexFormat
->TexelBytes
+ 63)
169 & ~63) * texImage
->Height
;
172 texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
175 size
= w
* texImage
->Height
* texImage
->Depth
;
180 fprintf(stderr
, "w=%d h=%d d=%d tb=%d intFormat=%d\n", texImage
->Width
, texImage
->Height
,
181 texImage
->Depth
, texImage
->TexFormat
->TexelBytes
,
182 texImage
->IntFormat
);
184 /* Align to 32-byte offset. It is faster to do this unconditionally
185 * (no branch penalty).
188 curOffset
= (curOffset
+ 0x1f) & ~0x1f;
190 t
->image
[0][i
].x
= curOffset
% BLIT_WIDTH_BYTES
;
191 t
->image
[0][i
].y
= curOffset
/ BLIT_WIDTH_BYTES
;
192 t
->image
[0][i
].width
= MIN2(size
, BLIT_WIDTH_BYTES
);
193 t
->image
[0][i
].height
= size
/ t
->image
[0][i
].width
;
196 /* for debugging only and only applicable to non-rectangle targets */
197 assert(size
% t
->image
[0][i
].width
== 0);
198 assert(t
->image
[0][i
].x
== 0
199 || (size
< BLIT_WIDTH_BYTES
200 && t
->image
[0][i
].height
== 1));
205 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
206 i
, texImage
->Width
, texImage
->Height
,
207 t
->image
[0][i
].x
, t
->image
[0][i
].y
,
208 t
->image
[0][i
].width
, t
->image
[0][i
].height
,
215 /* Align the total size of texture memory block.
218 (curOffset
+ RADEON_OFFSET_MASK
) & ~RADEON_OFFSET_MASK
;
220 /* Setup remaining cube face blits, if needed */
221 if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
222 /* Round totalSize up to multiple of BLIT_WIDTH_BYTES */
223 const GLuint faceSize
=
224 (t
->base
.totalSize
+ BLIT_WIDTH_BYTES
- 1)
225 & ~(BLIT_WIDTH_BYTES
- 1);
226 const GLuint lines
= faceSize
/ BLIT_WIDTH_BYTES
;
228 /* reuse face 0 x/y/width/height - just adjust y */
229 for (face
= 1; face
< 6; face
++) {
230 for (i
= 0; i
< numLevels
; i
++) {
231 t
->image
[face
][i
].x
= t
->image
[0][i
].x
;
232 t
->image
[face
][i
].y
=
233 t
->image
[0][i
].y
+ face
* lines
;
234 t
->image
[face
][i
].width
= t
->image
[0][i
].width
;
235 t
->image
[face
][i
].height
=
236 t
->image
[0][i
].height
;
239 t
->base
.totalSize
= 6 * faceSize
; /* total texmem needed */
244 t
->filter
&= ~R200_MAX_MIP_LEVEL_MASK
;
245 t
->filter
|= (numLevels
- 1) << R200_MAX_MIP_LEVEL_SHIFT
;
247 t
->format
&= ~(R300_TX_FORMAT_WIDTH_MASK
|
248 R300_TX_FORMAT_HEIGHT_MASK
|
249 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
250 R200_TXFORMAT_F5_WIDTH_MASK
|
251 R200_TXFORMAT_F5_HEIGHT_MASK
);
252 t
->format
|= ((log2Width
<< R300_TX_FORMAT_WIDTH_SHIFT
) |
253 (log2Height
<< R300_TX_FORMAT_HEIGHT_SHIFT
));
255 t
->format_x
&= ~(R200_DEPTH_LOG2_MASK
| R200_TEXCOORD_MASK
);
256 if (tObj
->Target
== GL_TEXTURE_3D
) {
257 t
->format_x
|= (log2Depth
<< R200_DEPTH_LOG2_SHIFT
);
258 t
->format_x
|= R200_TEXCOORD_VOLUME
;
259 } else if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
260 ASSERT(log2Width
== log2height
);
261 t
->format
|= ((log2Width
<< R200_TXFORMAT_F5_WIDTH_SHIFT
) |
262 (log2Height
<< R200_TXFORMAT_F5_HEIGHT_SHIFT
)
263 | (R200_TXFORMAT_CUBIC_MAP_ENABLE
));
264 t
->format_x
|= R200_TEXCOORD_CUBIC_ENV
;
265 t
->pp_cubic_faces
= ((log2Width
<< R200_FACE_WIDTH_1_SHIFT
) |
266 (log2Height
<< R200_FACE_HEIGHT_1_SHIFT
) |
267 (log2Width
<< R200_FACE_WIDTH_2_SHIFT
) |
268 (log2Height
<< R200_FACE_HEIGHT_2_SHIFT
) |
269 (log2Width
<< R200_FACE_WIDTH_3_SHIFT
) |
270 (log2Height
<< R200_FACE_HEIGHT_3_SHIFT
) |
271 (log2Width
<< R200_FACE_WIDTH_4_SHIFT
) |
272 (log2Height
<< R200_FACE_HEIGHT_4_SHIFT
));
275 t
->size
= (((tObj
->Image
[0][t
->base
.firstLevel
]->Width
- 1) << R300_TX_WIDTHMASK_SHIFT
)
276 |((tObj
->Image
[0][t
->base
.firstLevel
]->Height
- 1) << R300_TX_HEIGHTMASK_SHIFT
)
277 |((log2Width
>log2Height
)?log2Width
:log2Height
)<<R300_TX_SIZE_SHIFT
);
279 /* Only need to round to nearest 32 for textures, but the blitter
280 * requires 64-byte aligned pitches, and we may/may not need the
281 * blitter. NPOT only!
283 if (baseImage
->IsCompressed
)
285 (tObj
->Image
[0][t
->base
.firstLevel
]->Width
+ 63) & ~(63);
288 ((tObj
->Image
[0][t
->base
.firstLevel
]->Width
*
289 baseImage
->TexFormat
->TexelBytes
) + 63) & ~(63);
292 t
->dirty_state
= TEX_ALL
;
294 /* FYI: r300UploadTexImages( rmesa, t ) used to be called here */
297 /* ================================================================
298 * Texture combine functions
301 /* GL_ARB_texture_env_combine support
304 /* The color tables have combine functions for GL_SRC_COLOR,
305 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
307 static GLuint r300_register_color
[][R200_MAX_TEXTURE_UNITS
] = {
309 R200_TXC_ARG_A_R0_COLOR
,
310 R200_TXC_ARG_A_R1_COLOR
,
311 R200_TXC_ARG_A_R2_COLOR
,
312 R200_TXC_ARG_A_R3_COLOR
,
313 R200_TXC_ARG_A_R4_COLOR
,
314 R200_TXC_ARG_A_R5_COLOR
},
316 R200_TXC_ARG_A_R0_COLOR
| R200_TXC_COMP_ARG_A
,
317 R200_TXC_ARG_A_R1_COLOR
| R200_TXC_COMP_ARG_A
,
318 R200_TXC_ARG_A_R2_COLOR
| R200_TXC_COMP_ARG_A
,
319 R200_TXC_ARG_A_R3_COLOR
| R200_TXC_COMP_ARG_A
,
320 R200_TXC_ARG_A_R4_COLOR
| R200_TXC_COMP_ARG_A
,
321 R200_TXC_ARG_A_R5_COLOR
| R200_TXC_COMP_ARG_A
},
323 R200_TXC_ARG_A_R0_ALPHA
,
324 R200_TXC_ARG_A_R1_ALPHA
,
325 R200_TXC_ARG_A_R2_ALPHA
,
326 R200_TXC_ARG_A_R3_ALPHA
,
327 R200_TXC_ARG_A_R4_ALPHA
,
328 R200_TXC_ARG_A_R5_ALPHA
},
330 R200_TXC_ARG_A_R0_ALPHA
| R200_TXC_COMP_ARG_A
,
331 R200_TXC_ARG_A_R1_ALPHA
| R200_TXC_COMP_ARG_A
,
332 R200_TXC_ARG_A_R2_ALPHA
| R200_TXC_COMP_ARG_A
,
333 R200_TXC_ARG_A_R3_ALPHA
| R200_TXC_COMP_ARG_A
,
334 R200_TXC_ARG_A_R4_ALPHA
| R200_TXC_COMP_ARG_A
,
335 R200_TXC_ARG_A_R5_ALPHA
| R200_TXC_COMP_ARG_A
},
338 static GLuint r300_tfactor_color
[] = {
339 R200_TXC_ARG_A_TFACTOR_COLOR
,
340 R200_TXC_ARG_A_TFACTOR_COLOR
| R200_TXC_COMP_ARG_A
,
341 R200_TXC_ARG_A_TFACTOR_ALPHA
,
342 R200_TXC_ARG_A_TFACTOR_ALPHA
| R200_TXC_COMP_ARG_A
345 static GLuint r300_primary_color
[] = {
346 R200_TXC_ARG_A_DIFFUSE_COLOR
,
347 R200_TXC_ARG_A_DIFFUSE_COLOR
| R200_TXC_COMP_ARG_A
,
348 R200_TXC_ARG_A_DIFFUSE_ALPHA
,
349 R200_TXC_ARG_A_DIFFUSE_ALPHA
| R200_TXC_COMP_ARG_A
352 /* GL_ZERO table - indices 0-3
353 * GL_ONE table - indices 1-4
355 static GLuint r300_zero_color
[] = {
357 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
359 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
363 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
365 static GLuint r300_register_alpha
[][R200_MAX_TEXTURE_UNITS
] = {
367 R200_TXA_ARG_A_R0_ALPHA
,
368 R200_TXA_ARG_A_R1_ALPHA
,
369 R200_TXA_ARG_A_R2_ALPHA
,
370 R200_TXA_ARG_A_R3_ALPHA
,
371 R200_TXA_ARG_A_R4_ALPHA
,
372 R200_TXA_ARG_A_R5_ALPHA
},
374 R200_TXA_ARG_A_R0_ALPHA
| R200_TXA_COMP_ARG_A
,
375 R200_TXA_ARG_A_R1_ALPHA
| R200_TXA_COMP_ARG_A
,
376 R200_TXA_ARG_A_R2_ALPHA
| R200_TXA_COMP_ARG_A
,
377 R200_TXA_ARG_A_R3_ALPHA
| R200_TXA_COMP_ARG_A
,
378 R200_TXA_ARG_A_R4_ALPHA
| R200_TXA_COMP_ARG_A
,
379 R200_TXA_ARG_A_R5_ALPHA
| R200_TXA_COMP_ARG_A
},
382 static GLuint r300_tfactor_alpha
[] = {
383 R200_TXA_ARG_A_TFACTOR_ALPHA
,
384 R200_TXA_ARG_A_TFACTOR_ALPHA
| R200_TXA_COMP_ARG_A
387 static GLuint r300_primary_alpha
[] = {
388 R200_TXA_ARG_A_DIFFUSE_ALPHA
,
389 R200_TXA_ARG_A_DIFFUSE_ALPHA
| R200_TXA_COMP_ARG_A
392 /* GL_ZERO table - indices 0-1
393 * GL_ONE table - indices 1-2
395 static GLuint r300_zero_alpha
[] = {
397 R200_TXA_ARG_A_ZERO
| R200_TXA_COMP_ARG_A
,
401 /* Extract the arg from slot A, shift it into the correct argument slot
402 * and set the corresponding complement bit.
404 #define R200_COLOR_ARG( n, arg ) \
407 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
408 << R200_TXC_ARG_##arg##_SHIFT); \
410 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
411 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
414 #define R200_ALPHA_ARG( n, arg ) \
417 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
418 << R200_TXA_ARG_##arg##_SHIFT); \
420 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
421 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
424 /* ================================================================
425 * Texture unit state management
428 static GLboolean
r300UpdateTextureEnv(GLcontext
* ctx
, int unit
)
430 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
431 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
432 GLuint color_combine
, alpha_combine
;
434 #if 0 /* disable for now.. */
435 GLuint color_scale
= rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] &
436 ~(R200_TXC_SCALE_MASK
);
437 GLuint alpha_scale
= rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] &
438 ~(R200_TXA_DOT_ALPHA
| R200_TXA_SCALE_MASK
);
440 /* texUnit->_Current can be NULL if and only if the texture unit is
441 * not actually enabled.
443 assert((texUnit
->_ReallyEnabled
== 0)
444 || (texUnit
->_Current
!= NULL
));
446 if (RADEON_DEBUG
& DEBUG_TEXTURE
) {
447 fprintf(stderr
, "%s( %p, %d )\n", __FUNCTION__
, (void *)ctx
,
451 /* Set the texture environment state. Isn't this nice and clean?
452 * The chip will automagically set the texture alpha to 0xff when
453 * the texture format does not include an alpha component. This
454 * reduces the amount of special-casing we have to do, alpha-only
455 * textures being a notable exception.
457 /* Don't cache these results.
459 rmesa
->state
.texture
.unit
[unit
].format
= 0;
460 rmesa
->state
.texture
.unit
[unit
].envMode
= 0;
462 if (!texUnit
->_ReallyEnabled
) {
465 R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
|
466 R200_TXC_ARG_C_DIFFUSE_COLOR
| R200_TXC_OP_MADD
;
468 R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
|
469 R200_TXA_ARG_C_DIFFUSE_ALPHA
| R200_TXA_OP_MADD
;
472 R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
|
473 R200_TXC_ARG_C_R0_COLOR
| R200_TXC_OP_MADD
;
475 R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
|
476 R200_TXA_ARG_C_R0_ALPHA
| R200_TXA_OP_MADD
;
479 GLuint color_arg
[3], alpha_arg
[3];
481 const GLuint numColorArgs
=
482 texUnit
->_CurrentCombine
->_NumArgsRGB
;
483 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
484 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
485 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
488 * Extract the color and alpha combine function arguments.
490 for (i
= 0; i
< numColorArgs
; i
++) {
492 texUnit
->_CurrentCombine
->OperandRGB
[i
] -
496 switch (texUnit
->_CurrentCombine
->SourceRGB
[i
]) {
498 color_arg
[i
] = r300_register_color
[op
][unit
];
501 color_arg
[i
] = r300_tfactor_color
[op
];
503 case GL_PRIMARY_COLOR
:
504 color_arg
[i
] = r300_primary_color
[op
];
508 color_arg
[i
] = r300_primary_color
[op
];
511 r300_register_color
[op
][0];
514 color_arg
[i
] = r300_zero_color
[op
];
517 color_arg
[i
] = r300_zero_color
[op
+ 1];
524 for (i
= 0; i
< numAlphaArgs
; i
++) {
526 texUnit
->_CurrentCombine
->OperandA
[i
] -
530 switch (texUnit
->_CurrentCombine
->SourceA
[i
]) {
532 alpha_arg
[i
] = r300_register_alpha
[op
][unit
];
535 alpha_arg
[i
] = r300_tfactor_alpha
[op
];
537 case GL_PRIMARY_COLOR
:
538 alpha_arg
[i
] = r300_primary_alpha
[op
];
542 alpha_arg
[i
] = r300_primary_alpha
[op
];
545 r300_register_alpha
[op
][0];
548 alpha_arg
[i
] = r300_zero_alpha
[op
];
551 alpha_arg
[i
] = r300_zero_alpha
[op
+ 1];
559 * Build up the color and alpha combine functions.
561 switch (texUnit
->_CurrentCombine
->ModeRGB
) {
563 color_combine
= (R200_TXC_ARG_A_ZERO
|
564 R200_TXC_ARG_B_ZERO
|
566 R200_COLOR_ARG(0, C
);
569 color_combine
= (R200_TXC_ARG_C_ZERO
|
571 R200_COLOR_ARG(0, A
);
572 R200_COLOR_ARG(1, B
);
575 color_combine
= (R200_TXC_ARG_B_ZERO
|
576 R200_TXC_COMP_ARG_B
|
578 R200_COLOR_ARG(0, A
);
579 R200_COLOR_ARG(1, C
);
582 color_combine
= (R200_TXC_ARG_B_ZERO
| R200_TXC_COMP_ARG_B
| R200_TXC_BIAS_ARG_C
| /* new */
583 R200_TXC_OP_MADD
); /* was ADDSIGNED */
584 R200_COLOR_ARG(0, A
);
585 R200_COLOR_ARG(1, C
);
588 color_combine
= (R200_TXC_ARG_B_ZERO
|
589 R200_TXC_COMP_ARG_B
|
590 R200_TXC_NEG_ARG_C
| R200_TXC_OP_MADD
);
591 R200_COLOR_ARG(0, A
);
592 R200_COLOR_ARG(1, C
);
595 color_combine
= (R200_TXC_OP_LERP
);
596 R200_COLOR_ARG(0, B
);
597 R200_COLOR_ARG(1, A
);
598 R200_COLOR_ARG(2, C
);
601 case GL_DOT3_RGB_EXT
:
602 case GL_DOT3_RGBA_EXT
:
603 /* The EXT version of the DOT3 extension does not support the
604 * scale factor, but the ARB version (and the version in OpenGL
612 /* DOT3 works differently on R200 than on R100. On R100, just
613 * setting the DOT3 mode did everything for you. On R200, the
614 * driver has to enable the biasing and scale in the inputs to
615 * put them in the proper [-1,1] range. This is what the 4x and
616 * the -0.5 in the DOT3 spec do. The post-scale is then set
620 color_combine
= (R200_TXC_ARG_C_ZERO
|
622 R200_TXC_BIAS_ARG_A
|
623 R200_TXC_BIAS_ARG_B
|
624 R200_TXC_SCALE_ARG_A
|
625 R200_TXC_SCALE_ARG_B
);
626 R200_COLOR_ARG(0, A
);
627 R200_COLOR_ARG(1, B
);
630 case GL_MODULATE_ADD_ATI
:
631 color_combine
= (R200_TXC_OP_MADD
);
632 R200_COLOR_ARG(0, A
);
633 R200_COLOR_ARG(1, C
);
634 R200_COLOR_ARG(2, B
);
636 case GL_MODULATE_SIGNED_ADD_ATI
:
637 color_combine
= (R200_TXC_BIAS_ARG_C
| /* new */
638 R200_TXC_OP_MADD
); /* was ADDSIGNED */
639 R200_COLOR_ARG(0, A
);
640 R200_COLOR_ARG(1, C
);
641 R200_COLOR_ARG(2, B
);
643 case GL_MODULATE_SUBTRACT_ATI
:
644 color_combine
= (R200_TXC_NEG_ARG_C
| R200_TXC_OP_MADD
);
645 R200_COLOR_ARG(0, A
);
646 R200_COLOR_ARG(1, C
);
647 R200_COLOR_ARG(2, B
);
653 switch (texUnit
->_CurrentCombine
->ModeA
) {
655 alpha_combine
= (R200_TXA_ARG_A_ZERO
|
656 R200_TXA_ARG_B_ZERO
|
658 R200_ALPHA_ARG(0, C
);
661 alpha_combine
= (R200_TXA_ARG_C_ZERO
|
663 R200_ALPHA_ARG(0, A
);
664 R200_ALPHA_ARG(1, B
);
667 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
668 R200_TXA_COMP_ARG_B
|
670 R200_ALPHA_ARG(0, A
);
671 R200_ALPHA_ARG(1, C
);
674 alpha_combine
= (R200_TXA_ARG_B_ZERO
| R200_TXA_COMP_ARG_B
| R200_TXA_BIAS_ARG_C
| /* new */
675 R200_TXA_OP_MADD
); /* was ADDSIGNED */
676 R200_ALPHA_ARG(0, A
);
677 R200_ALPHA_ARG(1, C
);
680 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
681 R200_TXA_COMP_ARG_B
|
682 R200_TXA_NEG_ARG_C
| R200_TXA_OP_MADD
);
683 R200_ALPHA_ARG(0, A
);
684 R200_ALPHA_ARG(1, C
);
687 alpha_combine
= (R200_TXA_OP_LERP
);
688 R200_ALPHA_ARG(0, B
);
689 R200_ALPHA_ARG(1, A
);
690 R200_ALPHA_ARG(2, C
);
693 case GL_MODULATE_ADD_ATI
:
694 alpha_combine
= (R200_TXA_OP_MADD
);
695 R200_ALPHA_ARG(0, A
);
696 R200_ALPHA_ARG(1, C
);
697 R200_ALPHA_ARG(2, B
);
699 case GL_MODULATE_SIGNED_ADD_ATI
:
700 alpha_combine
= (R200_TXA_BIAS_ARG_C
| /* new */
701 R200_TXA_OP_MADD
); /* was ADDSIGNED */
702 R200_ALPHA_ARG(0, A
);
703 R200_ALPHA_ARG(1, C
);
704 R200_ALPHA_ARG(2, B
);
706 case GL_MODULATE_SUBTRACT_ATI
:
707 alpha_combine
= (R200_TXA_NEG_ARG_C
| R200_TXA_OP_MADD
);
708 R200_ALPHA_ARG(0, A
);
709 R200_ALPHA_ARG(1, C
);
710 R200_ALPHA_ARG(2, B
);
716 if ((texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
717 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
)) {
718 alpha_scale
|= R200_TXA_DOT_ALPHA
;
723 * Apply the scale factor.
725 color_scale
|= (RGBshift
<< R200_TXC_SCALE_SHIFT
);
726 alpha_scale
|= (Ashift
<< R200_TXA_SCALE_SHIFT
);
732 if (rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND
] != color_combine
||
733 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND
] != alpha_combine
||
734 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] != color_scale
||
735 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] != alpha_scale
) {
736 R300_STATECHANGE(rmesa
, pix
[unit
]);
737 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND
] = color_combine
;
738 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND
] = alpha_combine
;
739 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] = color_scale
;
740 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] = alpha_scale
;
748 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
749 R200_MIN_FILTER_MASK | \
750 R200_MAG_FILTER_MASK | \
751 R200_MAX_ANISO_MASK | \
753 R200_YUV_TEMPERATURE_MASK | \
754 R200_CLAMP_S_MASK | \
755 R200_CLAMP_T_MASK | \
756 R200_BORDER_MODE_D3D )
758 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
759 R200_TXFORMAT_HEIGHT_MASK | \
760 R200_TXFORMAT_FORMAT_MASK | \
761 R200_TXFORMAT_F5_WIDTH_MASK | \
762 R200_TXFORMAT_F5_HEIGHT_MASK | \
763 R200_TXFORMAT_ALPHA_IN_MAP | \
764 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
765 R200_TXFORMAT_NON_POWER2)
767 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
768 R200_TEXCOORD_MASK | \
769 R200_CLAMP_Q_MASK | \
770 R200_VOLUME_FILTER_MASK)
772 static void import_tex_obj_state(r300ContextPtr rmesa
,
773 int unit
, r300TexObjPtr texobj
)
775 #if 0 /* needs fixing.. or should be done elsewhere */
776 GLuint
*cmd
= R300_DB_STATE(tex
[unit
]);
778 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
779 cmd
[TEX_PP_TXFILTER
] |= texobj
->filter
& TEXOBJ_TXFILTER_MASK
;
780 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
781 cmd
[TEX_PP_TXFORMAT
] |= texobj
->format
& TEXOBJ_TXFORMAT_MASK
;
782 cmd
[TEX_PP_TXFORMAT_X
] &= ~TEXOBJ_TXFORMAT_X_MASK
;
783 cmd
[TEX_PP_TXFORMAT_X
] |=
784 texobj
->format_x
& TEXOBJ_TXFORMAT_X_MASK
;
785 cmd
[TEX_PP_TXSIZE
] = texobj
->size
; /* NPOT only! */
786 cmd
[TEX_PP_TXPITCH
] = texobj
->pitch
; /* NPOT only! */
787 cmd
[TEX_PP_TXOFFSET
] = texobj
->pp_txoffset
;
788 cmd
[TEX_PP_BORDER_COLOR
] = texobj
->pp_border_color
;
789 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.tex
[unit
]);
791 if (texobj
->base
.tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
792 GLuint
*cube_cmd
= R200_DB_STATE(cube
[unit
]);
793 GLuint bytesPerFace
= texobj
->base
.totalSize
/ 6;
794 ASSERT(texobj
->totalSize
% 6 == 0);
795 cube_cmd
[CUBE_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
796 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F1
] =
797 texobj
->pp_txoffset
+ 1 * bytesPerFace
;
798 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F2
] =
799 texobj
->pp_txoffset
+ 2 * bytesPerFace
;
800 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F3
] =
801 texobj
->pp_txoffset
+ 3 * bytesPerFace
;
802 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F4
] =
803 texobj
->pp_txoffset
+ 4 * bytesPerFace
;
804 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F5
] =
805 texobj
->pp_txoffset
+ 5 * bytesPerFace
;
806 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.cube
[unit
]);
809 texobj
->dirty_state
&= ~(1 << unit
);
813 static void set_texgen_matrix(r300ContextPtr rmesa
,
815 const GLfloat
* s_plane
,
816 const GLfloat
* t_plane
, const GLfloat
* r_plane
)
818 static const GLfloat scale_identity
[4] = { 1, 1, 1, 1 };
820 if (!TEST_EQ_4V(s_plane
, scale_identity
) ||
821 !TEST_EQ_4V(t_plane
, scale_identity
) ||
822 !TEST_EQ_4V(r_plane
, scale_identity
)) {
823 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<< unit
;
824 rmesa
->TexGenMatrix
[unit
].m
[0] = s_plane
[0];
825 rmesa
->TexGenMatrix
[unit
].m
[4] = s_plane
[1];
826 rmesa
->TexGenMatrix
[unit
].m
[8] = s_plane
[2];
827 rmesa
->TexGenMatrix
[unit
].m
[12] = s_plane
[3];
829 rmesa
->TexGenMatrix
[unit
].m
[1] = t_plane
[0];
830 rmesa
->TexGenMatrix
[unit
].m
[5] = t_plane
[1];
831 rmesa
->TexGenMatrix
[unit
].m
[9] = t_plane
[2];
832 rmesa
->TexGenMatrix
[unit
].m
[13] = t_plane
[3];
834 /* NOTE: r_plane goes in the 4th row, not 3rd! */
835 rmesa
->TexGenMatrix
[unit
].m
[3] = r_plane
[0];
836 rmesa
->TexGenMatrix
[unit
].m
[7] = r_plane
[1];
837 rmesa
->TexGenMatrix
[unit
].m
[11] = r_plane
[2];
838 rmesa
->TexGenMatrix
[unit
].m
[15] = r_plane
[3];
840 //rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
844 /* Need this special matrix to get correct reflection map coords */
845 static void set_texgen_reflection_matrix(r300ContextPtr rmesa
, GLuint unit
)
847 static const GLfloat m
[16] = {
853 _math_matrix_loadf(&(rmesa
->TexGenMatrix
[unit
]), m
);
854 _math_matrix_analyse(&(rmesa
->TexGenMatrix
[unit
]));
855 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<< unit
;
858 /* Need this special matrix to get correct normal map coords */
859 static void set_texgen_normal_map_matrix(r300ContextPtr rmesa
, GLuint unit
)
861 static const GLfloat m
[16] = {
867 _math_matrix_loadf(&(rmesa
->TexGenMatrix
[unit
]), m
);
868 _math_matrix_analyse(&(rmesa
->TexGenMatrix
[unit
]));
869 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<< unit
;
872 /* Ignoring the Q texcoord for now.
874 * Returns GL_FALSE if fallback required.
876 static GLboolean
r300_validate_texgen(GLcontext
* ctx
, GLuint unit
)
878 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
879 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
880 GLuint inputshift
= R200_TEXGEN_0_INPUT_SHIFT
+ unit
* 4;
881 GLuint tmp
= rmesa
->TexGenEnabled
;
883 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
884 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
);
885 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<< unit
);
886 rmesa
->TexGenInputs
&= ~(R200_TEXGEN_INPUT_MASK
<< inputshift
);
887 rmesa
->TexGenNeedNormals
[unit
] = 0;
890 fprintf(stderr
, "%s unit %d\n", __FUNCTION__
, unit
);
892 if ((texUnit
->TexGenEnabled
& (S_BIT
| T_BIT
| R_BIT
)) == 0) {
893 /* Disabled, no fallback:
895 rmesa
->TexGenInputs
|=
896 (R200_TEXGEN_INPUT_TEXCOORD_0
+ unit
) << inputshift
;
898 } else if (texUnit
->TexGenEnabled
& Q_BIT
) {
899 /* Very easy to do this, in fact would remove a fallback case
900 * elsewhere, but I haven't done it yet... Fallback:
902 /*fprintf(stderr, "fallback Q_BIT\n"); */
904 } else if (texUnit
->TexGenEnabled
== (S_BIT
| T_BIT
) &&
905 texUnit
->GenModeS
== texUnit
->GenModeT
) {
907 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
909 } else if (texUnit
->TexGenEnabled
== (S_BIT
| T_BIT
| R_BIT
) &&
910 texUnit
->GenModeS
== texUnit
->GenModeT
&&
911 texUnit
->GenModeT
== texUnit
->GenModeR
) {
913 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
916 /* Mixed modes, fallback:
918 /* fprintf(stderr, "fallback mixed texgen\n"); */
922 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
924 switch (texUnit
->GenModeS
) {
925 case GL_OBJECT_LINEAR
:
926 rmesa
->TexGenInputs
|= R200_TEXGEN_INPUT_OBJ
<< inputshift
;
927 set_texgen_matrix(rmesa
, unit
,
928 texUnit
->ObjectPlaneS
,
929 texUnit
->ObjectPlaneT
, texUnit
->ObjectPlaneR
);
933 rmesa
->TexGenInputs
|= R200_TEXGEN_INPUT_EYE
<< inputshift
;
934 set_texgen_matrix(rmesa
, unit
,
936 texUnit
->EyePlaneT
, texUnit
->EyePlaneR
);
939 case GL_REFLECTION_MAP_NV
:
940 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
941 rmesa
->TexGenInputs
|=
942 R200_TEXGEN_INPUT_EYE_REFLECT
<< inputshift
;
943 set_texgen_reflection_matrix(rmesa
, unit
);
946 case GL_NORMAL_MAP_NV
:
947 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
948 rmesa
->TexGenInputs
|=
949 R200_TEXGEN_INPUT_EYE_NORMAL
<< inputshift
;
950 set_texgen_normal_map_matrix(rmesa
, unit
);
954 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
955 rmesa
->TexGenInputs
|= R200_TEXGEN_INPUT_SPHERE
<< inputshift
;
959 /* Unsupported mode, fallback:
961 /* fprintf(stderr, "fallback unsupported texgen\n"); */
965 rmesa
->TexGenCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
967 if (tmp
!= rmesa
->TexGenEnabled
) {
968 //rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
974 static void disable_tex(GLcontext
* ctx
, int unit
)
976 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
978 #if 0 /* This needs to be redone.. or done elsewhere */
979 if (rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<< unit
)) {
980 /* Texture unit disabled */
981 if (rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
982 /* The old texture is no longer bound to this texture unit.
986 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&=
988 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
991 R300_STATECHANGE(rmesa
, ctx
);
992 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~((R200_TEX_0_ENABLE
|
993 R200_TEX_BLEND_0_ENABLE
) <<
995 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_BLEND_0_ENABLE
;
997 R300_STATECHANGE(rmesa
, tcl
);
998 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &=
1001 if (rmesa
->radeon
.TclFallback
& (RADEON_TCL_FALLBACK_TEXGEN_0
<< unit
)) {
1002 TCL_FALLBACK(ctx
, (RADEON_TCL_FALLBACK_TEXGEN_0
<< unit
),
1006 /* Actually want to keep all units less than max active texture
1007 * enabled, right? Fix this for >2 texunits.
1009 /* FIXME: What should happen here if r300UpdateTextureEnv fails? */
1011 r300UpdateTextureEnv(ctx
, unit
);
1015 R200_TEXGEN_0_INPUT_SHIFT
+ unit
* 4;
1016 GLuint tmp
= rmesa
->TexGenEnabled
;
1018 rmesa
->TexGenEnabled
&=
1019 ~(R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
);
1020 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<< unit
);
1021 rmesa
->TexGenEnabled
&=
1022 ~(R200_TEXGEN_INPUT_MASK
<< inputshift
);
1023 rmesa
->TexGenNeedNormals
[unit
] = 0;
1024 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1025 rmesa
->TexGenInputs
&=
1026 ~(R200_TEXGEN_INPUT_MASK
<< inputshift
);
1028 if (tmp
!= rmesa
->TexGenEnabled
) {
1029 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1030 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1037 static GLboolean
enable_tex_2d(GLcontext
* ctx
, int unit
)
1039 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1040 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1041 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1042 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1044 /* Need to load the 2d images associated with this unit.
1046 if (t
->format
& R200_TXFORMAT_NON_POWER2
) {
1047 t
->format
&= ~R200_TXFORMAT_NON_POWER2
;
1048 t
->base
.dirty_images
[0] = ~0;
1051 ASSERT(tObj
->Target
== GL_TEXTURE_2D
|| tObj
->Target
== GL_TEXTURE_1D
);
1053 if (t
->base
.dirty_images
[0]) {
1054 R300_FIREVERTICES(rmesa
);
1055 r300SetTexImages(rmesa
, tObj
);
1056 r300UploadTexImages(rmesa
, (r300TexObjPtr
) tObj
->DriverData
, 0);
1057 if (!t
->base
.memBlock
)
1064 #if ENABLE_HW_3D_TEXTURE
1065 static GLboolean
enable_tex_3d(GLcontext
* ctx
, int unit
)
1067 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1068 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1069 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1070 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1072 /* Need to load the 3d images associated with this unit.
1074 if (t
->format
& R200_TXFORMAT_NON_POWER2
) {
1075 t
->format
&= ~R200_TXFORMAT_NON_POWER2
;
1076 t
->base
.dirty_images
[0] = ~0;
1079 ASSERT(tObj
->Target
== GL_TEXTURE_3D
);
1081 /* R100 & R200 do not support mipmaps for 3D textures.
1083 if ((tObj
->MinFilter
!= GL_NEAREST
) && (tObj
->MinFilter
!= GL_LINEAR
)) {
1087 if (t
->base
.dirty_images
[0]) {
1088 R300_FIREVERTICES(rmesa
);
1089 r300SetTexImages(rmesa
, tObj
);
1090 r300UploadTexImages(rmesa
, (r300TexObjPtr
) tObj
->DriverData
, 0);
1091 if (!t
->base
.memBlock
)
1099 static GLboolean
enable_tex_cube(GLcontext
* ctx
, int unit
)
1101 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1102 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1103 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1104 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1107 /* Need to load the 2d images associated with this unit.
1109 if (t
->format
& R200_TXFORMAT_NON_POWER2
) {
1110 t
->format
&= ~R200_TXFORMAT_NON_POWER2
;
1111 for (face
= 0; face
< 6; face
++)
1112 t
->base
.dirty_images
[face
] = ~0;
1115 ASSERT(tObj
->Target
== GL_TEXTURE_CUBE_MAP
);
1117 if (t
->base
.dirty_images
[0] || t
->base
.dirty_images
[1] ||
1118 t
->base
.dirty_images
[2] || t
->base
.dirty_images
[3] ||
1119 t
->base
.dirty_images
[4] || t
->base
.dirty_images
[5]) {
1121 R300_FIREVERTICES(rmesa
);
1122 /* layout memory space, once for all faces */
1123 r300SetTexImages(rmesa
, tObj
);
1126 /* upload (per face) */
1127 for (face
= 0; face
< 6; face
++) {
1128 if (t
->base
.dirty_images
[face
]) {
1129 r300UploadTexImages(rmesa
,
1130 (r300TexObjPtr
) tObj
->DriverData
,
1135 if (!t
->base
.memBlock
) {
1136 /* texmem alloc failed, use s/w fallback */
1143 static GLboolean
enable_tex_rect(GLcontext
* ctx
, int unit
)
1145 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1146 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1147 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1148 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1150 if (!(t
->format
& R200_TXFORMAT_NON_POWER2
)) {
1151 t
->format
|= R200_TXFORMAT_NON_POWER2
;
1152 t
->base
.dirty_images
[0] = ~0;
1155 ASSERT(tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
1157 if (t
->base
.dirty_images
[0]) {
1158 R300_FIREVERTICES(rmesa
);
1159 r300SetTexImages(rmesa
, tObj
);
1160 r300UploadTexImages(rmesa
, (r300TexObjPtr
) tObj
->DriverData
, 0);
1161 if (!t
->base
.memBlock
&& !rmesa
->prefer_gart_client_texturing
)
1168 static GLboolean
update_tex_common(GLcontext
* ctx
, int unit
)
1170 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1171 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1172 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1173 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1176 /* Fallback if there's a texture border */
1177 if (tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0)
1180 /* Update state if this is a different texture object to last
1183 if (rmesa
->state
.texture
.unit
[unit
].texobj
!= t
) {
1184 if (rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
1185 /* The old texture is no longer bound to this texture unit.
1189 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&=
1193 rmesa
->state
.texture
.unit
[unit
].texobj
= t
;
1194 t
->base
.bound
|= (1UL << unit
);
1195 t
->dirty_state
|= 1 << unit
;
1196 driUpdateTextureLRU((driTextureObject
*) t
); /* XXX: should be locked! */
1199 #if 0 /* do elsewhere ? */
1204 cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<< unit
))) {
1205 R300_STATECHANGE(rmesa
, ctx
);
1206 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= (R200_TEX_0_ENABLE
|
1207 R200_TEX_BLEND_0_ENABLE
) <<
1210 R300_STATECHANGE(rmesa
, vtx
);
1211 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] |= 4 << (unit
* 3);
1213 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1216 if (t
->dirty_state
& (1 << unit
)) {
1217 import_tex_obj_state(rmesa
, unit
, t
);
1220 if (rmesa
->recheck_texgen
[unit
]) {
1221 GLboolean fallback
= !r300_validate_texgen(ctx
, unit
);
1222 TCL_FALLBACK(ctx
, (RADEON_TCL_FALLBACK_TEXGEN_0
<< unit
),
1224 rmesa
->recheck_texgen
[unit
] = 0;
1225 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1228 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1229 if (rmesa
->state
.texture
.unit
[unit
].format
!= format
||
1230 rmesa
->state
.texture
.unit
[unit
].envMode
!= texUnit
->EnvMode
) {
1231 rmesa
->state
.texture
.unit
[unit
].format
= format
;
1232 rmesa
->state
.texture
.unit
[unit
].envMode
= texUnit
->EnvMode
;
1233 if (!r300UpdateTextureEnv(ctx
, unit
)) {
1239 FALLBACK(&rmesa
->radeon
, RADEON_FALLBACK_BORDER_MODE
, t
->border_fallback
);
1240 return !t
->border_fallback
;
1243 static GLboolean
r300UpdateTextureUnit(GLcontext
* ctx
, int unit
)
1245 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1247 if (texUnit
->_ReallyEnabled
& (TEXTURE_RECT_BIT
)) {
1248 return (enable_tex_rect(ctx
, unit
) &&
1249 update_tex_common(ctx
, unit
));
1250 } else if (texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
)) {
1251 return (enable_tex_2d(ctx
, unit
) &&
1252 update_tex_common(ctx
, unit
));
1254 #if ENABLE_HW_3D_TEXTURE
1255 else if (texUnit
->_ReallyEnabled
& (TEXTURE_3D_BIT
)) {
1256 return (enable_tex_3d(ctx
, unit
) &&
1257 update_tex_common(ctx
, unit
));
1260 else if (texUnit
->_ReallyEnabled
& (TEXTURE_CUBE_BIT
)) {
1261 return (enable_tex_cube(ctx
, unit
) &&
1262 update_tex_common(ctx
, unit
));
1263 } else if (texUnit
->_ReallyEnabled
) {
1266 disable_tex(ctx
, unit
);
1271 void r300UpdateTextureState(GLcontext
* ctx
)
1273 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1278 ok
= (r300UpdateTextureUnit(ctx
, 0) &&
1279 r300UpdateTextureUnit(ctx
, 1) &&
1280 r300UpdateTextureUnit(ctx
, 2) &&
1281 r300UpdateTextureUnit(ctx
, 3) &&
1282 r300UpdateTextureUnit(ctx
, 4) &&
1283 r300UpdateTextureUnit(ctx
, 5) &&
1284 r300UpdateTextureUnit(ctx
, 6) &&
1285 r300UpdateTextureUnit(ctx
, 7)
1288 FALLBACK(&rmesa
->radeon
, RADEON_FALLBACK_TEXTURE
, !ok
);
1290 /* This needs correction, or just be done elsewhere
1291 if (rmesa->radeon.TclFallback)
1292 r300ChooseVertexState(ctx);
1295 #if 0 /* Workaround - disable.. */
1296 if (GET_CHIP(rmesa
->radeon
.radeonScreen
) == RADEON_CHIP_REAL_R200
) {
1298 * T0 hang workaround -------------
1299 * not needed for r200 derivatives?
1301 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_ENABLE_MASK
) ==
1303 && (rmesa
->hw
.tex
[0].
1304 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) >
1305 R200_MIN_FILTER_LINEAR
) {
1307 R300_STATECHANGE(rmesa
, ctx
);
1308 R300_STATECHANGE(rmesa
, tex
[1]);
1309 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_1_ENABLE
;
1310 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &=
1311 ~TEXOBJ_TXFORMAT_MASK
;
1312 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] |= 0x08000000;
1314 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
)
1315 && (rmesa
->hw
.tex
[1].
1316 cmd
[TEX_PP_TXFORMAT
] & 0x08000000)) {
1317 R300_STATECHANGE(rmesa
, tex
[1]);
1318 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &=
1323 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1324 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1325 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1326 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1327 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1328 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1329 R200_MIN_FILTER_LINEAR)) {
1330 R300_STATECHANGE(rmesa, ctx);
1331 R300_STATECHANGE(rmesa, tex[i+1]);
1332 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1333 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1334 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1337 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1338 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1339 R300_STATECHANGE(rmesa, tex[i+1]);
1340 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1346 * Texture cache LRU hang workaround -------------
1347 * not needed for r200 derivatives?
1351 if (((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
)) &&
1352 ((((rmesa
->hw
.tex
[0].
1353 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) & 0x04)
1355 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_2_ENABLE
)
1357 ((((rmesa
->hw
.tex
[2].
1358 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1360 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_4_ENABLE
)
1362 ((((rmesa
->hw
.tex
[4].
1363 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1368 if (((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_1_ENABLE
)) &&
1369 ((((rmesa
->hw
.tex
[1].
1370 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) & 0x04)
1372 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_3_ENABLE
)
1374 ((((rmesa
->hw
.tex
[3].
1375 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1377 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_5_ENABLE
)
1379 ((((rmesa
->hw
.tex
[5].
1380 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1385 if (dbg
!= rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
]) {
1386 R300_STATECHANGE(rmesa
, tam
);
1387 rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
] = dbg
;
1389 printf("TEXCACHE LRU HANG WORKAROUND %x\n",