2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
32 * Keith Whitwell <keith@tungstengraphics.com>
39 #include "texformat.h"
42 #include "r200_context.h"
43 #include "r200_state.h"
44 #include "r200_ioctl.h"
45 #include "r200_swtcl.h"
50 #define R200_TXFORMAT_A8 R200_TXFORMAT_I8
51 #define R200_TXFORMAT_L8 R200_TXFORMAT_I8
52 #define R200_TXFORMAT_AL88 R200_TXFORMAT_AI88
53 #define R200_TXFORMAT_YCBCR R200_TXFORMAT_YVYU422
54 #define R200_TXFORMAT_YCBCR_REV R200_TXFORMAT_VYUY422
55 #define R200_TXFORMAT_RGB_DXT1 R200_TXFORMAT_DXT1
56 #define R200_TXFORMAT_RGBA_DXT1 R200_TXFORMAT_DXT1
57 #define R200_TXFORMAT_RGBA_DXT3 R200_TXFORMAT_DXT23
58 #define R200_TXFORMAT_RGBA_DXT5 R200_TXFORMAT_DXT45
61 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, 0 }
62 #define _COLOR_REV(f) \
63 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f, 0 }
65 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
66 #define _ALPHA_REV(f) \
67 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
69 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, R200_YUV_TO_RGB }
71 [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
72 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
73 && (tx_table_le[f].format != 0xffffffff) )
76 GLuint format
, filter
;
80 [ MESA_FORMAT_RGBA8888
] = { R200_TXFORMAT_ABGR8888
| R200_TXFORMAT_ALPHA_IN_MAP
, 0 },
107 static const struct {
108 GLuint format
, filter
;
113 [ MESA_FORMAT_RGBA8888_REV
] = { R200_TXFORMAT_ABGR8888
| R200_TXFORMAT_ALPHA_IN_MAP
, 0 },
115 _ALPHA_REV(ARGB8888
),
120 _ALPHA_REV(ARGB4444
),
122 _ALPHA_REV(ARGB1555
),
144 * This function computes the number of bytes of storage needed for
145 * the given texture object (all mipmap levels, all cube faces).
146 * The \c image[face][level].x/y/width/height parameters for upload/blitting
147 * are computed here. \c pp_txfilter, \c pp_txformat, etc. will be set here
150 * \param rmesa Context pointer
151 * \param tObj GL texture object whose images are to be posted to
154 static void r200SetTexImages( r200ContextPtr rmesa
,
155 struct gl_texture_object
*tObj
)
157 r200TexObjPtr t
= (r200TexObjPtr
)tObj
->DriverData
;
158 const struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
159 GLint curOffset
, blitWidth
;
162 GLint log2Width
, log2Height
, log2Depth
;
164 const GLubyte littleEndian
= *((const GLubyte
*) &ui
);
166 /* Set the hardware texture format
169 t
->pp_txformat
&= ~(R200_TXFORMAT_FORMAT_MASK
|
170 R200_TXFORMAT_ALPHA_IN_MAP
);
171 t
->pp_txfilter
&= ~R200_YUV_TO_RGB
;
173 if ( VALID_FORMAT( baseImage
->TexFormat
->MesaFormat
) ) {
175 t
->pp_txformat
|= tx_table_le
[ baseImage
->TexFormat
->MesaFormat
].format
;
176 t
->pp_txfilter
|= tx_table_le
[ baseImage
->TexFormat
->MesaFormat
].filter
;
179 t
->pp_txformat
|= tx_table_be
[ baseImage
->TexFormat
->MesaFormat
].format
;
180 t
->pp_txfilter
|= tx_table_be
[ baseImage
->TexFormat
->MesaFormat
].filter
;
184 _mesa_problem(NULL
, "unexpected texture format in %s", __FUNCTION__
);
188 texelBytes
= baseImage
->TexFormat
->TexelBytes
;
190 /* Compute which mipmap levels we really want to send to the hardware.
193 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
194 log2Width
= tObj
->Image
[0][t
->base
.firstLevel
]->WidthLog2
;
195 log2Height
= tObj
->Image
[0][t
->base
.firstLevel
]->HeightLog2
;
196 log2Depth
= tObj
->Image
[0][t
->base
.firstLevel
]->DepthLog2
;
198 numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
200 assert(numLevels
<= RADEON_MAX_TEXTURE_LEVELS
);
202 /* Calculate mipmap offsets and dimensions for blitting (uploading)
203 * The idea is that we lay out the mipmap levels within a block of
204 * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
207 blitWidth
= BLIT_WIDTH_BYTES
;
210 /* figure out if this texture is suitable for tiling. */
212 if (rmesa
->texmicrotile
&& (tObj
->Target
!= GL_TEXTURE_RECTANGLE_NV
) &&
213 /* texrect might be able to use micro tiling too in theory? */
214 (baseImage
->Height
> 1)) {
215 /* allow 32 (bytes) x 1 mip (which will use two times the space
216 the non-tiled version would use) max if base texture is large enough */
217 if ((numLevels
== 1) ||
218 (((baseImage
->Width
* texelBytes
/ baseImage
->Height
) <= 32) &&
219 (baseImage
->Width
* texelBytes
> 64)) ||
220 ((baseImage
->Width
* texelBytes
/ baseImage
->Height
) <= 16)) {
221 t
->tile_bits
|= R200_TXO_MICRO_TILE
;
224 if (tObj
->Target
!= GL_TEXTURE_RECTANGLE_NV
) {
225 /* we can set macro tiling even for small textures, they will be untiled anyway */
226 t
->tile_bits
|= R200_TXO_MACRO_TILE
;
230 for (i
= 0; i
< numLevels
; i
++) {
231 const struct gl_texture_image
*texImage
;
234 texImage
= tObj
->Image
[0][i
+ t
->base
.firstLevel
];
238 /* find image size in bytes */
239 if (texImage
->IsCompressed
) {
240 /* need to calculate the size AFTER padding even though the texture is
241 submitted without padding.
242 Only handle pot textures currently - don't know if npot is even possible,
243 size calculation would certainly need (trivial) adjustments.
244 Align (and later pad) to 32byte, not sure what that 64byte blit width is
246 if ((t
->pp_txformat
& R200_TXFORMAT_FORMAT_MASK
) == R200_TXFORMAT_DXT1
) {
247 /* RGB_DXT1/RGBA_DXT1, 8 bytes per block */
248 if ((texImage
->Width
+ 3) < 8) /* width one block */
249 size
= texImage
->CompressedSize
* 4;
250 else if ((texImage
->Width
+ 3) < 16)
251 size
= texImage
->CompressedSize
* 2;
252 else size
= texImage
->CompressedSize
;
254 else /* DXT3/5, 16 bytes per block */
255 if ((texImage
->Width
+ 3) < 8)
256 size
= texImage
->CompressedSize
* 2;
257 else size
= texImage
->CompressedSize
;
259 else if (tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
) {
260 size
= ((texImage
->Width
* texelBytes
+ 63) & ~63) * texImage
->Height
;
262 else if (t
->tile_bits
& R200_TXO_MICRO_TILE
) {
263 /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
264 though the actual offset may be different (if texture is less than
265 32 bytes width) to the untiled case */
266 int w
= (texImage
->Width
* texelBytes
* 2 + 31) & ~31;
267 size
= (w
* ((texImage
->Height
+ 1) / 2)) * texImage
->Depth
;
268 blitWidth
= MAX2(texImage
->Width
, 64 / texelBytes
);
271 int w
= (texImage
->Width
* texelBytes
+ 31) & ~31;
272 size
= w
* texImage
->Height
* texImage
->Depth
;
273 blitWidth
= MAX2(texImage
->Width
, 64 / texelBytes
);
277 /* Align to 32-byte offset. It is faster to do this unconditionally
278 * (no branch penalty).
281 curOffset
= (curOffset
+ 0x1f) & ~0x1f;
284 t
->image
[0][i
].x
= curOffset
; /* fix x and y coords up later together with offset */
285 t
->image
[0][i
].y
= 0;
286 t
->image
[0][i
].width
= MIN2(size
/ texelBytes
, blitWidth
);
287 t
->image
[0][i
].height
= (size
/ texelBytes
) / t
->image
[0][i
].width
;
290 t
->image
[0][i
].x
= curOffset
% BLIT_WIDTH_BYTES
;
291 t
->image
[0][i
].y
= curOffset
/ BLIT_WIDTH_BYTES
;
292 t
->image
[0][i
].width
= MIN2(size
, BLIT_WIDTH_BYTES
);
293 t
->image
[0][i
].height
= size
/ t
->image
[0][i
].width
;
297 /* for debugging only and only applicable to non-rectangle targets */
298 assert(size
% t
->image
[0][i
].width
== 0);
299 assert(t
->image
[0][i
].x
== 0
300 || (size
< BLIT_WIDTH_BYTES
&& t
->image
[0][i
].height
== 1));
305 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
306 i
, texImage
->Width
, texImage
->Height
,
307 t
->image
[0][i
].x
, t
->image
[0][i
].y
,
308 t
->image
[0][i
].width
, t
->image
[0][i
].height
, size
, curOffset
);
314 /* Align the total size of texture memory block.
316 t
->base
.totalSize
= (curOffset
+ RADEON_OFFSET_MASK
) & ~RADEON_OFFSET_MASK
;
318 /* Setup remaining cube face blits, if needed */
319 if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
320 const GLuint faceSize
= t
->base
.totalSize
;
322 /* reuse face 0 x/y/width/height - just update the offset when uploading */
323 for (face
= 1; face
< 6; face
++) {
324 for (i
= 0; i
< numLevels
; i
++) {
325 t
->image
[face
][i
].x
= t
->image
[0][i
].x
;
326 t
->image
[face
][i
].y
= t
->image
[0][i
].y
;
327 t
->image
[face
][i
].width
= t
->image
[0][i
].width
;
328 t
->image
[face
][i
].height
= t
->image
[0][i
].height
;
331 t
->base
.totalSize
= 6 * faceSize
; /* total texmem needed */
337 t
->pp_txfilter
&= ~R200_MAX_MIP_LEVEL_MASK
;
338 t
->pp_txfilter
|= (numLevels
- 1) << R200_MAX_MIP_LEVEL_SHIFT
;
340 t
->pp_txformat
&= ~(R200_TXFORMAT_WIDTH_MASK
|
341 R200_TXFORMAT_HEIGHT_MASK
|
342 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
343 R200_TXFORMAT_F5_WIDTH_MASK
|
344 R200_TXFORMAT_F5_HEIGHT_MASK
);
345 t
->pp_txformat
|= ((log2Width
<< R200_TXFORMAT_WIDTH_SHIFT
) |
346 (log2Height
<< R200_TXFORMAT_HEIGHT_SHIFT
));
348 t
->pp_txformat_x
&= ~(R200_DEPTH_LOG2_MASK
| R200_TEXCOORD_MASK
);
349 if (tObj
->Target
== GL_TEXTURE_3D
) {
350 t
->pp_txformat_x
|= (log2Depth
<< R200_DEPTH_LOG2_SHIFT
);
351 t
->pp_txformat_x
|= R200_TEXCOORD_VOLUME
;
353 else if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
354 ASSERT(log2Width
== log2Height
);
355 t
->pp_txformat
|= ((log2Width
<< R200_TXFORMAT_F5_WIDTH_SHIFT
) |
356 (log2Height
<< R200_TXFORMAT_F5_HEIGHT_SHIFT
) |
357 /* don't think we need this bit, if it exists at all - fglrx does not set it */
358 (R200_TXFORMAT_CUBIC_MAP_ENABLE
));
359 t
->pp_txformat_x
|= R200_TEXCOORD_CUBIC_ENV
;
360 t
->pp_cubic_faces
= ((log2Width
<< R200_FACE_WIDTH_1_SHIFT
) |
361 (log2Height
<< R200_FACE_HEIGHT_1_SHIFT
) |
362 (log2Width
<< R200_FACE_WIDTH_2_SHIFT
) |
363 (log2Height
<< R200_FACE_HEIGHT_2_SHIFT
) |
364 (log2Width
<< R200_FACE_WIDTH_3_SHIFT
) |
365 (log2Height
<< R200_FACE_HEIGHT_3_SHIFT
) |
366 (log2Width
<< R200_FACE_WIDTH_4_SHIFT
) |
367 (log2Height
<< R200_FACE_HEIGHT_4_SHIFT
));
370 /* If we don't in fact send enough texture coordinates, q will be 1,
371 * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
373 t
->pp_txformat_x
|= R200_TEXCOORD_PROJ
;
376 t
->pp_txsize
= (((tObj
->Image
[0][t
->base
.firstLevel
]->Width
- 1) << 0) |
377 ((tObj
->Image
[0][t
->base
.firstLevel
]->Height
- 1) << 16));
379 /* Only need to round to nearest 32 for textures, but the blitter
380 * requires 64-byte aligned pitches, and we may/may not need the
381 * blitter. NPOT only!
383 if (baseImage
->IsCompressed
)
384 t
->pp_txpitch
= (tObj
->Image
[0][t
->base
.firstLevel
]->Width
+ 63) & ~(63);
386 t
->pp_txpitch
= ((tObj
->Image
[0][t
->base
.firstLevel
]->Width
* texelBytes
) + 63) & ~(63);
389 t
->dirty_state
= TEX_ALL
;
391 /* FYI: r200UploadTexImages( rmesa, t ) used to be called here */
396 /* ================================================================
397 * Texture combine functions
400 /* GL_ARB_texture_env_combine support
403 /* The color tables have combine functions for GL_SRC_COLOR,
404 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
406 static GLuint r200_register_color
[][R200_MAX_TEXTURE_UNITS
] =
409 R200_TXC_ARG_A_R0_COLOR
,
410 R200_TXC_ARG_A_R1_COLOR
,
411 R200_TXC_ARG_A_R2_COLOR
,
412 R200_TXC_ARG_A_R3_COLOR
,
413 R200_TXC_ARG_A_R4_COLOR
,
414 R200_TXC_ARG_A_R5_COLOR
417 R200_TXC_ARG_A_R0_COLOR
| R200_TXC_COMP_ARG_A
,
418 R200_TXC_ARG_A_R1_COLOR
| R200_TXC_COMP_ARG_A
,
419 R200_TXC_ARG_A_R2_COLOR
| R200_TXC_COMP_ARG_A
,
420 R200_TXC_ARG_A_R3_COLOR
| R200_TXC_COMP_ARG_A
,
421 R200_TXC_ARG_A_R4_COLOR
| R200_TXC_COMP_ARG_A
,
422 R200_TXC_ARG_A_R5_COLOR
| R200_TXC_COMP_ARG_A
425 R200_TXC_ARG_A_R0_ALPHA
,
426 R200_TXC_ARG_A_R1_ALPHA
,
427 R200_TXC_ARG_A_R2_ALPHA
,
428 R200_TXC_ARG_A_R3_ALPHA
,
429 R200_TXC_ARG_A_R4_ALPHA
,
430 R200_TXC_ARG_A_R5_ALPHA
433 R200_TXC_ARG_A_R0_ALPHA
| R200_TXC_COMP_ARG_A
,
434 R200_TXC_ARG_A_R1_ALPHA
| R200_TXC_COMP_ARG_A
,
435 R200_TXC_ARG_A_R2_ALPHA
| R200_TXC_COMP_ARG_A
,
436 R200_TXC_ARG_A_R3_ALPHA
| R200_TXC_COMP_ARG_A
,
437 R200_TXC_ARG_A_R4_ALPHA
| R200_TXC_COMP_ARG_A
,
438 R200_TXC_ARG_A_R5_ALPHA
| R200_TXC_COMP_ARG_A
442 static GLuint r200_tfactor_color
[] =
444 R200_TXC_ARG_A_TFACTOR_COLOR
,
445 R200_TXC_ARG_A_TFACTOR_COLOR
| R200_TXC_COMP_ARG_A
,
446 R200_TXC_ARG_A_TFACTOR_ALPHA
,
447 R200_TXC_ARG_A_TFACTOR_ALPHA
| R200_TXC_COMP_ARG_A
450 static GLuint r200_tfactor1_color
[] =
452 R200_TXC_ARG_A_TFACTOR1_COLOR
,
453 R200_TXC_ARG_A_TFACTOR1_COLOR
| R200_TXC_COMP_ARG_A
,
454 R200_TXC_ARG_A_TFACTOR1_ALPHA
,
455 R200_TXC_ARG_A_TFACTOR1_ALPHA
| R200_TXC_COMP_ARG_A
458 static GLuint r200_primary_color
[] =
460 R200_TXC_ARG_A_DIFFUSE_COLOR
,
461 R200_TXC_ARG_A_DIFFUSE_COLOR
| R200_TXC_COMP_ARG_A
,
462 R200_TXC_ARG_A_DIFFUSE_ALPHA
,
463 R200_TXC_ARG_A_DIFFUSE_ALPHA
| R200_TXC_COMP_ARG_A
466 /* GL_ZERO table - indices 0-3
467 * GL_ONE table - indices 1-4
469 static GLuint r200_zero_color
[] =
472 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
474 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
478 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
480 static GLuint r200_register_alpha
[][R200_MAX_TEXTURE_UNITS
] =
483 R200_TXA_ARG_A_R0_ALPHA
,
484 R200_TXA_ARG_A_R1_ALPHA
,
485 R200_TXA_ARG_A_R2_ALPHA
,
486 R200_TXA_ARG_A_R3_ALPHA
,
487 R200_TXA_ARG_A_R4_ALPHA
,
488 R200_TXA_ARG_A_R5_ALPHA
491 R200_TXA_ARG_A_R0_ALPHA
| R200_TXA_COMP_ARG_A
,
492 R200_TXA_ARG_A_R1_ALPHA
| R200_TXA_COMP_ARG_A
,
493 R200_TXA_ARG_A_R2_ALPHA
| R200_TXA_COMP_ARG_A
,
494 R200_TXA_ARG_A_R3_ALPHA
| R200_TXA_COMP_ARG_A
,
495 R200_TXA_ARG_A_R4_ALPHA
| R200_TXA_COMP_ARG_A
,
496 R200_TXA_ARG_A_R5_ALPHA
| R200_TXA_COMP_ARG_A
500 static GLuint r200_tfactor_alpha
[] =
502 R200_TXA_ARG_A_TFACTOR_ALPHA
,
503 R200_TXA_ARG_A_TFACTOR_ALPHA
| R200_TXA_COMP_ARG_A
506 static GLuint r200_tfactor1_alpha
[] =
508 R200_TXA_ARG_A_TFACTOR1_ALPHA
,
509 R200_TXA_ARG_A_TFACTOR1_ALPHA
| R200_TXA_COMP_ARG_A
512 static GLuint r200_primary_alpha
[] =
514 R200_TXA_ARG_A_DIFFUSE_ALPHA
,
515 R200_TXA_ARG_A_DIFFUSE_ALPHA
| R200_TXA_COMP_ARG_A
518 /* GL_ZERO table - indices 0-1
519 * GL_ONE table - indices 1-2
521 static GLuint r200_zero_alpha
[] =
524 R200_TXA_ARG_A_ZERO
| R200_TXA_COMP_ARG_A
,
529 /* Extract the arg from slot A, shift it into the correct argument slot
530 * and set the corresponding complement bit.
532 #define R200_COLOR_ARG( n, arg ) \
535 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
536 << R200_TXC_ARG_##arg##_SHIFT); \
538 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
539 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
542 #define R200_ALPHA_ARG( n, arg ) \
545 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
546 << R200_TXA_ARG_##arg##_SHIFT); \
548 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
549 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
553 /* ================================================================
554 * Texture unit state management
557 static GLboolean
r200UpdateTextureEnv( GLcontext
*ctx
, int unit
, int slot
, GLuint replaceargs
)
559 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
560 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
561 GLuint color_combine
, alpha_combine
;
562 GLuint color_scale
= rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] &
563 ~(R200_TXC_SCALE_MASK
| R200_TXC_OUTPUT_REG_MASK
| R200_TXC_TFACTOR_SEL_MASK
|
564 R200_TXC_TFACTOR1_SEL_MASK
);
565 GLuint alpha_scale
= rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] &
566 ~(R200_TXA_DOT_ALPHA
| R200_TXA_SCALE_MASK
| R200_TXA_OUTPUT_REG_MASK
|
567 R200_TXA_TFACTOR_SEL_MASK
| R200_TXA_TFACTOR1_SEL_MASK
);
569 /* texUnit->_Current can be NULL if and only if the texture unit is
570 * not actually enabled.
572 assert( (texUnit
->_ReallyEnabled
== 0)
573 || (texUnit
->_Current
!= NULL
) );
575 if ( R200_DEBUG
& DEBUG_TEXTURE
) {
576 fprintf( stderr
, "%s( %p, %d )\n", __FUNCTION__
, (void *)ctx
, unit
);
579 /* Set the texture environment state. Isn't this nice and clean?
580 * The chip will automagically set the texture alpha to 0xff when
581 * the texture format does not include an alpha component. This
582 * reduces the amount of special-casing we have to do, alpha-only
583 * textures being a notable exception.
586 color_scale
|= ((rmesa
->state
.texture
.unit
[unit
].outputreg
+ 1) << R200_TXC_OUTPUT_REG_SHIFT
) |
587 (unit
<< R200_TXC_TFACTOR_SEL_SHIFT
) |
588 (replaceargs
<< R200_TXC_TFACTOR1_SEL_SHIFT
);
589 alpha_scale
|= ((rmesa
->state
.texture
.unit
[unit
].outputreg
+ 1) << R200_TXA_OUTPUT_REG_SHIFT
) |
590 (unit
<< R200_TXA_TFACTOR_SEL_SHIFT
) |
591 (replaceargs
<< R200_TXA_TFACTOR1_SEL_SHIFT
);
593 if ( !texUnit
->_ReallyEnabled
) {
595 color_combine
= R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
596 | R200_TXC_ARG_C_DIFFUSE_COLOR
| R200_TXC_OP_MADD
;
597 alpha_combine
= R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
598 | R200_TXA_ARG_C_DIFFUSE_ALPHA
| R200_TXA_OP_MADD
;
601 GLuint color_arg
[3], alpha_arg
[3];
603 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
604 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
605 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
606 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
609 const GLint replaceoprgb
=
610 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->OperandRGB
[0] - GL_SRC_COLOR
;
611 const GLint replaceopa
=
612 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->OperandA
[0] - GL_SRC_ALPHA
;
615 * Extract the color and alpha combine function arguments.
617 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
618 GLint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
] - GL_SRC_COLOR
;
619 const GLint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
624 color_arg
[i
] = r200_register_color
[op
][unit
];
627 color_arg
[i
] = r200_tfactor_color
[op
];
629 case GL_PRIMARY_COLOR
:
630 color_arg
[i
] = r200_primary_color
[op
];
633 if (replaceargs
!= unit
) {
634 const GLint srcRGBreplace
=
635 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->SourceRGB
[0];
637 op
= op
^ replaceopa
;
640 op
= op
^ replaceoprgb
;
642 switch (srcRGBreplace
) {
644 color_arg
[i
] = r200_register_color
[op
][replaceargs
];
647 color_arg
[i
] = r200_tfactor1_color
[op
];
649 case GL_PRIMARY_COLOR
:
650 color_arg
[i
] = r200_primary_color
[op
];
654 color_arg
[i
] = r200_primary_color
[op
];
656 color_arg
[i
] = r200_register_color
[op
]
657 [rmesa
->state
.texture
.unit
[replaceargs
- 1].outputreg
];
660 color_arg
[i
] = r200_zero_color
[op
];
663 color_arg
[i
] = r200_zero_color
[op
+1];
671 color_arg
[i
] = r200_register_color
[op
][srcRGBreplace
- GL_TEXTURE0
];
679 color_arg
[i
] = r200_primary_color
[op
];
681 color_arg
[i
] = r200_register_color
[op
]
682 [rmesa
->state
.texture
.unit
[unit
- 1].outputreg
];
686 color_arg
[i
] = r200_zero_color
[op
];
689 color_arg
[i
] = r200_zero_color
[op
+1];
697 color_arg
[i
] = r200_register_color
[op
][srcRGBi
- GL_TEXTURE0
];
704 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
705 GLint op
= texUnit
->_CurrentCombine
->OperandA
[i
] - GL_SRC_ALPHA
;
706 const GLint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
711 alpha_arg
[i
] = r200_register_alpha
[op
][unit
];
714 alpha_arg
[i
] = r200_tfactor_alpha
[op
];
716 case GL_PRIMARY_COLOR
:
717 alpha_arg
[i
] = r200_primary_alpha
[op
];
720 if (replaceargs
!= unit
) {
721 const GLint srcAreplace
=
722 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->SourceA
[0];
723 op
= op
^ replaceopa
;
724 switch (srcAreplace
) {
726 alpha_arg
[i
] = r200_register_alpha
[op
][replaceargs
];
729 alpha_arg
[i
] = r200_tfactor1_alpha
[op
];
731 case GL_PRIMARY_COLOR
:
732 alpha_arg
[i
] = r200_primary_alpha
[op
];
736 alpha_arg
[i
] = r200_primary_alpha
[op
];
738 alpha_arg
[i
] = r200_register_alpha
[op
]
739 [rmesa
->state
.texture
.unit
[replaceargs
- 1].outputreg
];
742 alpha_arg
[i
] = r200_zero_alpha
[op
];
745 alpha_arg
[i
] = r200_zero_alpha
[op
+1];
753 alpha_arg
[i
] = r200_register_alpha
[op
][srcAreplace
- GL_TEXTURE0
];
761 alpha_arg
[i
] = r200_primary_alpha
[op
];
763 alpha_arg
[i
] = r200_register_alpha
[op
]
764 [rmesa
->state
.texture
.unit
[unit
- 1].outputreg
];
768 alpha_arg
[i
] = r200_zero_alpha
[op
];
771 alpha_arg
[i
] = r200_zero_alpha
[op
+1];
779 alpha_arg
[i
] = r200_register_alpha
[op
][srcAi
- GL_TEXTURE0
];
787 * Build up the color and alpha combine functions.
789 switch ( texUnit
->_CurrentCombine
->ModeRGB
) {
791 color_combine
= (R200_TXC_ARG_A_ZERO
|
792 R200_TXC_ARG_B_ZERO
|
794 R200_COLOR_ARG( 0, C
);
797 color_combine
= (R200_TXC_ARG_C_ZERO
|
799 R200_COLOR_ARG( 0, A
);
800 R200_COLOR_ARG( 1, B
);
803 color_combine
= (R200_TXC_ARG_B_ZERO
|
804 R200_TXC_COMP_ARG_B
|
806 R200_COLOR_ARG( 0, A
);
807 R200_COLOR_ARG( 1, C
);
810 color_combine
= (R200_TXC_ARG_B_ZERO
|
811 R200_TXC_COMP_ARG_B
|
812 R200_TXC_BIAS_ARG_C
| /* new */
813 R200_TXC_OP_MADD
); /* was ADDSIGNED */
814 R200_COLOR_ARG( 0, A
);
815 R200_COLOR_ARG( 1, C
);
818 color_combine
= (R200_TXC_ARG_B_ZERO
|
819 R200_TXC_COMP_ARG_B
|
822 R200_COLOR_ARG( 0, A
);
823 R200_COLOR_ARG( 1, C
);
826 color_combine
= (R200_TXC_OP_LERP
);
827 R200_COLOR_ARG( 0, B
);
828 R200_COLOR_ARG( 1, A
);
829 R200_COLOR_ARG( 2, C
);
832 case GL_DOT3_RGB_EXT
:
833 case GL_DOT3_RGBA_EXT
:
834 /* The EXT version of the DOT3 extension does not support the
835 * scale factor, but the ARB version (and the version in OpenGL
843 /* DOT3 works differently on R200 than on R100. On R100, just
844 * setting the DOT3 mode did everything for you. On R200, the
845 * driver has to enable the biasing and scale in the inputs to
846 * put them in the proper [-1,1] range. This is what the 4x and
847 * the -0.5 in the DOT3 spec do. The post-scale is then set
851 color_combine
= (R200_TXC_ARG_C_ZERO
|
853 R200_TXC_BIAS_ARG_A
|
854 R200_TXC_BIAS_ARG_B
|
855 R200_TXC_SCALE_ARG_A
|
856 R200_TXC_SCALE_ARG_B
);
857 R200_COLOR_ARG( 0, A
);
858 R200_COLOR_ARG( 1, B
);
861 case GL_MODULATE_ADD_ATI
:
862 color_combine
= (R200_TXC_OP_MADD
);
863 R200_COLOR_ARG( 0, A
);
864 R200_COLOR_ARG( 1, C
);
865 R200_COLOR_ARG( 2, B
);
867 case GL_MODULATE_SIGNED_ADD_ATI
:
868 color_combine
= (R200_TXC_BIAS_ARG_C
| /* new */
869 R200_TXC_OP_MADD
); /* was ADDSIGNED */
870 R200_COLOR_ARG( 0, A
);
871 R200_COLOR_ARG( 1, C
);
872 R200_COLOR_ARG( 2, B
);
874 case GL_MODULATE_SUBTRACT_ATI
:
875 color_combine
= (R200_TXC_NEG_ARG_C
|
877 R200_COLOR_ARG( 0, A
);
878 R200_COLOR_ARG( 1, C
);
879 R200_COLOR_ARG( 2, B
);
885 switch ( texUnit
->_CurrentCombine
->ModeA
) {
887 alpha_combine
= (R200_TXA_ARG_A_ZERO
|
888 R200_TXA_ARG_B_ZERO
|
890 R200_ALPHA_ARG( 0, C
);
893 alpha_combine
= (R200_TXA_ARG_C_ZERO
|
895 R200_ALPHA_ARG( 0, A
);
896 R200_ALPHA_ARG( 1, B
);
899 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
900 R200_TXA_COMP_ARG_B
|
902 R200_ALPHA_ARG( 0, A
);
903 R200_ALPHA_ARG( 1, C
);
906 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
907 R200_TXA_COMP_ARG_B
|
908 R200_TXA_BIAS_ARG_C
| /* new */
909 R200_TXA_OP_MADD
); /* was ADDSIGNED */
910 R200_ALPHA_ARG( 0, A
);
911 R200_ALPHA_ARG( 1, C
);
914 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
915 R200_TXA_COMP_ARG_B
|
918 R200_ALPHA_ARG( 0, A
);
919 R200_ALPHA_ARG( 1, C
);
922 alpha_combine
= (R200_TXA_OP_LERP
);
923 R200_ALPHA_ARG( 0, B
);
924 R200_ALPHA_ARG( 1, A
);
925 R200_ALPHA_ARG( 2, C
);
928 case GL_MODULATE_ADD_ATI
:
929 alpha_combine
= (R200_TXA_OP_MADD
);
930 R200_ALPHA_ARG( 0, A
);
931 R200_ALPHA_ARG( 1, C
);
932 R200_ALPHA_ARG( 2, B
);
934 case GL_MODULATE_SIGNED_ADD_ATI
:
935 alpha_combine
= (R200_TXA_BIAS_ARG_C
| /* new */
936 R200_TXA_OP_MADD
); /* was ADDSIGNED */
937 R200_ALPHA_ARG( 0, A
);
938 R200_ALPHA_ARG( 1, C
);
939 R200_ALPHA_ARG( 2, B
);
941 case GL_MODULATE_SUBTRACT_ATI
:
942 alpha_combine
= (R200_TXA_NEG_ARG_C
|
944 R200_ALPHA_ARG( 0, A
);
945 R200_ALPHA_ARG( 1, C
);
946 R200_ALPHA_ARG( 2, B
);
952 if ( (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
953 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ) {
954 alpha_scale
|= R200_TXA_DOT_ALPHA
;
959 * Apply the scale factor.
961 color_scale
|= (RGBshift
<< R200_TXC_SCALE_SHIFT
);
962 alpha_scale
|= (Ashift
<< R200_TXA_SCALE_SHIFT
);
968 if ( rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND
] != color_combine
||
969 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND
] != alpha_combine
||
970 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] != color_scale
||
971 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] != alpha_scale
) {
972 R200_STATECHANGE( rmesa
, pix
[slot
] );
973 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND
] = color_combine
;
974 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND
] = alpha_combine
;
975 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] = color_scale
;
976 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] = alpha_scale
;
985 static GLboolean
r200UpdateAllTexEnv( GLcontext
*ctx
)
987 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
988 GLint i
, j
, currslot
;
989 GLint maxunitused
= -1;
990 GLboolean texregfree
[6] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
991 GLubyte stageref
[7] = {0, 0, 0, 0, 0, 0, 0};
992 GLint nextunit
[R200_MAX_TEXTURE_UNITS
] = {0, 0, 0, 0, 0, 0};
993 GLint currentnext
= -1;
996 /* find highest used unit */
997 for ( j
= 0; j
< R200_MAX_TEXTURE_UNITS
; j
++) {
998 if (ctx
->Texture
.Unit
[j
]._ReallyEnabled
) {
1002 stageref
[maxunitused
+ 1] = REF_COLOR
| REF_ALPHA
;
1004 for ( j
= maxunitused
; j
>= 0; j
-- ) {
1005 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[j
];
1007 rmesa
->state
.texture
.unit
[j
].outputreg
= -1;
1009 if (stageref
[j
+ 1]) {
1011 /* use the lowest available reg. That gets us automatically reg0 for the last stage.
1012 need this even for disabled units, as it may get referenced due to the replace
1014 for ( i
= 0 ; i
< R200_MAX_TEXTURE_UNITS
; i
++ ) {
1015 if (texregfree
[i
]) {
1016 rmesa
->state
.texture
.unit
[j
].outputreg
= i
;
1020 if (rmesa
->state
.texture
.unit
[j
].outputreg
== -1) {
1021 /* no more free regs we can use. Need a fallback :-( */
1025 nextunit
[j
] = currentnext
;
1027 if (!texUnit
->_ReallyEnabled
) {
1028 /* the not enabled stages are referenced "indirectly",
1029 must not cut off the lower stages */
1030 stageref
[j
] = REF_COLOR
| REF_ALPHA
;
1035 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
1036 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
1037 const GLboolean isdot3rgba
= (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ||
1038 (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
);
1041 /* check if we need the color part, special case for dot3_rgba
1042 as if only the alpha part is referenced later on it still is using the color part */
1043 if ((stageref
[j
+ 1] & REF_COLOR
) || isdot3rgba
) {
1044 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
1045 const GLuint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
1046 const GLuint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
];
1047 switch ( srcRGBi
) {
1049 /* op 0/1 are referencing color, op 2/3 alpha */
1050 stageref
[j
] |= (op
>> 1) + 1;
1053 texregfree
[j
] = GL_FALSE
;
1061 texregfree
[srcRGBi
- GL_TEXTURE0
] = GL_FALSE
;
1063 default: /* don't care about other sources here */
1069 /* alpha args are ignored for dot3_rgba */
1070 if ((stageref
[j
+ 1] & REF_ALPHA
) && !isdot3rgba
) {
1072 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
1073 const GLuint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
1076 stageref
[j
] |= REF_ALPHA
;
1079 texregfree
[j
] = GL_FALSE
;
1087 texregfree
[srcAi
- GL_TEXTURE0
] = GL_FALSE
;
1089 default: /* don't care about other sources here */
1097 /* don't enable texture sampling for units if the result is not used */
1098 for (i
= 0; i
< R200_MAX_TEXTURE_UNITS
; i
++) {
1099 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
&& !texregfree
[i
])
1100 rmesa
->state
.texture
.unit
[i
].unitneeded
= ctx
->Texture
.Unit
[i
]._ReallyEnabled
;
1101 else rmesa
->state
.texture
.unit
[i
].unitneeded
= 0;
1106 rmesa
->state
.envneeded
= 1;
1109 while ((i
<= maxunitused
) && (i
>= 0)) {
1110 /* only output instruction if the results are referenced */
1111 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
&& stageref
[i
+1]) {
1112 GLuint replaceunit
= i
;
1113 /* try to optimize GL_REPLACE away (only one level deep though) */
1114 if ( (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ModeRGB
== GL_REPLACE
) &&
1115 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ModeA
== GL_REPLACE
) &&
1116 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ScaleShiftRGB
== 0) &&
1117 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ScaleShiftA
== 0) &&
1118 (nextunit
[i
] > 0) ) {
1119 /* yippie! can optimize it away! */
1124 /* need env instruction slot */
1125 rmesa
->state
.envneeded
|= 1 << currslot
;
1126 ok
= r200UpdateTextureEnv( ctx
, i
, currslot
, replaceunit
);
1127 if (!ok
) return GL_FALSE
;
1133 if (currslot
== 0) {
1134 /* need one stage at least */
1135 rmesa
->state
.texture
.unit
[0].outputreg
= 0;
1136 ok
= r200UpdateTextureEnv( ctx
, 0, 0, 0 );
1139 R200_STATECHANGE( rmesa
, ctx
);
1140 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~(R200_TEX_BLEND_ENABLE_MASK
| R200_MULTI_PASS_ENABLE
);
1141 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= rmesa
->state
.envneeded
<< R200_TEX_BLEND_0_ENABLE_SHIFT
;
1150 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
1151 R200_MIN_FILTER_MASK | \
1152 R200_MAG_FILTER_MASK | \
1153 R200_MAX_ANISO_MASK | \
1155 R200_YUV_TEMPERATURE_MASK | \
1156 R200_CLAMP_S_MASK | \
1157 R200_CLAMP_T_MASK | \
1158 R200_BORDER_MODE_D3D )
1160 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
1161 R200_TXFORMAT_HEIGHT_MASK | \
1162 R200_TXFORMAT_FORMAT_MASK | \
1163 R200_TXFORMAT_F5_WIDTH_MASK | \
1164 R200_TXFORMAT_F5_HEIGHT_MASK | \
1165 R200_TXFORMAT_ALPHA_IN_MAP | \
1166 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
1167 R200_TXFORMAT_NON_POWER2)
1169 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
1170 R200_TEXCOORD_MASK | \
1171 R200_CLAMP_Q_MASK | \
1172 R200_VOLUME_FILTER_MASK)
1175 static void import_tex_obj_state( r200ContextPtr rmesa
,
1177 r200TexObjPtr texobj
)
1179 /* do not use RADEON_DB_STATE to avoid stale texture caches */
1180 int *cmd
= &rmesa
->hw
.tex
[unit
].cmd
[TEX_CMD_0
];
1182 R200_STATECHANGE( rmesa
, tex
[unit
] );
1184 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
1185 cmd
[TEX_PP_TXFILTER
] |= texobj
->pp_txfilter
& TEXOBJ_TXFILTER_MASK
;
1186 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1187 cmd
[TEX_PP_TXFORMAT
] |= texobj
->pp_txformat
& TEXOBJ_TXFORMAT_MASK
;
1188 cmd
[TEX_PP_TXFORMAT_X
] &= ~TEXOBJ_TXFORMAT_X_MASK
;
1189 cmd
[TEX_PP_TXFORMAT_X
] |= texobj
->pp_txformat_x
& TEXOBJ_TXFORMAT_X_MASK
;
1190 cmd
[TEX_PP_TXSIZE
] = texobj
->pp_txsize
; /* NPOT only! */
1191 cmd
[TEX_PP_TXPITCH
] = texobj
->pp_txpitch
; /* NPOT only! */
1192 cmd
[TEX_PP_BORDER_COLOR
] = texobj
->pp_border_color
;
1193 if (rmesa
->r200Screen
->drmSupportsFragShader
) {
1194 cmd
[TEX_PP_TXOFFSET_NEWDRM
] = texobj
->pp_txoffset
;
1197 cmd
[TEX_PP_TXOFFSET_OLDDRM
] = texobj
->pp_txoffset
;
1200 if (texobj
->base
.tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
1201 int *cube_cmd
= &rmesa
->hw
.cube
[unit
].cmd
[CUBE_CMD_0
];
1202 GLuint bytesPerFace
= texobj
->base
.totalSize
/ 6;
1203 ASSERT(texobj
->base
.totalSize
% 6 == 0);
1205 R200_STATECHANGE( rmesa
, cube
[unit
] );
1206 cube_cmd
[CUBE_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
1207 if (rmesa
->r200Screen
->drmSupportsFragShader
) {
1208 /* that value is submitted twice. could change cube atom
1209 to not include that command when new drm is used */
1210 cmd
[TEX_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
1212 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F1
] = texobj
->pp_txoffset
+ 1 * bytesPerFace
;
1213 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F2
] = texobj
->pp_txoffset
+ 2 * bytesPerFace
;
1214 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F3
] = texobj
->pp_txoffset
+ 3 * bytesPerFace
;
1215 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F4
] = texobj
->pp_txoffset
+ 4 * bytesPerFace
;
1216 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F5
] = texobj
->pp_txoffset
+ 5 * bytesPerFace
;
1219 texobj
->dirty_state
&= ~(1<<unit
);
1223 static void set_texgen_matrix( r200ContextPtr rmesa
,
1225 const GLfloat
*s_plane
,
1226 const GLfloat
*t_plane
,
1227 const GLfloat
*r_plane
,
1228 const GLfloat
*q_plane
)
1252 _math_matrix_loadf( &(rmesa
->TexGenMatrix
[unit
]), m
);
1253 _math_matrix_analyse( &(rmesa
->TexGenMatrix
[unit
]) );
1254 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<<unit
;
1258 static GLuint
r200_need_dis_texgen(const GLbitfield texGenEnabled
,
1259 const GLfloat
*planeS
,
1260 const GLfloat
*planeT
,
1261 const GLfloat
*planeR
,
1262 const GLfloat
*planeQ
)
1264 GLuint needtgenable
= 0;
1266 if (!(texGenEnabled
& S_BIT
)) {
1267 if (((texGenEnabled
& T_BIT
) && planeT
[0] != 0.0) ||
1268 ((texGenEnabled
& R_BIT
) && planeR
[0] != 0.0) ||
1269 ((texGenEnabled
& Q_BIT
) && planeQ
[0] != 0.0)) {
1270 needtgenable
|= S_BIT
;
1273 if (!(texGenEnabled
& T_BIT
)) {
1274 if (((texGenEnabled
& S_BIT
) && planeS
[1] != 0.0) ||
1275 ((texGenEnabled
& R_BIT
) && planeR
[1] != 0.0) ||
1276 ((texGenEnabled
& Q_BIT
) && planeQ
[1] != 0.0)) {
1277 needtgenable
|= T_BIT
;
1280 if (!(texGenEnabled
& R_BIT
)) {
1281 if (((texGenEnabled
& S_BIT
) && planeS
[2] != 0.0) ||
1282 ((texGenEnabled
& T_BIT
) && planeT
[2] != 0.0) ||
1283 ((texGenEnabled
& Q_BIT
) && planeQ
[2] != 0.0)) {
1284 needtgenable
|= R_BIT
;
1287 if (!(texGenEnabled
& Q_BIT
)) {
1288 if (((texGenEnabled
& S_BIT
) && planeS
[3] != 0.0) ||
1289 ((texGenEnabled
& T_BIT
) && planeT
[3] != 0.0) ||
1290 ((texGenEnabled
& R_BIT
) && planeR
[3] != 0.0)) {
1291 needtgenable
|= Q_BIT
;
1295 return needtgenable
;
1300 * Returns GL_FALSE if fallback required.
1302 static GLboolean
r200_validate_texgen( GLcontext
*ctx
, GLuint unit
)
1304 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1305 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1306 GLuint inputshift
= R200_TEXGEN_0_INPUT_SHIFT
+ unit
*4;
1309 GLboolean mixed_fallback
= GL_FALSE
;
1310 static const GLfloat I
[16] = {
1315 static const GLfloat reflect
[16] = {
1321 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1322 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
1323 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
1324 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
1325 tgi
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] & ~(R200_TEXGEN_INPUT_MASK
<<
1327 tgcm
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] & ~(R200_TEXGEN_COMP_MASK
<<
1331 fprintf(stderr
, "%s unit %d\n", __FUNCTION__
, unit
);
1333 if (texUnit
->TexGenEnabled
& S_BIT
) {
1334 mode
= texUnit
->GenModeS
;
1336 tgcm
|= R200_TEXGEN_COMP_S
<< (unit
* 4);
1339 if (texUnit
->TexGenEnabled
& T_BIT
) {
1340 if (texUnit
->GenModeT
!= mode
)
1341 mixed_fallback
= GL_TRUE
;
1343 tgcm
|= R200_TEXGEN_COMP_T
<< (unit
* 4);
1346 if (texUnit
->TexGenEnabled
& R_BIT
) {
1347 if (texUnit
->GenModeR
!= mode
)
1348 mixed_fallback
= GL_TRUE
;
1350 tgcm
|= R200_TEXGEN_COMP_R
<< (unit
* 4);
1353 if (texUnit
->TexGenEnabled
& Q_BIT
) {
1354 if (texUnit
->GenModeQ
!= mode
)
1355 mixed_fallback
= GL_TRUE
;
1357 tgcm
|= R200_TEXGEN_COMP_Q
<< (unit
* 4);
1360 if (mixed_fallback
) {
1361 if (R200_DEBUG
& DEBUG_FALLBACKS
)
1362 fprintf(stderr
, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
1363 texUnit
->TexGenEnabled
, texUnit
->GenModeS
, texUnit
->GenModeT
,
1364 texUnit
->GenModeR
, texUnit
->GenModeQ
);
1368 /* we CANNOT do mixed mode if the texgen mode requires a plane where the input
1369 is not enabled for texgen, since the planes are concatenated into texmat,
1370 and thus the input will come from texcoord rather than tex gen equation!
1371 Either fallback or just hope that those texcoords aren't really needed...
1372 Assuming the former will cause lots of unnecessary fallbacks, the latter will
1373 generate bogus results sometimes - it's pretty much impossible to really know
1374 when a fallback is needed, depends on texmat and what sort of texture is bound
1375 etc, - for now fallback if we're missing either S or T bits, there's a high
1376 probability we need the texcoords in that case.
1377 That's a lot of work for some obscure texgen mixed mode fixup - why oh why
1378 doesn't the chip just directly accept the plane parameters :-(. */
1380 case GL_OBJECT_LINEAR
: {
1381 GLuint needtgenable
= r200_need_dis_texgen( texUnit
->TexGenEnabled
,
1382 texUnit
->ObjectPlaneS
, texUnit
->ObjectPlaneT
,
1383 texUnit
->ObjectPlaneR
, texUnit
->ObjectPlaneQ
);
1384 if (needtgenable
& (S_BIT
| T_BIT
)) {
1385 if (R200_DEBUG
& DEBUG_FALLBACKS
)
1386 fprintf(stderr
, "fallback mixed texgen / obj plane, 0x%x\n",
1387 texUnit
->TexGenEnabled
);
1390 if (needtgenable
& (R_BIT
)) {
1391 tgcm
&= ~(R200_TEXGEN_COMP_R
<< (unit
* 4));
1393 if (needtgenable
& (Q_BIT
)) {
1394 tgcm
&= ~(R200_TEXGEN_COMP_Q
<< (unit
* 4));
1397 tgi
|= R200_TEXGEN_INPUT_OBJ
<< inputshift
;
1398 set_texgen_matrix( rmesa
, unit
,
1399 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->ObjectPlaneS
: I
,
1400 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->ObjectPlaneT
: I
+ 4,
1401 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->ObjectPlaneR
: I
+ 8,
1402 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->ObjectPlaneQ
: I
+ 12);
1406 case GL_EYE_LINEAR
: {
1407 GLuint needtgenable
= r200_need_dis_texgen( texUnit
->TexGenEnabled
,
1408 texUnit
->EyePlaneS
, texUnit
->EyePlaneT
,
1409 texUnit
->EyePlaneR
, texUnit
->EyePlaneQ
);
1410 if (needtgenable
& (S_BIT
| T_BIT
)) {
1411 if (R200_DEBUG
& DEBUG_FALLBACKS
)
1412 fprintf(stderr
, "fallback mixed texgen / eye plane, 0x%x\n",
1413 texUnit
->TexGenEnabled
);
1416 if (needtgenable
& (R_BIT
)) {
1417 tgcm
&= ~(R200_TEXGEN_COMP_R
<< (unit
* 4));
1419 if (needtgenable
& (Q_BIT
)) {
1420 tgcm
&= ~(R200_TEXGEN_COMP_Q
<< (unit
* 4));
1422 tgi
|= R200_TEXGEN_INPUT_EYE
<< inputshift
;
1423 set_texgen_matrix( rmesa
, unit
,
1424 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->EyePlaneS
: I
,
1425 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->EyePlaneT
: I
+ 4,
1426 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->EyePlaneR
: I
+ 8,
1427 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->EyePlaneQ
: I
+ 12);
1431 case GL_REFLECTION_MAP_NV
:
1432 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1433 tgi
|= R200_TEXGEN_INPUT_EYE_REFLECT
<< inputshift
;
1434 /* pretty weird, must only negate when lighting is enabled? */
1435 if (ctx
->Light
.Enabled
)
1436 set_texgen_matrix( rmesa
, unit
,
1437 (texUnit
->TexGenEnabled
& S_BIT
) ? reflect
: I
,
1438 (texUnit
->TexGenEnabled
& T_BIT
) ? reflect
+ 4 : I
+ 4,
1439 (texUnit
->TexGenEnabled
& R_BIT
) ? reflect
+ 8 : I
+ 8,
1443 case GL_NORMAL_MAP_NV
:
1444 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1445 tgi
|= R200_TEXGEN_INPUT_EYE_NORMAL
<<inputshift
;
1449 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1450 tgi
|= R200_TEXGEN_INPUT_SPHERE
<<inputshift
;
1454 /* All texgen units were disabled, so just pass coords through. */
1455 tgi
|= unit
<< inputshift
;
1459 /* Unsupported mode, fallback:
1461 if (R200_DEBUG
& DEBUG_FALLBACKS
)
1462 fprintf(stderr
, "fallback unsupported texgen, %d\n",
1467 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
1468 rmesa
->TexGenCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
1470 if (tgi
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] ||
1471 tgcm
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
])
1473 R200_STATECHANGE(rmesa
, tcg
);
1474 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] = tgi
;
1475 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] = tgcm
;
1482 static void disable_tex( GLcontext
*ctx
, int unit
)
1484 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1486 if (rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<<unit
)) {
1487 /* Texture unit disabled */
1488 if ( rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
1489 /* The old texture is no longer bound to this texture unit.
1493 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&= ~(1UL << unit
);
1494 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
1497 R200_STATECHANGE( rmesa
, ctx
);
1498 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~(R200_TEX_0_ENABLE
<< unit
);
1500 R200_STATECHANGE( rmesa
, vtx
);
1501 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
1503 if (rmesa
->TclFallback
& (R200_TCL_FALLBACK_TEXGEN_0
<<unit
)) {
1504 TCL_FALLBACK( ctx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), GL_FALSE
);
1507 /* Actually want to keep all units less than max active texture
1508 * enabled, right? Fix this for >2 texunits.
1512 GLuint tmp
= rmesa
->TexGenEnabled
;
1514 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
1515 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
1516 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
1517 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1519 if (tmp
!= rmesa
->TexGenEnabled
) {
1520 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1521 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1527 void set_re_cntl_d3d( GLcontext
*ctx
, int unit
, GLboolean use_d3d
)
1529 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1533 re_cntl
= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] & ~(R200_VTX_STQ0_D3D
<< (2 * unit
));
1535 re_cntl
|= R200_VTX_STQ0_D3D
<< (2 * unit
);
1537 if ( re_cntl
!= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] ) {
1538 R200_STATECHANGE( rmesa
, set
);
1539 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] = re_cntl
;
1543 static GLboolean
enable_tex_2d( GLcontext
*ctx
, int unit
)
1545 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1546 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1547 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1548 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1550 /* Need to load the 2d images associated with this unit.
1552 if (t
->pp_txformat
& R200_TXFORMAT_NON_POWER2
) {
1553 t
->pp_txformat
&= ~R200_TXFORMAT_NON_POWER2
;
1554 t
->base
.dirty_images
[0] = ~0;
1557 ASSERT(tObj
->Target
== GL_TEXTURE_2D
|| tObj
->Target
== GL_TEXTURE_1D
);
1559 if ( t
->base
.dirty_images
[0] ) {
1560 R200_FIREVERTICES( rmesa
);
1561 r200SetTexImages( rmesa
, tObj
);
1562 r200UploadTexImages( rmesa
, (r200TexObjPtr
) tObj
->DriverData
, 0 );
1563 if ( !t
->base
.memBlock
)
1567 set_re_cntl_d3d( ctx
, unit
, GL_FALSE
);
1572 #if ENABLE_HW_3D_TEXTURE
1573 static GLboolean
enable_tex_3d( GLcontext
*ctx
, int unit
)
1575 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1576 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1577 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1578 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1580 /* Need to load the 3d images associated with this unit.
1582 if (t
->pp_txformat
& R200_TXFORMAT_NON_POWER2
) {
1583 t
->pp_txformat
&= ~R200_TXFORMAT_NON_POWER2
;
1584 t
->base
.dirty_images
[0] = ~0;
1587 ASSERT(tObj
->Target
== GL_TEXTURE_3D
);
1589 /* R100 & R200 do not support mipmaps for 3D textures.
1591 if ( (tObj
->MinFilter
!= GL_NEAREST
) && (tObj
->MinFilter
!= GL_LINEAR
) ) {
1595 if ( t
->base
.dirty_images
[0] ) {
1596 R200_FIREVERTICES( rmesa
);
1597 r200SetTexImages( rmesa
, tObj
);
1598 r200UploadTexImages( rmesa
, (r200TexObjPtr
) tObj
->DriverData
, 0 );
1599 if ( !t
->base
.memBlock
)
1603 set_re_cntl_d3d( ctx
, unit
, GL_TRUE
);
1609 static GLboolean
enable_tex_cube( GLcontext
*ctx
, int unit
)
1611 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1612 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1613 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1614 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1617 /* Need to load the 2d images associated with this unit.
1619 if (t
->pp_txformat
& R200_TXFORMAT_NON_POWER2
) {
1620 t
->pp_txformat
&= ~R200_TXFORMAT_NON_POWER2
;
1621 for (face
= 0; face
< 6; face
++)
1622 t
->base
.dirty_images
[face
] = ~0;
1625 ASSERT(tObj
->Target
== GL_TEXTURE_CUBE_MAP
);
1627 if ( t
->base
.dirty_images
[0] || t
->base
.dirty_images
[1] ||
1628 t
->base
.dirty_images
[2] || t
->base
.dirty_images
[3] ||
1629 t
->base
.dirty_images
[4] || t
->base
.dirty_images
[5] ) {
1631 R200_FIREVERTICES( rmesa
);
1632 /* layout memory space, once for all faces */
1633 r200SetTexImages( rmesa
, tObj
);
1636 /* upload (per face) */
1637 for (face
= 0; face
< 6; face
++) {
1638 if (t
->base
.dirty_images
[face
]) {
1639 r200UploadTexImages( rmesa
, (r200TexObjPtr
) tObj
->DriverData
, face
);
1643 if ( !t
->base
.memBlock
) {
1644 /* texmem alloc failed, use s/w fallback */
1648 set_re_cntl_d3d( ctx
, unit
, GL_TRUE
);
1653 static GLboolean
enable_tex_rect( GLcontext
*ctx
, int unit
)
1655 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1656 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1657 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1658 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1660 if (!(t
->pp_txformat
& R200_TXFORMAT_NON_POWER2
)) {
1661 t
->pp_txformat
|= R200_TXFORMAT_NON_POWER2
;
1662 t
->base
.dirty_images
[0] = ~0;
1665 ASSERT(tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
1667 if ( t
->base
.dirty_images
[0] ) {
1668 R200_FIREVERTICES( rmesa
);
1669 r200SetTexImages( rmesa
, tObj
);
1670 r200UploadTexImages( rmesa
, (r200TexObjPtr
) tObj
->DriverData
, 0 );
1671 if ( !t
->base
.memBlock
&& !rmesa
->prefer_gart_client_texturing
)
1675 set_re_cntl_d3d( ctx
, unit
, GL_FALSE
);
1681 static GLboolean
update_tex_common( GLcontext
*ctx
, int unit
)
1683 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1684 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1685 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1686 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1688 /* Fallback if there's a texture border */
1689 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 )
1692 /* Update state if this is a different texture object to last
1695 if ( rmesa
->state
.texture
.unit
[unit
].texobj
!= t
) {
1696 if ( rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
1697 /* The old texture is no longer bound to this texture unit.
1701 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&=
1705 rmesa
->state
.texture
.unit
[unit
].texobj
= t
;
1706 t
->base
.bound
|= (1UL << unit
);
1707 t
->dirty_state
|= 1<<unit
;
1708 driUpdateTextureLRU( (driTextureObject
*) t
); /* XXX: should be locked! */
1714 if ( 1|| !(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<<unit
))) {
1715 R200_STATECHANGE( rmesa
, ctx
);
1716 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_0_ENABLE
<< unit
;
1718 R200_STATECHANGE( rmesa
, vtx
);
1719 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
1720 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] |= 4 << (unit
* 3);
1722 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1725 if (t
->dirty_state
& (1<<unit
)) {
1726 import_tex_obj_state( rmesa
, unit
, t
);
1729 if (rmesa
->recheck_texgen
[unit
]) {
1730 GLboolean fallback
= !r200_validate_texgen( ctx
, unit
);
1731 TCL_FALLBACK( ctx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), fallback
);
1732 rmesa
->recheck_texgen
[unit
] = 0;
1733 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1736 FALLBACK( rmesa
, R200_FALLBACK_BORDER_MODE
, t
->border_fallback
);
1737 return !t
->border_fallback
;
1742 static GLboolean
r200UpdateTextureUnit( GLcontext
*ctx
, int unit
)
1744 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1745 GLuint unitneeded
= rmesa
->state
.texture
.unit
[unit
].unitneeded
;
1747 if ( unitneeded
& (TEXTURE_RECT_BIT
) ) {
1748 return (enable_tex_rect( ctx
, unit
) &&
1749 update_tex_common( ctx
, unit
));
1751 else if ( unitneeded
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
) ) {
1752 return (enable_tex_2d( ctx
, unit
) &&
1753 update_tex_common( ctx
, unit
));
1755 #if ENABLE_HW_3D_TEXTURE
1756 else if ( unitneeded
& (TEXTURE_3D_BIT
) ) {
1757 return (enable_tex_3d( ctx
, unit
) &&
1758 update_tex_common( ctx
, unit
));
1761 else if ( unitneeded
& (TEXTURE_CUBE_BIT
) ) {
1762 return (enable_tex_cube( ctx
, unit
) &&
1763 update_tex_common( ctx
, unit
));
1765 else if ( unitneeded
) {
1769 disable_tex( ctx
, unit
);
1775 void r200UpdateTextureState( GLcontext
*ctx
)
1777 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1781 if (ctx
->ATIFragmentShader
._Enabled
) {
1783 for (i
= 0; i
< R200_MAX_TEXTURE_UNITS
; i
++) {
1784 rmesa
->state
.texture
.unit
[i
].unitneeded
= ctx
->Texture
.Unit
[i
]._ReallyEnabled
;
1789 ok
= r200UpdateAllTexEnv( ctx
);
1792 ok
= (r200UpdateTextureUnit( ctx
, 0 ) &&
1793 r200UpdateTextureUnit( ctx
, 1 ) &&
1794 r200UpdateTextureUnit( ctx
, 2 ) &&
1795 r200UpdateTextureUnit( ctx
, 3 ) &&
1796 r200UpdateTextureUnit( ctx
, 4 ) &&
1797 r200UpdateTextureUnit( ctx
, 5 ));
1800 if (ok
&& ctx
->ATIFragmentShader
._Enabled
) {
1801 r200UpdateFragmentShader(ctx
);
1804 FALLBACK( rmesa
, R200_FALLBACK_TEXTURE
, !ok
);
1806 if (rmesa
->TclFallback
)
1807 r200ChooseVertexState( ctx
);
1810 if (rmesa
->r200Screen
->chip_family
== CHIP_FAMILY_R200
) {
1813 * T0 hang workaround -------------
1814 * not needed for r200 derivatives
1816 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_ENABLE_MASK
) == R200_TEX_0_ENABLE
&&
1817 (rmesa
->hw
.tex
[0].cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) > R200_MIN_FILTER_LINEAR
) {
1819 R200_STATECHANGE(rmesa
, ctx
);
1820 R200_STATECHANGE(rmesa
, tex
[1]);
1821 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_1_ENABLE
;
1822 if (!(rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] & R200_PPX_TEX_1_ENABLE
))
1823 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1824 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] |= R200_TXFORMAT_LOOKUP_DISABLE
;
1826 else if (!ctx
->ATIFragmentShader
._Enabled
) {
1827 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
) &&
1828 (rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] & R200_TXFORMAT_LOOKUP_DISABLE
)) {
1829 R200_STATECHANGE(rmesa
, tex
[1]);
1830 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~R200_TXFORMAT_LOOKUP_DISABLE
;
1833 /* do the same workaround for the first pass of a fragment shader.
1834 * completely unknown if necessary / sufficient.
1836 if ((rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] & R200_PPX_TEX_ENABLE_MASK
) == R200_PPX_TEX_0_ENABLE
&&
1837 (rmesa
->hw
.tex
[0].cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) > R200_MIN_FILTER_LINEAR
) {
1839 R200_STATECHANGE(rmesa
, cst
);
1840 R200_STATECHANGE(rmesa
, tex
[1]);
1841 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] |= R200_PPX_TEX_1_ENABLE
;
1842 if (!(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
))
1843 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1844 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXMULTI_CTL
] |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE
;
1847 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1848 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1849 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1850 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1851 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1852 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1853 R200_MIN_FILTER_LINEAR)) {
1854 R200_STATECHANGE(rmesa, ctx);
1855 R200_STATECHANGE(rmesa, tex[i+1]);
1856 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1857 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1858 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1861 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1862 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1863 R200_STATECHANGE(rmesa, tex[i+1]);
1864 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1870 * Texture cache LRU hang workaround -------------
1871 * not needed for r200 derivatives
1872 * hopefully this covers first pass of a shader as well
1875 /* While the cases below attempt to only enable the workaround in the
1876 * specific cases necessary, they were insufficient. See bugzilla #1519,
1877 * #729, #814. Tests with quake3 showed no impact on performance.
1882 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) &&
1883 ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1885 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1886 ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1888 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1889 ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1895 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) &&
1896 ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1898 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1899 ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1901 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1902 ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1908 if (dbg
!= rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
]) {
1909 R200_STATECHANGE( rmesa
, tam
);
1910 rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
] = dbg
;
1911 if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg
);