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>
35 #include "main/glheader.h"
36 #include "main/imports.h"
37 #include "main/context.h"
38 #include "main/macros.h"
39 #include "main/texformat.h"
40 #include "main/texobj.h"
41 #include "main/enums.h"
43 #include "r200_context.h"
44 #include "r200_state.h"
45 #include "r200_ioctl.h"
46 #include "r200_swtcl.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
56 #define R200_TXFORMAT_RGB_DXT1 R200_TXFORMAT_DXT1
57 #define R200_TXFORMAT_RGBA_DXT1 R200_TXFORMAT_DXT1
58 #define R200_TXFORMAT_RGBA_DXT3 R200_TXFORMAT_DXT23
59 #define R200_TXFORMAT_RGBA_DXT5 R200_TXFORMAT_DXT45
62 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, 0 }
63 #define _COLOR_REV(f) \
64 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f, 0 }
66 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
67 #define _ALPHA_REV(f) \
68 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
70 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, R200_YUV_TO_RGB }
72 [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
73 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
74 && (tx_table_be[f].format != 0xffffffff) )
77 GLuint format
, filter
;
80 static const struct tx_table tx_table_be
[] =
82 [ MESA_FORMAT_RGBA8888
] = { R200_TXFORMAT_ABGR8888
| R200_TXFORMAT_ALPHA_IN_MAP
, 0 },
109 static const struct tx_table tx_table_le
[] =
112 [ MESA_FORMAT_RGBA8888_REV
] = { R200_TXFORMAT_ABGR8888
| R200_TXFORMAT_ALPHA_IN_MAP
, 0 },
114 _ALPHA_REV(ARGB8888
),
115 [ MESA_FORMAT_RGB888
] = { R200_TXFORMAT_ARGB8888
, 0 },
119 _ALPHA_REV(ARGB4444
),
121 _ALPHA_REV(ARGB1555
),
143 * This function computes the number of bytes of storage needed for
144 * the given texture object (all mipmap levels, all cube faces).
145 * The \c image[face][level].x/y/width/height parameters for upload/blitting
146 * are computed here. \c pp_txfilter, \c pp_txformat, etc. will be set here
149 * \param rmesa Context pointer
150 * \param tObj GL texture object whose images are to be posted to
153 static void r200SetTexImages( r200ContextPtr rmesa
,
154 struct gl_texture_object
*tObj
)
156 r200TexObjPtr t
= (r200TexObjPtr
)tObj
->DriverData
;
157 const struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
158 GLint curOffset
, blitWidth
;
161 GLint log2Width
, log2Height
, log2Depth
;
163 /* Set the hardware texture format
165 if ( !t
->image_override
) {
166 if ( VALID_FORMAT( baseImage
->TexFormat
->MesaFormat
) ) {
167 const struct tx_table
*table
= _mesa_little_endian() ? tx_table_le
:
170 t
->pp_txformat
&= ~(R200_TXFORMAT_FORMAT_MASK
|
171 R200_TXFORMAT_ALPHA_IN_MAP
);
172 t
->pp_txfilter
&= ~R200_YUV_TO_RGB
;
174 t
->pp_txformat
|= table
[ baseImage
->TexFormat
->MesaFormat
].format
;
175 t
->pp_txfilter
|= table
[ baseImage
->TexFormat
->MesaFormat
].filter
;
178 _mesa_problem(NULL
, "unexpected texture format in %s", __FUNCTION__
);
183 texelBytes
= baseImage
->TexFormat
->TexelBytes
;
185 /* Compute which mipmap levels we really want to send to the hardware.
188 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
189 log2Width
= tObj
->Image
[0][t
->base
.firstLevel
]->WidthLog2
;
190 log2Height
= tObj
->Image
[0][t
->base
.firstLevel
]->HeightLog2
;
191 log2Depth
= tObj
->Image
[0][t
->base
.firstLevel
]->DepthLog2
;
193 numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
195 assert(numLevels
<= RADEON_MAX_TEXTURE_LEVELS
);
197 /* Calculate mipmap offsets and dimensions for blitting (uploading)
198 * The idea is that we lay out the mipmap levels within a block of
199 * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
202 blitWidth
= BLIT_WIDTH_BYTES
;
205 /* figure out if this texture is suitable for tiling. */
207 if (rmesa
->texmicrotile
&& (tObj
->Target
!= GL_TEXTURE_RECTANGLE_NV
) &&
208 /* texrect might be able to use micro tiling too in theory? */
209 (baseImage
->Height
> 1)) {
210 /* allow 32 (bytes) x 1 mip (which will use two times the space
211 the non-tiled version would use) max if base texture is large enough */
212 if ((numLevels
== 1) ||
213 (((baseImage
->Width
* texelBytes
/ baseImage
->Height
) <= 32) &&
214 (baseImage
->Width
* texelBytes
> 64)) ||
215 ((baseImage
->Width
* texelBytes
/ baseImage
->Height
) <= 16)) {
216 t
->tile_bits
|= R200_TXO_MICRO_TILE
;
219 if (tObj
->Target
!= GL_TEXTURE_RECTANGLE_NV
) {
220 /* we can set macro tiling even for small textures, they will be untiled anyway */
221 t
->tile_bits
|= R200_TXO_MACRO_TILE
;
225 for (i
= 0; i
< numLevels
; i
++) {
226 const struct gl_texture_image
*texImage
;
229 texImage
= tObj
->Image
[0][i
+ t
->base
.firstLevel
];
233 /* find image size in bytes */
234 if (texImage
->IsCompressed
) {
235 /* need to calculate the size AFTER padding even though the texture is
236 submitted without padding.
237 Only handle pot textures currently - don't know if npot is even possible,
238 size calculation would certainly need (trivial) adjustments.
239 Align (and later pad) to 32byte, not sure what that 64byte blit width is
241 if ((t
->pp_txformat
& R200_TXFORMAT_FORMAT_MASK
) == R200_TXFORMAT_DXT1
) {
242 /* RGB_DXT1/RGBA_DXT1, 8 bytes per block */
243 if ((texImage
->Width
+ 3) < 8) /* width one block */
244 size
= texImage
->CompressedSize
* 4;
245 else if ((texImage
->Width
+ 3) < 16)
246 size
= texImage
->CompressedSize
* 2;
247 else size
= texImage
->CompressedSize
;
249 else /* DXT3/5, 16 bytes per block */
250 if ((texImage
->Width
+ 3) < 8)
251 size
= texImage
->CompressedSize
* 2;
252 else size
= texImage
->CompressedSize
;
254 else if (tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
) {
255 size
= ((texImage
->Width
* texelBytes
+ 63) & ~63) * texImage
->Height
;
257 else if (t
->tile_bits
& R200_TXO_MICRO_TILE
) {
258 /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
259 though the actual offset may be different (if texture is less than
260 32 bytes width) to the untiled case */
261 int w
= (texImage
->Width
* texelBytes
* 2 + 31) & ~31;
262 size
= (w
* ((texImage
->Height
+ 1) / 2)) * texImage
->Depth
;
263 blitWidth
= MAX2(texImage
->Width
, 64 / texelBytes
);
266 int w
= (texImage
->Width
* texelBytes
+ 31) & ~31;
267 size
= w
* texImage
->Height
* texImage
->Depth
;
268 blitWidth
= MAX2(texImage
->Width
, 64 / texelBytes
);
272 /* Align to 32-byte offset. It is faster to do this unconditionally
273 * (no branch penalty).
276 curOffset
= (curOffset
+ 0x1f) & ~0x1f;
279 t
->image
[0][i
].x
= curOffset
; /* fix x and y coords up later together with offset */
280 t
->image
[0][i
].y
= 0;
281 t
->image
[0][i
].width
= MIN2(size
/ texelBytes
, blitWidth
);
282 t
->image
[0][i
].height
= (size
/ texelBytes
) / t
->image
[0][i
].width
;
285 t
->image
[0][i
].x
= curOffset
% BLIT_WIDTH_BYTES
;
286 t
->image
[0][i
].y
= curOffset
/ BLIT_WIDTH_BYTES
;
287 t
->image
[0][i
].width
= MIN2(size
, BLIT_WIDTH_BYTES
);
288 t
->image
[0][i
].height
= size
/ t
->image
[0][i
].width
;
292 /* for debugging only and only applicable to non-rectangle targets */
293 assert(size
% t
->image
[0][i
].width
== 0);
294 assert(t
->image
[0][i
].x
== 0
295 || (size
< BLIT_WIDTH_BYTES
&& t
->image
[0][i
].height
== 1));
300 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
301 i
, texImage
->Width
, texImage
->Height
,
302 t
->image
[0][i
].x
, t
->image
[0][i
].y
,
303 t
->image
[0][i
].width
, t
->image
[0][i
].height
, size
, curOffset
);
309 /* Align the total size of texture memory block.
311 t
->base
.totalSize
= (curOffset
+ RADEON_OFFSET_MASK
) & ~RADEON_OFFSET_MASK
;
313 /* Setup remaining cube face blits, if needed */
314 if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
315 const GLuint faceSize
= t
->base
.totalSize
;
317 /* reuse face 0 x/y/width/height - just update the offset when uploading */
318 for (face
= 1; face
< 6; face
++) {
319 for (i
= 0; i
< numLevels
; i
++) {
320 t
->image
[face
][i
].x
= t
->image
[0][i
].x
;
321 t
->image
[face
][i
].y
= t
->image
[0][i
].y
;
322 t
->image
[face
][i
].width
= t
->image
[0][i
].width
;
323 t
->image
[face
][i
].height
= t
->image
[0][i
].height
;
326 t
->base
.totalSize
= 6 * faceSize
; /* total texmem needed */
332 t
->pp_txfilter
&= ~R200_MAX_MIP_LEVEL_MASK
;
333 t
->pp_txfilter
|= (numLevels
- 1) << R200_MAX_MIP_LEVEL_SHIFT
;
335 t
->pp_txformat
&= ~(R200_TXFORMAT_WIDTH_MASK
|
336 R200_TXFORMAT_HEIGHT_MASK
|
337 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
338 R200_TXFORMAT_F5_WIDTH_MASK
|
339 R200_TXFORMAT_F5_HEIGHT_MASK
);
340 t
->pp_txformat
|= ((log2Width
<< R200_TXFORMAT_WIDTH_SHIFT
) |
341 (log2Height
<< R200_TXFORMAT_HEIGHT_SHIFT
));
343 t
->pp_txformat_x
&= ~(R200_DEPTH_LOG2_MASK
| R200_TEXCOORD_MASK
);
344 if (tObj
->Target
== GL_TEXTURE_3D
) {
345 t
->pp_txformat_x
|= (log2Depth
<< R200_DEPTH_LOG2_SHIFT
);
346 t
->pp_txformat_x
|= R200_TEXCOORD_VOLUME
;
348 else if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
349 ASSERT(log2Width
== log2Height
);
350 t
->pp_txformat
|= ((log2Width
<< R200_TXFORMAT_F5_WIDTH_SHIFT
) |
351 (log2Height
<< R200_TXFORMAT_F5_HEIGHT_SHIFT
) |
352 /* don't think we need this bit, if it exists at all - fglrx does not set it */
353 (R200_TXFORMAT_CUBIC_MAP_ENABLE
));
354 t
->pp_txformat_x
|= R200_TEXCOORD_CUBIC_ENV
;
355 t
->pp_cubic_faces
= ((log2Width
<< R200_FACE_WIDTH_1_SHIFT
) |
356 (log2Height
<< R200_FACE_HEIGHT_1_SHIFT
) |
357 (log2Width
<< R200_FACE_WIDTH_2_SHIFT
) |
358 (log2Height
<< R200_FACE_HEIGHT_2_SHIFT
) |
359 (log2Width
<< R200_FACE_WIDTH_3_SHIFT
) |
360 (log2Height
<< R200_FACE_HEIGHT_3_SHIFT
) |
361 (log2Width
<< R200_FACE_WIDTH_4_SHIFT
) |
362 (log2Height
<< R200_FACE_HEIGHT_4_SHIFT
));
365 /* If we don't in fact send enough texture coordinates, q will be 1,
366 * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
368 t
->pp_txformat_x
|= R200_TEXCOORD_PROJ
;
371 t
->pp_txsize
= (((tObj
->Image
[0][t
->base
.firstLevel
]->Width
- 1) << 0) |
372 ((tObj
->Image
[0][t
->base
.firstLevel
]->Height
- 1) << 16));
374 /* Only need to round to nearest 32 for textures, but the blitter
375 * requires 64-byte aligned pitches, and we may/may not need the
376 * blitter. NPOT only!
378 if ( !t
->image_override
) {
379 if (baseImage
->IsCompressed
)
380 t
->pp_txpitch
= (tObj
->Image
[0][t
->base
.firstLevel
]->Width
+ 63) & ~(63);
382 t
->pp_txpitch
= ((tObj
->Image
[0][t
->base
.firstLevel
]->Width
* texelBytes
) + 63) & ~(63);
386 t
->dirty_state
= TEX_ALL
;
388 /* FYI: r200UploadTexImages( rmesa, t ) used to be called here */
393 /* ================================================================
394 * Texture combine functions
397 /* GL_ARB_texture_env_combine support
400 /* The color tables have combine functions for GL_SRC_COLOR,
401 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
403 static GLuint r200_register_color
[][R200_MAX_TEXTURE_UNITS
] =
406 R200_TXC_ARG_A_R0_COLOR
,
407 R200_TXC_ARG_A_R1_COLOR
,
408 R200_TXC_ARG_A_R2_COLOR
,
409 R200_TXC_ARG_A_R3_COLOR
,
410 R200_TXC_ARG_A_R4_COLOR
,
411 R200_TXC_ARG_A_R5_COLOR
414 R200_TXC_ARG_A_R0_COLOR
| R200_TXC_COMP_ARG_A
,
415 R200_TXC_ARG_A_R1_COLOR
| R200_TXC_COMP_ARG_A
,
416 R200_TXC_ARG_A_R2_COLOR
| R200_TXC_COMP_ARG_A
,
417 R200_TXC_ARG_A_R3_COLOR
| R200_TXC_COMP_ARG_A
,
418 R200_TXC_ARG_A_R4_COLOR
| R200_TXC_COMP_ARG_A
,
419 R200_TXC_ARG_A_R5_COLOR
| R200_TXC_COMP_ARG_A
422 R200_TXC_ARG_A_R0_ALPHA
,
423 R200_TXC_ARG_A_R1_ALPHA
,
424 R200_TXC_ARG_A_R2_ALPHA
,
425 R200_TXC_ARG_A_R3_ALPHA
,
426 R200_TXC_ARG_A_R4_ALPHA
,
427 R200_TXC_ARG_A_R5_ALPHA
430 R200_TXC_ARG_A_R0_ALPHA
| R200_TXC_COMP_ARG_A
,
431 R200_TXC_ARG_A_R1_ALPHA
| R200_TXC_COMP_ARG_A
,
432 R200_TXC_ARG_A_R2_ALPHA
| R200_TXC_COMP_ARG_A
,
433 R200_TXC_ARG_A_R3_ALPHA
| R200_TXC_COMP_ARG_A
,
434 R200_TXC_ARG_A_R4_ALPHA
| R200_TXC_COMP_ARG_A
,
435 R200_TXC_ARG_A_R5_ALPHA
| R200_TXC_COMP_ARG_A
439 static GLuint r200_tfactor_color
[] =
441 R200_TXC_ARG_A_TFACTOR_COLOR
,
442 R200_TXC_ARG_A_TFACTOR_COLOR
| R200_TXC_COMP_ARG_A
,
443 R200_TXC_ARG_A_TFACTOR_ALPHA
,
444 R200_TXC_ARG_A_TFACTOR_ALPHA
| R200_TXC_COMP_ARG_A
447 static GLuint r200_tfactor1_color
[] =
449 R200_TXC_ARG_A_TFACTOR1_COLOR
,
450 R200_TXC_ARG_A_TFACTOR1_COLOR
| R200_TXC_COMP_ARG_A
,
451 R200_TXC_ARG_A_TFACTOR1_ALPHA
,
452 R200_TXC_ARG_A_TFACTOR1_ALPHA
| R200_TXC_COMP_ARG_A
455 static GLuint r200_primary_color
[] =
457 R200_TXC_ARG_A_DIFFUSE_COLOR
,
458 R200_TXC_ARG_A_DIFFUSE_COLOR
| R200_TXC_COMP_ARG_A
,
459 R200_TXC_ARG_A_DIFFUSE_ALPHA
,
460 R200_TXC_ARG_A_DIFFUSE_ALPHA
| R200_TXC_COMP_ARG_A
463 /* GL_ZERO table - indices 0-3
464 * GL_ONE table - indices 1-4
466 static GLuint r200_zero_color
[] =
469 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
471 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
475 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
477 static GLuint r200_register_alpha
[][R200_MAX_TEXTURE_UNITS
] =
480 R200_TXA_ARG_A_R0_ALPHA
,
481 R200_TXA_ARG_A_R1_ALPHA
,
482 R200_TXA_ARG_A_R2_ALPHA
,
483 R200_TXA_ARG_A_R3_ALPHA
,
484 R200_TXA_ARG_A_R4_ALPHA
,
485 R200_TXA_ARG_A_R5_ALPHA
488 R200_TXA_ARG_A_R0_ALPHA
| R200_TXA_COMP_ARG_A
,
489 R200_TXA_ARG_A_R1_ALPHA
| R200_TXA_COMP_ARG_A
,
490 R200_TXA_ARG_A_R2_ALPHA
| R200_TXA_COMP_ARG_A
,
491 R200_TXA_ARG_A_R3_ALPHA
| R200_TXA_COMP_ARG_A
,
492 R200_TXA_ARG_A_R4_ALPHA
| R200_TXA_COMP_ARG_A
,
493 R200_TXA_ARG_A_R5_ALPHA
| R200_TXA_COMP_ARG_A
497 static GLuint r200_tfactor_alpha
[] =
499 R200_TXA_ARG_A_TFACTOR_ALPHA
,
500 R200_TXA_ARG_A_TFACTOR_ALPHA
| R200_TXA_COMP_ARG_A
503 static GLuint r200_tfactor1_alpha
[] =
505 R200_TXA_ARG_A_TFACTOR1_ALPHA
,
506 R200_TXA_ARG_A_TFACTOR1_ALPHA
| R200_TXA_COMP_ARG_A
509 static GLuint r200_primary_alpha
[] =
511 R200_TXA_ARG_A_DIFFUSE_ALPHA
,
512 R200_TXA_ARG_A_DIFFUSE_ALPHA
| R200_TXA_COMP_ARG_A
515 /* GL_ZERO table - indices 0-1
516 * GL_ONE table - indices 1-2
518 static GLuint r200_zero_alpha
[] =
521 R200_TXA_ARG_A_ZERO
| R200_TXA_COMP_ARG_A
,
526 /* Extract the arg from slot A, shift it into the correct argument slot
527 * and set the corresponding complement bit.
529 #define R200_COLOR_ARG( n, arg ) \
532 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
533 << R200_TXC_ARG_##arg##_SHIFT); \
535 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
536 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
539 #define R200_ALPHA_ARG( n, arg ) \
542 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
543 << R200_TXA_ARG_##arg##_SHIFT); \
545 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
546 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
550 /* ================================================================
551 * Texture unit state management
554 static GLboolean
r200UpdateTextureEnv( GLcontext
*ctx
, int unit
, int slot
, GLuint replaceargs
)
556 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
557 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
558 GLuint color_combine
, alpha_combine
;
559 GLuint color_scale
= rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] &
560 ~(R200_TXC_SCALE_MASK
| R200_TXC_OUTPUT_REG_MASK
| R200_TXC_TFACTOR_SEL_MASK
|
561 R200_TXC_TFACTOR1_SEL_MASK
);
562 GLuint alpha_scale
= rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] &
563 ~(R200_TXA_DOT_ALPHA
| R200_TXA_SCALE_MASK
| R200_TXA_OUTPUT_REG_MASK
|
564 R200_TXA_TFACTOR_SEL_MASK
| R200_TXA_TFACTOR1_SEL_MASK
);
566 /* texUnit->_Current can be NULL if and only if the texture unit is
567 * not actually enabled.
569 assert( (texUnit
->_ReallyEnabled
== 0)
570 || (texUnit
->_Current
!= NULL
) );
572 if ( R200_DEBUG
& DEBUG_TEXTURE
) {
573 fprintf( stderr
, "%s( %p, %d )\n", __FUNCTION__
, (void *)ctx
, unit
);
576 /* Set the texture environment state. Isn't this nice and clean?
577 * The chip will automagically set the texture alpha to 0xff when
578 * the texture format does not include an alpha component. This
579 * reduces the amount of special-casing we have to do, alpha-only
580 * textures being a notable exception.
583 color_scale
|= ((rmesa
->state
.texture
.unit
[unit
].outputreg
+ 1) << R200_TXC_OUTPUT_REG_SHIFT
) |
584 (unit
<< R200_TXC_TFACTOR_SEL_SHIFT
) |
585 (replaceargs
<< R200_TXC_TFACTOR1_SEL_SHIFT
);
586 alpha_scale
|= ((rmesa
->state
.texture
.unit
[unit
].outputreg
+ 1) << R200_TXA_OUTPUT_REG_SHIFT
) |
587 (unit
<< R200_TXA_TFACTOR_SEL_SHIFT
) |
588 (replaceargs
<< R200_TXA_TFACTOR1_SEL_SHIFT
);
590 if ( !texUnit
->_ReallyEnabled
) {
592 color_combine
= R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
593 | R200_TXC_ARG_C_DIFFUSE_COLOR
| R200_TXC_OP_MADD
;
594 alpha_combine
= R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
595 | R200_TXA_ARG_C_DIFFUSE_ALPHA
| R200_TXA_OP_MADD
;
598 GLuint color_arg
[3], alpha_arg
[3];
600 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
601 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
602 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
603 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
606 const GLint replaceoprgb
=
607 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->OperandRGB
[0] - GL_SRC_COLOR
;
608 const GLint replaceopa
=
609 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->OperandA
[0] - GL_SRC_ALPHA
;
612 * Extract the color and alpha combine function arguments.
614 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
615 GLint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
] - GL_SRC_COLOR
;
616 const GLint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
621 color_arg
[i
] = r200_register_color
[op
][unit
];
624 color_arg
[i
] = r200_tfactor_color
[op
];
626 case GL_PRIMARY_COLOR
:
627 color_arg
[i
] = r200_primary_color
[op
];
630 if (replaceargs
!= unit
) {
631 const GLint srcRGBreplace
=
632 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->SourceRGB
[0];
634 op
= op
^ replaceopa
;
637 op
= op
^ replaceoprgb
;
639 switch (srcRGBreplace
) {
641 color_arg
[i
] = r200_register_color
[op
][replaceargs
];
644 color_arg
[i
] = r200_tfactor1_color
[op
];
646 case GL_PRIMARY_COLOR
:
647 color_arg
[i
] = r200_primary_color
[op
];
651 color_arg
[i
] = r200_primary_color
[op
];
653 color_arg
[i
] = r200_register_color
[op
]
654 [rmesa
->state
.texture
.unit
[replaceargs
- 1].outputreg
];
657 color_arg
[i
] = r200_zero_color
[op
];
660 color_arg
[i
] = r200_zero_color
[op
+1];
668 color_arg
[i
] = r200_register_color
[op
][srcRGBreplace
- GL_TEXTURE0
];
676 color_arg
[i
] = r200_primary_color
[op
];
678 color_arg
[i
] = r200_register_color
[op
]
679 [rmesa
->state
.texture
.unit
[unit
- 1].outputreg
];
683 color_arg
[i
] = r200_zero_color
[op
];
686 color_arg
[i
] = r200_zero_color
[op
+1];
694 color_arg
[i
] = r200_register_color
[op
][srcRGBi
- GL_TEXTURE0
];
701 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
702 GLint op
= texUnit
->_CurrentCombine
->OperandA
[i
] - GL_SRC_ALPHA
;
703 const GLint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
708 alpha_arg
[i
] = r200_register_alpha
[op
][unit
];
711 alpha_arg
[i
] = r200_tfactor_alpha
[op
];
713 case GL_PRIMARY_COLOR
:
714 alpha_arg
[i
] = r200_primary_alpha
[op
];
717 if (replaceargs
!= unit
) {
718 const GLint srcAreplace
=
719 ctx
->Texture
.Unit
[replaceargs
]._CurrentCombine
->SourceA
[0];
720 op
= op
^ replaceopa
;
721 switch (srcAreplace
) {
723 alpha_arg
[i
] = r200_register_alpha
[op
][replaceargs
];
726 alpha_arg
[i
] = r200_tfactor1_alpha
[op
];
728 case GL_PRIMARY_COLOR
:
729 alpha_arg
[i
] = r200_primary_alpha
[op
];
733 alpha_arg
[i
] = r200_primary_alpha
[op
];
735 alpha_arg
[i
] = r200_register_alpha
[op
]
736 [rmesa
->state
.texture
.unit
[replaceargs
- 1].outputreg
];
739 alpha_arg
[i
] = r200_zero_alpha
[op
];
742 alpha_arg
[i
] = r200_zero_alpha
[op
+1];
750 alpha_arg
[i
] = r200_register_alpha
[op
][srcAreplace
- GL_TEXTURE0
];
758 alpha_arg
[i
] = r200_primary_alpha
[op
];
760 alpha_arg
[i
] = r200_register_alpha
[op
]
761 [rmesa
->state
.texture
.unit
[unit
- 1].outputreg
];
765 alpha_arg
[i
] = r200_zero_alpha
[op
];
768 alpha_arg
[i
] = r200_zero_alpha
[op
+1];
776 alpha_arg
[i
] = r200_register_alpha
[op
][srcAi
- GL_TEXTURE0
];
784 * Build up the color and alpha combine functions.
786 switch ( texUnit
->_CurrentCombine
->ModeRGB
) {
788 color_combine
= (R200_TXC_ARG_A_ZERO
|
789 R200_TXC_ARG_B_ZERO
|
791 R200_COLOR_ARG( 0, C
);
794 color_combine
= (R200_TXC_ARG_C_ZERO
|
796 R200_COLOR_ARG( 0, A
);
797 R200_COLOR_ARG( 1, B
);
800 color_combine
= (R200_TXC_ARG_B_ZERO
|
801 R200_TXC_COMP_ARG_B
|
803 R200_COLOR_ARG( 0, A
);
804 R200_COLOR_ARG( 1, C
);
807 color_combine
= (R200_TXC_ARG_B_ZERO
|
808 R200_TXC_COMP_ARG_B
|
809 R200_TXC_BIAS_ARG_C
| /* new */
810 R200_TXC_OP_MADD
); /* was ADDSIGNED */
811 R200_COLOR_ARG( 0, A
);
812 R200_COLOR_ARG( 1, C
);
815 color_combine
= (R200_TXC_ARG_B_ZERO
|
816 R200_TXC_COMP_ARG_B
|
819 R200_COLOR_ARG( 0, A
);
820 R200_COLOR_ARG( 1, C
);
823 color_combine
= (R200_TXC_OP_LERP
);
824 R200_COLOR_ARG( 0, B
);
825 R200_COLOR_ARG( 1, A
);
826 R200_COLOR_ARG( 2, C
);
829 case GL_DOT3_RGB_EXT
:
830 case GL_DOT3_RGBA_EXT
:
831 /* The EXT version of the DOT3 extension does not support the
832 * scale factor, but the ARB version (and the version in OpenGL
840 /* DOT3 works differently on R200 than on R100. On R100, just
841 * setting the DOT3 mode did everything for you. On R200, the
842 * driver has to enable the biasing and scale in the inputs to
843 * put them in the proper [-1,1] range. This is what the 4x and
844 * the -0.5 in the DOT3 spec do. The post-scale is then set
848 color_combine
= (R200_TXC_ARG_C_ZERO
|
850 R200_TXC_BIAS_ARG_A
|
851 R200_TXC_BIAS_ARG_B
|
852 R200_TXC_SCALE_ARG_A
|
853 R200_TXC_SCALE_ARG_B
);
854 R200_COLOR_ARG( 0, A
);
855 R200_COLOR_ARG( 1, B
);
858 case GL_MODULATE_ADD_ATI
:
859 color_combine
= (R200_TXC_OP_MADD
);
860 R200_COLOR_ARG( 0, A
);
861 R200_COLOR_ARG( 1, C
);
862 R200_COLOR_ARG( 2, B
);
864 case GL_MODULATE_SIGNED_ADD_ATI
:
865 color_combine
= (R200_TXC_BIAS_ARG_C
| /* new */
866 R200_TXC_OP_MADD
); /* was ADDSIGNED */
867 R200_COLOR_ARG( 0, A
);
868 R200_COLOR_ARG( 1, C
);
869 R200_COLOR_ARG( 2, B
);
871 case GL_MODULATE_SUBTRACT_ATI
:
872 color_combine
= (R200_TXC_NEG_ARG_C
|
874 R200_COLOR_ARG( 0, A
);
875 R200_COLOR_ARG( 1, C
);
876 R200_COLOR_ARG( 2, B
);
882 switch ( texUnit
->_CurrentCombine
->ModeA
) {
884 alpha_combine
= (R200_TXA_ARG_A_ZERO
|
885 R200_TXA_ARG_B_ZERO
|
887 R200_ALPHA_ARG( 0, C
);
890 alpha_combine
= (R200_TXA_ARG_C_ZERO
|
892 R200_ALPHA_ARG( 0, A
);
893 R200_ALPHA_ARG( 1, B
);
896 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
897 R200_TXA_COMP_ARG_B
|
899 R200_ALPHA_ARG( 0, A
);
900 R200_ALPHA_ARG( 1, C
);
903 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
904 R200_TXA_COMP_ARG_B
|
905 R200_TXA_BIAS_ARG_C
| /* new */
906 R200_TXA_OP_MADD
); /* was ADDSIGNED */
907 R200_ALPHA_ARG( 0, A
);
908 R200_ALPHA_ARG( 1, C
);
911 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
912 R200_TXA_COMP_ARG_B
|
915 R200_ALPHA_ARG( 0, A
);
916 R200_ALPHA_ARG( 1, C
);
919 alpha_combine
= (R200_TXA_OP_LERP
);
920 R200_ALPHA_ARG( 0, B
);
921 R200_ALPHA_ARG( 1, A
);
922 R200_ALPHA_ARG( 2, C
);
925 case GL_MODULATE_ADD_ATI
:
926 alpha_combine
= (R200_TXA_OP_MADD
);
927 R200_ALPHA_ARG( 0, A
);
928 R200_ALPHA_ARG( 1, C
);
929 R200_ALPHA_ARG( 2, B
);
931 case GL_MODULATE_SIGNED_ADD_ATI
:
932 alpha_combine
= (R200_TXA_BIAS_ARG_C
| /* new */
933 R200_TXA_OP_MADD
); /* was ADDSIGNED */
934 R200_ALPHA_ARG( 0, A
);
935 R200_ALPHA_ARG( 1, C
);
936 R200_ALPHA_ARG( 2, B
);
938 case GL_MODULATE_SUBTRACT_ATI
:
939 alpha_combine
= (R200_TXA_NEG_ARG_C
|
941 R200_ALPHA_ARG( 0, A
);
942 R200_ALPHA_ARG( 1, C
);
943 R200_ALPHA_ARG( 2, B
);
949 if ( (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
950 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ) {
951 alpha_scale
|= R200_TXA_DOT_ALPHA
;
956 * Apply the scale factor.
958 color_scale
|= (RGBshift
<< R200_TXC_SCALE_SHIFT
);
959 alpha_scale
|= (Ashift
<< R200_TXA_SCALE_SHIFT
);
965 if ( rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND
] != color_combine
||
966 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND
] != alpha_combine
||
967 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] != color_scale
||
968 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] != alpha_scale
) {
969 R200_STATECHANGE( rmesa
, pix
[slot
] );
970 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND
] = color_combine
;
971 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND
] = alpha_combine
;
972 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXCBLEND2
] = color_scale
;
973 rmesa
->hw
.pix
[slot
].cmd
[PIX_PP_TXABLEND2
] = alpha_scale
;
979 void r200SetTexOffset(__DRIcontext
* pDRICtx
, GLint texname
,
980 unsigned long long offset
, GLint depth
, GLuint pitch
)
982 r200ContextPtr rmesa
= pDRICtx
->driverPrivate
;
983 struct gl_texture_object
*tObj
=
984 _mesa_lookup_texture(rmesa
->glCtx
, texname
);
990 t
= (r200TexObjPtr
) tObj
->DriverData
;
992 t
->image_override
= GL_TRUE
;
997 t
->pp_txoffset
= offset
;
998 t
->pp_txpitch
= pitch
- 32;
1002 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_ARGB8888
].format
;
1003 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_ARGB8888
].filter
;
1007 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_RGB888
].format
;
1008 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_RGB888
].filter
;
1011 t
->pp_txformat
= tx_table_le
[MESA_FORMAT_RGB565
].format
;
1012 t
->pp_txfilter
|= tx_table_le
[MESA_FORMAT_RGB565
].filter
;
1020 static GLboolean
r200UpdateAllTexEnv( GLcontext
*ctx
)
1022 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1023 GLint i
, j
, currslot
;
1024 GLint maxunitused
= -1;
1025 GLboolean texregfree
[6] = {GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
};
1026 GLubyte stageref
[7] = {0, 0, 0, 0, 0, 0, 0};
1027 GLint nextunit
[R200_MAX_TEXTURE_UNITS
] = {0, 0, 0, 0, 0, 0};
1028 GLint currentnext
= -1;
1031 /* find highest used unit */
1032 for ( j
= 0; j
< R200_MAX_TEXTURE_UNITS
; j
++) {
1033 if (ctx
->Texture
.Unit
[j
]._ReallyEnabled
) {
1037 stageref
[maxunitused
+ 1] = REF_COLOR
| REF_ALPHA
;
1039 for ( j
= maxunitused
; j
>= 0; j
-- ) {
1040 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[j
];
1042 rmesa
->state
.texture
.unit
[j
].outputreg
= -1;
1044 if (stageref
[j
+ 1]) {
1046 /* use the lowest available reg. That gets us automatically reg0 for the last stage.
1047 need this even for disabled units, as it may get referenced due to the replace
1049 for ( i
= 0 ; i
< R200_MAX_TEXTURE_UNITS
; i
++ ) {
1050 if (texregfree
[i
]) {
1051 rmesa
->state
.texture
.unit
[j
].outputreg
= i
;
1055 if (rmesa
->state
.texture
.unit
[j
].outputreg
== -1) {
1056 /* no more free regs we can use. Need a fallback :-( */
1060 nextunit
[j
] = currentnext
;
1062 if (!texUnit
->_ReallyEnabled
) {
1063 /* the not enabled stages are referenced "indirectly",
1064 must not cut off the lower stages */
1065 stageref
[j
] = REF_COLOR
| REF_ALPHA
;
1070 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
1071 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
1072 const GLboolean isdot3rgba
= (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ||
1073 (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
);
1076 /* check if we need the color part, special case for dot3_rgba
1077 as if only the alpha part is referenced later on it still is using the color part */
1078 if ((stageref
[j
+ 1] & REF_COLOR
) || isdot3rgba
) {
1079 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
1080 const GLuint srcRGBi
= texUnit
->_CurrentCombine
->SourceRGB
[i
];
1081 const GLuint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
];
1082 switch ( srcRGBi
) {
1084 /* op 0/1 are referencing color, op 2/3 alpha */
1085 stageref
[j
] |= (op
>> 1) + 1;
1088 texregfree
[j
] = GL_FALSE
;
1096 texregfree
[srcRGBi
- GL_TEXTURE0
] = GL_FALSE
;
1098 default: /* don't care about other sources here */
1104 /* alpha args are ignored for dot3_rgba */
1105 if ((stageref
[j
+ 1] & REF_ALPHA
) && !isdot3rgba
) {
1107 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
1108 const GLuint srcAi
= texUnit
->_CurrentCombine
->SourceA
[i
];
1111 stageref
[j
] |= REF_ALPHA
;
1114 texregfree
[j
] = GL_FALSE
;
1122 texregfree
[srcAi
- GL_TEXTURE0
] = GL_FALSE
;
1124 default: /* don't care about other sources here */
1132 /* don't enable texture sampling for units if the result is not used */
1133 for (i
= 0; i
< R200_MAX_TEXTURE_UNITS
; i
++) {
1134 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
&& !texregfree
[i
])
1135 rmesa
->state
.texture
.unit
[i
].unitneeded
= ctx
->Texture
.Unit
[i
]._ReallyEnabled
;
1136 else rmesa
->state
.texture
.unit
[i
].unitneeded
= 0;
1141 rmesa
->state
.envneeded
= 1;
1144 while ((i
<= maxunitused
) && (i
>= 0)) {
1145 /* only output instruction if the results are referenced */
1146 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
&& stageref
[i
+1]) {
1147 GLuint replaceunit
= i
;
1148 /* try to optimize GL_REPLACE away (only one level deep though) */
1149 if ( (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ModeRGB
== GL_REPLACE
) &&
1150 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ModeA
== GL_REPLACE
) &&
1151 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ScaleShiftRGB
== 0) &&
1152 (ctx
->Texture
.Unit
[i
]._CurrentCombine
->ScaleShiftA
== 0) &&
1153 (nextunit
[i
] > 0) ) {
1154 /* yippie! can optimize it away! */
1159 /* need env instruction slot */
1160 rmesa
->state
.envneeded
|= 1 << currslot
;
1161 ok
= r200UpdateTextureEnv( ctx
, i
, currslot
, replaceunit
);
1162 if (!ok
) return GL_FALSE
;
1168 if (currslot
== 0) {
1169 /* need one stage at least */
1170 rmesa
->state
.texture
.unit
[0].outputreg
= 0;
1171 ok
= r200UpdateTextureEnv( ctx
, 0, 0, 0 );
1174 R200_STATECHANGE( rmesa
, ctx
);
1175 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~(R200_TEX_BLEND_ENABLE_MASK
| R200_MULTI_PASS_ENABLE
);
1176 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= rmesa
->state
.envneeded
<< R200_TEX_BLEND_0_ENABLE_SHIFT
;
1185 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
1186 R200_MIN_FILTER_MASK | \
1187 R200_MAG_FILTER_MASK | \
1188 R200_MAX_ANISO_MASK | \
1190 R200_YUV_TEMPERATURE_MASK | \
1191 R200_CLAMP_S_MASK | \
1192 R200_CLAMP_T_MASK | \
1193 R200_BORDER_MODE_D3D )
1195 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
1196 R200_TXFORMAT_HEIGHT_MASK | \
1197 R200_TXFORMAT_FORMAT_MASK | \
1198 R200_TXFORMAT_F5_WIDTH_MASK | \
1199 R200_TXFORMAT_F5_HEIGHT_MASK | \
1200 R200_TXFORMAT_ALPHA_IN_MAP | \
1201 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
1202 R200_TXFORMAT_NON_POWER2)
1204 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
1205 R200_TEXCOORD_MASK | \
1206 R200_CLAMP_Q_MASK | \
1207 R200_VOLUME_FILTER_MASK)
1210 static void import_tex_obj_state( r200ContextPtr rmesa
,
1212 r200TexObjPtr texobj
)
1214 /* do not use RADEON_DB_STATE to avoid stale texture caches */
1215 int *cmd
= &rmesa
->hw
.tex
[unit
].cmd
[TEX_CMD_0
];
1217 R200_STATECHANGE( rmesa
, tex
[unit
] );
1219 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
1220 cmd
[TEX_PP_TXFILTER
] |= texobj
->pp_txfilter
& TEXOBJ_TXFILTER_MASK
;
1221 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1222 cmd
[TEX_PP_TXFORMAT
] |= texobj
->pp_txformat
& TEXOBJ_TXFORMAT_MASK
;
1223 cmd
[TEX_PP_TXFORMAT_X
] &= ~TEXOBJ_TXFORMAT_X_MASK
;
1224 cmd
[TEX_PP_TXFORMAT_X
] |= texobj
->pp_txformat_x
& TEXOBJ_TXFORMAT_X_MASK
;
1225 cmd
[TEX_PP_TXSIZE
] = texobj
->pp_txsize
; /* NPOT only! */
1226 cmd
[TEX_PP_TXPITCH
] = texobj
->pp_txpitch
; /* NPOT only! */
1227 cmd
[TEX_PP_BORDER_COLOR
] = texobj
->pp_border_color
;
1228 if (rmesa
->r200Screen
->drmSupportsFragShader
) {
1229 cmd
[TEX_PP_TXOFFSET_NEWDRM
] = texobj
->pp_txoffset
;
1232 cmd
[TEX_PP_TXOFFSET_OLDDRM
] = texobj
->pp_txoffset
;
1235 if (texobj
->base
.tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
1236 int *cube_cmd
= &rmesa
->hw
.cube
[unit
].cmd
[CUBE_CMD_0
];
1237 GLuint bytesPerFace
= texobj
->base
.totalSize
/ 6;
1238 ASSERT(texobj
->base
.totalSize
% 6 == 0);
1240 R200_STATECHANGE( rmesa
, cube
[unit
] );
1241 cube_cmd
[CUBE_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
1242 if (rmesa
->r200Screen
->drmSupportsFragShader
) {
1243 /* that value is submitted twice. could change cube atom
1244 to not include that command when new drm is used */
1245 cmd
[TEX_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
1247 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F1
] = texobj
->pp_txoffset
+ 1 * bytesPerFace
;
1248 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F2
] = texobj
->pp_txoffset
+ 2 * bytesPerFace
;
1249 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F3
] = texobj
->pp_txoffset
+ 3 * bytesPerFace
;
1250 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F4
] = texobj
->pp_txoffset
+ 4 * bytesPerFace
;
1251 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F5
] = texobj
->pp_txoffset
+ 5 * bytesPerFace
;
1254 texobj
->dirty_state
&= ~(1<<unit
);
1258 static void set_texgen_matrix( r200ContextPtr rmesa
,
1260 const GLfloat
*s_plane
,
1261 const GLfloat
*t_plane
,
1262 const GLfloat
*r_plane
,
1263 const GLfloat
*q_plane
)
1287 _math_matrix_loadf( &(rmesa
->TexGenMatrix
[unit
]), m
);
1288 _math_matrix_analyse( &(rmesa
->TexGenMatrix
[unit
]) );
1289 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<<unit
;
1293 static GLuint
r200_need_dis_texgen(const GLbitfield texGenEnabled
,
1294 const GLfloat
*planeS
,
1295 const GLfloat
*planeT
,
1296 const GLfloat
*planeR
,
1297 const GLfloat
*planeQ
)
1299 GLuint needtgenable
= 0;
1301 if (!(texGenEnabled
& S_BIT
)) {
1302 if (((texGenEnabled
& T_BIT
) && planeT
[0] != 0.0) ||
1303 ((texGenEnabled
& R_BIT
) && planeR
[0] != 0.0) ||
1304 ((texGenEnabled
& Q_BIT
) && planeQ
[0] != 0.0)) {
1305 needtgenable
|= S_BIT
;
1308 if (!(texGenEnabled
& T_BIT
)) {
1309 if (((texGenEnabled
& S_BIT
) && planeS
[1] != 0.0) ||
1310 ((texGenEnabled
& R_BIT
) && planeR
[1] != 0.0) ||
1311 ((texGenEnabled
& Q_BIT
) && planeQ
[1] != 0.0)) {
1312 needtgenable
|= T_BIT
;
1315 if (!(texGenEnabled
& R_BIT
)) {
1316 if (((texGenEnabled
& S_BIT
) && planeS
[2] != 0.0) ||
1317 ((texGenEnabled
& T_BIT
) && planeT
[2] != 0.0) ||
1318 ((texGenEnabled
& Q_BIT
) && planeQ
[2] != 0.0)) {
1319 needtgenable
|= R_BIT
;
1322 if (!(texGenEnabled
& Q_BIT
)) {
1323 if (((texGenEnabled
& S_BIT
) && planeS
[3] != 0.0) ||
1324 ((texGenEnabled
& T_BIT
) && planeT
[3] != 0.0) ||
1325 ((texGenEnabled
& R_BIT
) && planeR
[3] != 0.0)) {
1326 needtgenable
|= Q_BIT
;
1330 return needtgenable
;
1335 * Returns GL_FALSE if fallback required.
1337 static GLboolean
r200_validate_texgen( GLcontext
*ctx
, GLuint unit
)
1339 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1340 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1341 GLuint inputshift
= R200_TEXGEN_0_INPUT_SHIFT
+ unit
*4;
1344 GLboolean mixed_fallback
= GL_FALSE
;
1345 static const GLfloat I
[16] = {
1350 static const GLfloat reflect
[16] = {
1356 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1357 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
1358 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
1359 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
1360 tgi
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] & ~(R200_TEXGEN_INPUT_MASK
<<
1362 tgcm
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] & ~(R200_TEXGEN_COMP_MASK
<<
1366 fprintf(stderr
, "%s unit %d\n", __FUNCTION__
, unit
);
1368 if (texUnit
->TexGenEnabled
& S_BIT
) {
1369 mode
= texUnit
->GenS
.Mode
;
1371 tgcm
|= R200_TEXGEN_COMP_S
<< (unit
* 4);
1374 if (texUnit
->TexGenEnabled
& T_BIT
) {
1375 if (texUnit
->GenT
.Mode
!= mode
)
1376 mixed_fallback
= GL_TRUE
;
1378 tgcm
|= R200_TEXGEN_COMP_T
<< (unit
* 4);
1381 if (texUnit
->TexGenEnabled
& R_BIT
) {
1382 if (texUnit
->GenR
.Mode
!= mode
)
1383 mixed_fallback
= GL_TRUE
;
1385 tgcm
|= R200_TEXGEN_COMP_R
<< (unit
* 4);
1388 if (texUnit
->TexGenEnabled
& Q_BIT
) {
1389 if (texUnit
->GenQ
.Mode
!= mode
)
1390 mixed_fallback
= GL_TRUE
;
1392 tgcm
|= R200_TEXGEN_COMP_Q
<< (unit
* 4);
1395 if (mixed_fallback
) {
1396 if (R200_DEBUG
& DEBUG_FALLBACKS
)
1397 fprintf(stderr
, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
1398 texUnit
->TexGenEnabled
, texUnit
->GenS
.Mode
, texUnit
->GenT
.Mode
,
1399 texUnit
->GenR
.Mode
, texUnit
->GenQ
.Mode
);
1403 /* we CANNOT do mixed mode if the texgen mode requires a plane where the input
1404 is not enabled for texgen, since the planes are concatenated into texmat,
1405 and thus the input will come from texcoord rather than tex gen equation!
1406 Either fallback or just hope that those texcoords aren't really needed...
1407 Assuming the former will cause lots of unnecessary fallbacks, the latter will
1408 generate bogus results sometimes - it's pretty much impossible to really know
1409 when a fallback is needed, depends on texmat and what sort of texture is bound
1410 etc, - for now fallback if we're missing either S or T bits, there's a high
1411 probability we need the texcoords in that case.
1412 That's a lot of work for some obscure texgen mixed mode fixup - why oh why
1413 doesn't the chip just directly accept the plane parameters :-(. */
1415 case GL_OBJECT_LINEAR
: {
1416 GLuint needtgenable
= r200_need_dis_texgen( texUnit
->TexGenEnabled
,
1417 texUnit
->GenS
.ObjectPlane
,
1418 texUnit
->GenT
.ObjectPlane
,
1419 texUnit
->GenR
.ObjectPlane
,
1420 texUnit
->GenQ
.ObjectPlane
);
1421 if (needtgenable
& (S_BIT
| T_BIT
)) {
1422 if (R200_DEBUG
& DEBUG_FALLBACKS
)
1423 fprintf(stderr
, "fallback mixed texgen / obj plane, 0x%x\n",
1424 texUnit
->TexGenEnabled
);
1427 if (needtgenable
& (R_BIT
)) {
1428 tgcm
&= ~(R200_TEXGEN_COMP_R
<< (unit
* 4));
1430 if (needtgenable
& (Q_BIT
)) {
1431 tgcm
&= ~(R200_TEXGEN_COMP_Q
<< (unit
* 4));
1434 tgi
|= R200_TEXGEN_INPUT_OBJ
<< inputshift
;
1435 set_texgen_matrix( rmesa
, unit
,
1436 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->GenS
.ObjectPlane
: I
,
1437 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->GenT
.ObjectPlane
: I
+ 4,
1438 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->GenR
.ObjectPlane
: I
+ 8,
1439 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->GenQ
.ObjectPlane
: I
+ 12);
1443 case GL_EYE_LINEAR
: {
1444 GLuint needtgenable
= r200_need_dis_texgen( texUnit
->TexGenEnabled
,
1445 texUnit
->GenS
.EyePlane
,
1446 texUnit
->GenT
.EyePlane
,
1447 texUnit
->GenR
.EyePlane
,
1448 texUnit
->GenQ
.EyePlane
);
1449 if (needtgenable
& (S_BIT
| T_BIT
)) {
1450 if (R200_DEBUG
& DEBUG_FALLBACKS
)
1451 fprintf(stderr
, "fallback mixed texgen / eye plane, 0x%x\n",
1452 texUnit
->TexGenEnabled
);
1455 if (needtgenable
& (R_BIT
)) {
1456 tgcm
&= ~(R200_TEXGEN_COMP_R
<< (unit
* 4));
1458 if (needtgenable
& (Q_BIT
)) {
1459 tgcm
&= ~(R200_TEXGEN_COMP_Q
<< (unit
* 4));
1461 tgi
|= R200_TEXGEN_INPUT_EYE
<< inputshift
;
1462 set_texgen_matrix( rmesa
, unit
,
1463 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->GenS
.EyePlane
: I
,
1464 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->GenT
.EyePlane
: I
+ 4,
1465 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->GenR
.EyePlane
: I
+ 8,
1466 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->GenQ
.EyePlane
: I
+ 12);
1470 case GL_REFLECTION_MAP_NV
:
1471 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1472 tgi
|= R200_TEXGEN_INPUT_EYE_REFLECT
<< inputshift
;
1473 /* pretty weird, must only negate when lighting is enabled? */
1474 if (ctx
->Light
.Enabled
)
1475 set_texgen_matrix( rmesa
, unit
,
1476 (texUnit
->TexGenEnabled
& S_BIT
) ? reflect
: I
,
1477 (texUnit
->TexGenEnabled
& T_BIT
) ? reflect
+ 4 : I
+ 4,
1478 (texUnit
->TexGenEnabled
& R_BIT
) ? reflect
+ 8 : I
+ 8,
1482 case GL_NORMAL_MAP_NV
:
1483 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1484 tgi
|= R200_TEXGEN_INPUT_EYE_NORMAL
<<inputshift
;
1488 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1489 tgi
|= R200_TEXGEN_INPUT_SPHERE
<<inputshift
;
1493 /* All texgen units were disabled, so just pass coords through. */
1494 tgi
|= unit
<< inputshift
;
1498 /* Unsupported mode, fallback:
1500 if (R200_DEBUG
& DEBUG_FALLBACKS
)
1501 fprintf(stderr
, "fallback unsupported texgen, %d\n",
1502 texUnit
->GenS
.Mode
);
1506 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
1507 rmesa
->TexGenCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
1509 if (tgi
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] ||
1510 tgcm
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
])
1512 R200_STATECHANGE(rmesa
, tcg
);
1513 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] = tgi
;
1514 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] = tgcm
;
1521 static void disable_tex( GLcontext
*ctx
, int unit
)
1523 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1525 if (rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<<unit
)) {
1526 /* Texture unit disabled */
1527 if ( rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
1528 /* The old texture is no longer bound to this texture unit.
1532 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&= ~(1UL << unit
);
1533 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
1536 R200_STATECHANGE( rmesa
, ctx
);
1537 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~(R200_TEX_0_ENABLE
<< unit
);
1539 R200_STATECHANGE( rmesa
, vtx
);
1540 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
1542 if (rmesa
->TclFallback
& (R200_TCL_FALLBACK_TEXGEN_0
<<unit
)) {
1543 TCL_FALLBACK( ctx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), GL_FALSE
);
1546 /* Actually want to keep all units less than max active texture
1547 * enabled, right? Fix this for >2 texunits.
1551 GLuint tmp
= rmesa
->TexGenEnabled
;
1553 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
1554 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
1555 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
1556 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1558 if (tmp
!= rmesa
->TexGenEnabled
) {
1559 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1560 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1566 void set_re_cntl_d3d( GLcontext
*ctx
, int unit
, GLboolean use_d3d
)
1568 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1572 re_cntl
= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] & ~(R200_VTX_STQ0_D3D
<< (2 * unit
));
1574 re_cntl
|= R200_VTX_STQ0_D3D
<< (2 * unit
);
1576 if ( re_cntl
!= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] ) {
1577 R200_STATECHANGE( rmesa
, set
);
1578 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] = re_cntl
;
1582 static GLboolean
enable_tex_2d( GLcontext
*ctx
, int unit
)
1584 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1585 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1586 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1587 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1589 /* Need to load the 2d images associated with this unit.
1591 if (t
->pp_txformat
& R200_TXFORMAT_NON_POWER2
) {
1592 t
->pp_txformat
&= ~R200_TXFORMAT_NON_POWER2
;
1593 t
->base
.dirty_images
[0] = ~0;
1596 ASSERT(tObj
->Target
== GL_TEXTURE_2D
|| tObj
->Target
== GL_TEXTURE_1D
);
1598 if ( t
->base
.dirty_images
[0] ) {
1599 R200_FIREVERTICES( rmesa
);
1600 r200SetTexImages( rmesa
, tObj
);
1601 r200UploadTexImages( rmesa
, (r200TexObjPtr
) tObj
->DriverData
, 0 );
1602 if ( !t
->base
.memBlock
&& !t
->image_override
)
1606 set_re_cntl_d3d( ctx
, unit
, GL_FALSE
);
1611 #if ENABLE_HW_3D_TEXTURE
1612 static GLboolean
enable_tex_3d( GLcontext
*ctx
, int unit
)
1614 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1615 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1616 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1617 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1619 /* Need to load the 3d images associated with this unit.
1621 if (t
->pp_txformat
& R200_TXFORMAT_NON_POWER2
) {
1622 t
->pp_txformat
&= ~R200_TXFORMAT_NON_POWER2
;
1623 t
->base
.dirty_images
[0] = ~0;
1626 ASSERT(tObj
->Target
== GL_TEXTURE_3D
);
1628 /* R100 & R200 do not support mipmaps for 3D textures.
1630 if ( (tObj
->MinFilter
!= GL_NEAREST
) && (tObj
->MinFilter
!= GL_LINEAR
) ) {
1634 if ( t
->base
.dirty_images
[0] ) {
1635 R200_FIREVERTICES( rmesa
);
1636 r200SetTexImages( rmesa
, tObj
);
1637 r200UploadTexImages( rmesa
, (r200TexObjPtr
) tObj
->DriverData
, 0 );
1638 if ( !t
->base
.memBlock
)
1642 set_re_cntl_d3d( ctx
, unit
, GL_TRUE
);
1648 static GLboolean
enable_tex_cube( GLcontext
*ctx
, int unit
)
1650 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1651 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1652 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1653 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1656 /* Need to load the 2d images associated with this unit.
1658 if (t
->pp_txformat
& R200_TXFORMAT_NON_POWER2
) {
1659 t
->pp_txformat
&= ~R200_TXFORMAT_NON_POWER2
;
1660 for (face
= 0; face
< 6; face
++)
1661 t
->base
.dirty_images
[face
] = ~0;
1664 ASSERT(tObj
->Target
== GL_TEXTURE_CUBE_MAP
);
1666 if ( t
->base
.dirty_images
[0] || t
->base
.dirty_images
[1] ||
1667 t
->base
.dirty_images
[2] || t
->base
.dirty_images
[3] ||
1668 t
->base
.dirty_images
[4] || t
->base
.dirty_images
[5] ) {
1670 R200_FIREVERTICES( rmesa
);
1671 /* layout memory space, once for all faces */
1672 r200SetTexImages( rmesa
, tObj
);
1675 /* upload (per face) */
1676 for (face
= 0; face
< 6; face
++) {
1677 if (t
->base
.dirty_images
[face
]) {
1678 r200UploadTexImages( rmesa
, (r200TexObjPtr
) tObj
->DriverData
, face
);
1682 if ( !t
->base
.memBlock
) {
1683 /* texmem alloc failed, use s/w fallback */
1687 set_re_cntl_d3d( ctx
, unit
, GL_TRUE
);
1692 static GLboolean
enable_tex_rect( GLcontext
*ctx
, int unit
)
1694 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1695 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1696 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1697 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1699 if (!(t
->pp_txformat
& R200_TXFORMAT_NON_POWER2
)) {
1700 t
->pp_txformat
|= R200_TXFORMAT_NON_POWER2
;
1701 t
->base
.dirty_images
[0] = ~0;
1704 ASSERT(tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
1706 if ( t
->base
.dirty_images
[0] ) {
1707 R200_FIREVERTICES( rmesa
);
1708 r200SetTexImages( rmesa
, tObj
);
1709 r200UploadTexImages( rmesa
, (r200TexObjPtr
) tObj
->DriverData
, 0 );
1710 if ( !t
->base
.memBlock
&&
1711 !t
->image_override
&&
1712 !rmesa
->prefer_gart_client_texturing
)
1716 set_re_cntl_d3d( ctx
, unit
, GL_FALSE
);
1722 static GLboolean
update_tex_common( GLcontext
*ctx
, int unit
)
1724 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1725 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1726 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1727 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1729 /* Fallback if there's a texture border */
1730 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 )
1733 /* Update state if this is a different texture object to last
1736 if ( rmesa
->state
.texture
.unit
[unit
].texobj
!= t
) {
1737 if ( rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
1738 /* The old texture is no longer bound to this texture unit.
1742 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&=
1746 rmesa
->state
.texture
.unit
[unit
].texobj
= t
;
1747 t
->base
.bound
|= (1UL << unit
);
1748 t
->dirty_state
|= 1<<unit
;
1749 driUpdateTextureLRU( (driTextureObject
*) t
); /* XXX: should be locked! */
1755 if ( 1|| !(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<<unit
))) {
1756 R200_STATECHANGE( rmesa
, ctx
);
1757 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_0_ENABLE
<< unit
;
1759 R200_STATECHANGE( rmesa
, vtx
);
1760 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
1761 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] |= 4 << (unit
* 3);
1763 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1766 if (t
->dirty_state
& (1<<unit
)) {
1767 import_tex_obj_state( rmesa
, unit
, t
);
1770 if (rmesa
->recheck_texgen
[unit
]) {
1771 GLboolean fallback
= !r200_validate_texgen( ctx
, unit
);
1772 TCL_FALLBACK( ctx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), fallback
);
1773 rmesa
->recheck_texgen
[unit
] = 0;
1774 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1777 FALLBACK( rmesa
, R200_FALLBACK_BORDER_MODE
, t
->border_fallback
);
1778 return !t
->border_fallback
;
1783 static GLboolean
r200UpdateTextureUnit( GLcontext
*ctx
, int unit
)
1785 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1786 GLuint unitneeded
= rmesa
->state
.texture
.unit
[unit
].unitneeded
;
1788 if ( unitneeded
& (TEXTURE_RECT_BIT
) ) {
1789 return (enable_tex_rect( ctx
, unit
) &&
1790 update_tex_common( ctx
, unit
));
1792 else if ( unitneeded
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
) ) {
1793 return (enable_tex_2d( ctx
, unit
) &&
1794 update_tex_common( ctx
, unit
));
1796 #if ENABLE_HW_3D_TEXTURE
1797 else if ( unitneeded
& (TEXTURE_3D_BIT
) ) {
1798 return (enable_tex_3d( ctx
, unit
) &&
1799 update_tex_common( ctx
, unit
));
1802 else if ( unitneeded
& (TEXTURE_CUBE_BIT
) ) {
1803 return (enable_tex_cube( ctx
, unit
) &&
1804 update_tex_common( ctx
, unit
));
1806 else if ( unitneeded
) {
1810 disable_tex( ctx
, unit
);
1816 void r200UpdateTextureState( GLcontext
*ctx
)
1818 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1822 /* NOTE: must not manipulate rmesa->state.texture.unit[].unitneeded or
1823 rmesa->state.envneeded before a R200_STATECHANGE (or R200_NEWPRIM) since
1824 we use these to determine if we want to emit the corresponding state
1826 R200_NEWPRIM( rmesa
);
1828 if (ctx
->ATIFragmentShader
._Enabled
) {
1830 for (i
= 0; i
< R200_MAX_TEXTURE_UNITS
; i
++) {
1831 rmesa
->state
.texture
.unit
[i
].unitneeded
= ctx
->Texture
.Unit
[i
]._ReallyEnabled
;
1836 ok
= r200UpdateAllTexEnv( ctx
);
1839 ok
= (r200UpdateTextureUnit( ctx
, 0 ) &&
1840 r200UpdateTextureUnit( ctx
, 1 ) &&
1841 r200UpdateTextureUnit( ctx
, 2 ) &&
1842 r200UpdateTextureUnit( ctx
, 3 ) &&
1843 r200UpdateTextureUnit( ctx
, 4 ) &&
1844 r200UpdateTextureUnit( ctx
, 5 ));
1847 if (ok
&& ctx
->ATIFragmentShader
._Enabled
) {
1848 r200UpdateFragmentShader(ctx
);
1851 FALLBACK( rmesa
, R200_FALLBACK_TEXTURE
, !ok
);
1853 if (rmesa
->TclFallback
)
1854 r200ChooseVertexState( ctx
);
1857 if (rmesa
->r200Screen
->chip_family
== CHIP_FAMILY_R200
) {
1860 * T0 hang workaround -------------
1861 * not needed for r200 derivatives
1863 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_ENABLE_MASK
) == R200_TEX_0_ENABLE
&&
1864 (rmesa
->hw
.tex
[0].cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) > R200_MIN_FILTER_LINEAR
) {
1866 R200_STATECHANGE(rmesa
, ctx
);
1867 R200_STATECHANGE(rmesa
, tex
[1]);
1868 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_1_ENABLE
;
1869 if (!(rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] & R200_PPX_TEX_1_ENABLE
))
1870 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1871 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] |= R200_TXFORMAT_LOOKUP_DISABLE
;
1873 else if (!ctx
->ATIFragmentShader
._Enabled
) {
1874 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
) &&
1875 (rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] & R200_TXFORMAT_LOOKUP_DISABLE
)) {
1876 R200_STATECHANGE(rmesa
, tex
[1]);
1877 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~R200_TXFORMAT_LOOKUP_DISABLE
;
1880 /* do the same workaround for the first pass of a fragment shader.
1881 * completely unknown if necessary / sufficient.
1883 if ((rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] & R200_PPX_TEX_ENABLE_MASK
) == R200_PPX_TEX_0_ENABLE
&&
1884 (rmesa
->hw
.tex
[0].cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) > R200_MIN_FILTER_LINEAR
) {
1886 R200_STATECHANGE(rmesa
, cst
);
1887 R200_STATECHANGE(rmesa
, tex
[1]);
1888 rmesa
->hw
.cst
.cmd
[CST_PP_CNTL_X
] |= R200_PPX_TEX_1_ENABLE
;
1889 if (!(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
))
1890 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1891 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXMULTI_CTL
] |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE
;
1894 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1895 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1896 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1897 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1898 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1899 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1900 R200_MIN_FILTER_LINEAR)) {
1901 R200_STATECHANGE(rmesa, ctx);
1902 R200_STATECHANGE(rmesa, tex[i+1]);
1903 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1904 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1905 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1908 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1909 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1910 R200_STATECHANGE(rmesa, tex[i+1]);
1911 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1917 * Texture cache LRU hang workaround -------------
1918 * not needed for r200 derivatives
1919 * hopefully this covers first pass of a shader as well
1922 /* While the cases below attempt to only enable the workaround in the
1923 * specific cases necessary, they were insufficient. See bugzilla #1519,
1924 * #729, #814. Tests with quake3 showed no impact on performance.
1929 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) &&
1930 ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1932 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1933 ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1935 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1936 ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1942 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) &&
1943 ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1945 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1946 ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1948 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1949 ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1955 if (dbg
!= rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
]) {
1956 R200_STATECHANGE( rmesa
, tam
);
1957 rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
] = dbg
;
1958 if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg
);