1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_texstate.c,v 1.3 2003/02/15 22:18:47 dawes Exp $ */
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
33 * Keith Whitwell <keith@tungstengraphics.com>
40 #include "texformat.h"
43 #include "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[f].format != 0xffffffff) )
77 GLuint format
, filter
;
113 * This function computes the number of bytes of storage needed for
114 * the given texture object (all mipmap levels, all cube faces).
115 * The \c image[face][level].x/y/width/height parameters for upload/blitting
116 * are computed here. \c pp_txfilter, \c pp_txformat, etc. will be set here
119 * \param rmesa Context pointer
120 * \param tObj GL texture object whose images are to be posted to
123 static void r200SetTexImages( r200ContextPtr rmesa
,
124 struct gl_texture_object
*tObj
)
126 r200TexObjPtr t
= (r200TexObjPtr
)tObj
->DriverData
;
127 const struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
131 GLint log2Width
, log2Height
, log2Depth
;
133 /* Set the hardware texture format
136 t
->pp_txformat
&= ~(R200_TXFORMAT_FORMAT_MASK
|
137 R200_TXFORMAT_ALPHA_IN_MAP
);
138 t
->pp_txfilter
&= ~R200_YUV_TO_RGB
;
140 if ( VALID_FORMAT( baseImage
->TexFormat
->MesaFormat
) ) {
141 t
->pp_txformat
|= tx_table
[ baseImage
->TexFormat
->MesaFormat
].format
;
142 t
->pp_txfilter
|= tx_table
[ baseImage
->TexFormat
->MesaFormat
].filter
;
145 _mesa_problem(NULL
, "unexpected texture format in %s", __FUNCTION__
);
150 /* Compute which mipmap levels we really want to send to the hardware.
153 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
154 log2Width
= tObj
->Image
[0][t
->base
.firstLevel
]->WidthLog2
;
155 log2Height
= tObj
->Image
[0][t
->base
.firstLevel
]->HeightLog2
;
156 log2Depth
= tObj
->Image
[0][t
->base
.firstLevel
]->DepthLog2
;
158 numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
160 assert(numLevels
<= RADEON_MAX_TEXTURE_LEVELS
);
162 /* Calculate mipmap offsets and dimensions for blitting (uploading)
163 * The idea is that we lay out the mipmap levels within a block of
164 * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
168 for (i
= 0; i
< numLevels
; i
++) {
169 const struct gl_texture_image
*texImage
;
172 texImage
= tObj
->Image
[0][i
+ t
->base
.firstLevel
];
176 /* find image size in bytes */
177 if (texImage
->IsCompressed
) {
178 /* need to calculate the size AFTER padding even though the texture is
179 submitted without padding.
180 Only handle pot textures currently - don't know if npot is even possible,
181 size calculation would certainly need (trivial) adjustments.
182 Align (and later pad) to 32byte, not sure what that 64byte blit width is
184 if ((t
->pp_txformat
& R200_TXFORMAT_FORMAT_MASK
) == R200_TXFORMAT_DXT1
) {
185 /* RGB_DXT1/RGBA_DXT1, 8 bytes per block */
186 if ((texImage
->Width
+ 3) < 8) /* width one block */
187 size
= texImage
->CompressedSize
* 4;
188 else if ((texImage
->Width
+ 3) < 16)
189 size
= texImage
->CompressedSize
* 2;
190 else size
= texImage
->CompressedSize
;
192 else /* DXT3/5, 16 bytes per block */
193 if ((texImage
->Width
+ 3) < 8)
194 size
= texImage
->CompressedSize
* 2;
195 else size
= texImage
->CompressedSize
;
197 else if (tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
) {
198 size
= ((texImage
->Width
* texImage
->TexFormat
->TexelBytes
+ 63)
199 & ~63) * texImage
->Height
;
202 int w
= texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
205 size
= w
* texImage
->Height
* texImage
->Depth
;
210 /* Align to 32-byte offset. It is faster to do this unconditionally
211 * (no branch penalty).
214 curOffset
= (curOffset
+ 0x1f) & ~0x1f;
216 t
->image
[0][i
].x
= curOffset
% BLIT_WIDTH_BYTES
;
217 t
->image
[0][i
].y
= curOffset
/ BLIT_WIDTH_BYTES
;
218 t
->image
[0][i
].width
= MIN2(size
, BLIT_WIDTH_BYTES
);
219 t
->image
[0][i
].height
= size
/ t
->image
[0][i
].width
;
222 /* for debugging only and only applicable to non-rectangle targets */
223 assert(size
% t
->image
[0][i
].width
== 0);
224 assert(t
->image
[0][i
].x
== 0
225 || (size
< BLIT_WIDTH_BYTES
&& t
->image
[0][i
].height
== 1));
230 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
231 i
, texImage
->Width
, texImage
->Height
,
232 t
->image
[0][i
].x
, t
->image
[0][i
].y
,
233 t
->image
[0][i
].width
, t
->image
[0][i
].height
, size
, curOffset
);
239 /* Align the total size of texture memory block.
241 t
->base
.totalSize
= (curOffset
+ RADEON_OFFSET_MASK
) & ~RADEON_OFFSET_MASK
;
243 /* Setup remaining cube face blits, if needed */
244 if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
245 /* Round totalSize up to multiple of BLIT_WIDTH_BYTES */
246 const GLuint faceSize
= (t
->base
.totalSize
+ BLIT_WIDTH_BYTES
- 1)
247 & ~(BLIT_WIDTH_BYTES
-1);
248 const GLuint lines
= faceSize
/ BLIT_WIDTH_BYTES
;
250 /* reuse face 0 x/y/width/height - just adjust y */
251 for (face
= 1; face
< 6; face
++) {
252 for (i
= 0; i
< numLevels
; i
++) {
253 t
->image
[face
][i
].x
= t
->image
[0][i
].x
;
254 t
->image
[face
][i
].y
= t
->image
[0][i
].y
+ face
* lines
;
255 t
->image
[face
][i
].width
= t
->image
[0][i
].width
;
256 t
->image
[face
][i
].height
= t
->image
[0][i
].height
;
259 t
->base
.totalSize
= 6 * faceSize
; /* total texmem needed */
265 t
->pp_txfilter
&= ~R200_MAX_MIP_LEVEL_MASK
;
266 t
->pp_txfilter
|= (numLevels
- 1) << R200_MAX_MIP_LEVEL_SHIFT
;
268 t
->pp_txformat
&= ~(R200_TXFORMAT_WIDTH_MASK
|
269 R200_TXFORMAT_HEIGHT_MASK
|
270 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
271 R200_TXFORMAT_F5_WIDTH_MASK
|
272 R200_TXFORMAT_F5_HEIGHT_MASK
);
273 t
->pp_txformat
|= ((log2Width
<< R200_TXFORMAT_WIDTH_SHIFT
) |
274 (log2Height
<< R200_TXFORMAT_HEIGHT_SHIFT
));
276 t
->pp_txformat_x
&= ~(R200_DEPTH_LOG2_MASK
| R200_TEXCOORD_MASK
);
277 if (tObj
->Target
== GL_TEXTURE_3D
) {
278 t
->pp_txformat_x
|= (log2Depth
<< R200_DEPTH_LOG2_SHIFT
);
279 t
->pp_txformat_x
|= R200_TEXCOORD_VOLUME
;
281 else if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
282 ASSERT(log2Width
== log2height
);
283 t
->pp_txformat
|= ((log2Width
<< R200_TXFORMAT_F5_WIDTH_SHIFT
) |
284 (log2Height
<< R200_TXFORMAT_F5_HEIGHT_SHIFT
) |
285 (R200_TXFORMAT_CUBIC_MAP_ENABLE
));
286 t
->pp_txformat_x
|= R200_TEXCOORD_CUBIC_ENV
;
287 t
->pp_cubic_faces
= ((log2Width
<< R200_FACE_WIDTH_1_SHIFT
) |
288 (log2Height
<< R200_FACE_HEIGHT_1_SHIFT
) |
289 (log2Width
<< R200_FACE_WIDTH_2_SHIFT
) |
290 (log2Height
<< R200_FACE_HEIGHT_2_SHIFT
) |
291 (log2Width
<< R200_FACE_WIDTH_3_SHIFT
) |
292 (log2Height
<< R200_FACE_HEIGHT_3_SHIFT
) |
293 (log2Width
<< R200_FACE_WIDTH_4_SHIFT
) |
294 (log2Height
<< R200_FACE_HEIGHT_4_SHIFT
));
297 /* If we don't in fact send enough texture coordinates, q will be 1,
298 * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
300 t
->pp_txformat_x
|= R200_TEXCOORD_PROJ
;
303 t
->pp_txsize
= (((tObj
->Image
[0][t
->base
.firstLevel
]->Width
- 1) << 0) |
304 ((tObj
->Image
[0][t
->base
.firstLevel
]->Height
- 1) << 16));
306 /* Only need to round to nearest 32 for textures, but the blitter
307 * requires 64-byte aligned pitches, and we may/may not need the
308 * blitter. NPOT only!
310 if (baseImage
->IsCompressed
)
311 t
->pp_txpitch
= (tObj
->Image
[0][t
->base
.firstLevel
]->Width
+ 63) & ~(63);
313 t
->pp_txpitch
= ((tObj
->Image
[0][t
->base
.firstLevel
]->Width
* baseImage
->TexFormat
->TexelBytes
) + 63) & ~(63);
316 t
->dirty_state
= TEX_ALL
;
318 /* FYI: r200UploadTexImages( rmesa, t ) used to be called here */
323 /* ================================================================
324 * Texture combine functions
327 /* GL_ARB_texture_env_combine support
330 /* The color tables have combine functions for GL_SRC_COLOR,
331 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
333 static GLuint r200_register_color
[][R200_MAX_TEXTURE_UNITS
] =
336 R200_TXC_ARG_A_R0_COLOR
,
337 R200_TXC_ARG_A_R1_COLOR
,
338 R200_TXC_ARG_A_R2_COLOR
,
339 R200_TXC_ARG_A_R3_COLOR
,
340 R200_TXC_ARG_A_R4_COLOR
,
341 R200_TXC_ARG_A_R5_COLOR
344 R200_TXC_ARG_A_R0_COLOR
| R200_TXC_COMP_ARG_A
,
345 R200_TXC_ARG_A_R1_COLOR
| R200_TXC_COMP_ARG_A
,
346 R200_TXC_ARG_A_R2_COLOR
| R200_TXC_COMP_ARG_A
,
347 R200_TXC_ARG_A_R3_COLOR
| R200_TXC_COMP_ARG_A
,
348 R200_TXC_ARG_A_R4_COLOR
| R200_TXC_COMP_ARG_A
,
349 R200_TXC_ARG_A_R5_COLOR
| R200_TXC_COMP_ARG_A
352 R200_TXC_ARG_A_R0_ALPHA
,
353 R200_TXC_ARG_A_R1_ALPHA
,
354 R200_TXC_ARG_A_R2_ALPHA
,
355 R200_TXC_ARG_A_R3_ALPHA
,
356 R200_TXC_ARG_A_R4_ALPHA
,
357 R200_TXC_ARG_A_R5_ALPHA
360 R200_TXC_ARG_A_R0_ALPHA
| R200_TXC_COMP_ARG_A
,
361 R200_TXC_ARG_A_R1_ALPHA
| R200_TXC_COMP_ARG_A
,
362 R200_TXC_ARG_A_R2_ALPHA
| R200_TXC_COMP_ARG_A
,
363 R200_TXC_ARG_A_R3_ALPHA
| R200_TXC_COMP_ARG_A
,
364 R200_TXC_ARG_A_R4_ALPHA
| R200_TXC_COMP_ARG_A
,
365 R200_TXC_ARG_A_R5_ALPHA
| R200_TXC_COMP_ARG_A
369 static GLuint r200_tfactor_color
[] =
371 R200_TXC_ARG_A_TFACTOR_COLOR
,
372 R200_TXC_ARG_A_TFACTOR_COLOR
| R200_TXC_COMP_ARG_A
,
373 R200_TXC_ARG_A_TFACTOR_ALPHA
,
374 R200_TXC_ARG_A_TFACTOR_ALPHA
| R200_TXC_COMP_ARG_A
377 static GLuint r200_primary_color
[] =
379 R200_TXC_ARG_A_DIFFUSE_COLOR
,
380 R200_TXC_ARG_A_DIFFUSE_COLOR
| R200_TXC_COMP_ARG_A
,
381 R200_TXC_ARG_A_DIFFUSE_ALPHA
,
382 R200_TXC_ARG_A_DIFFUSE_ALPHA
| R200_TXC_COMP_ARG_A
385 /* GL_ZERO table - indices 0-3
386 * GL_ONE table - indices 1-4
388 static GLuint r200_zero_color
[] =
391 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
393 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
397 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
399 static GLuint r200_register_alpha
[][R200_MAX_TEXTURE_UNITS
] =
402 R200_TXA_ARG_A_R0_ALPHA
,
403 R200_TXA_ARG_A_R1_ALPHA
,
404 R200_TXA_ARG_A_R2_ALPHA
,
405 R200_TXA_ARG_A_R3_ALPHA
,
406 R200_TXA_ARG_A_R4_ALPHA
,
407 R200_TXA_ARG_A_R5_ALPHA
410 R200_TXA_ARG_A_R0_ALPHA
| R200_TXA_COMP_ARG_A
,
411 R200_TXA_ARG_A_R1_ALPHA
| R200_TXA_COMP_ARG_A
,
412 R200_TXA_ARG_A_R2_ALPHA
| R200_TXA_COMP_ARG_A
,
413 R200_TXA_ARG_A_R3_ALPHA
| R200_TXA_COMP_ARG_A
,
414 R200_TXA_ARG_A_R4_ALPHA
| R200_TXA_COMP_ARG_A
,
415 R200_TXA_ARG_A_R5_ALPHA
| R200_TXA_COMP_ARG_A
419 static GLuint r200_tfactor_alpha
[] =
421 R200_TXA_ARG_A_TFACTOR_ALPHA
,
422 R200_TXA_ARG_A_TFACTOR_ALPHA
| R200_TXA_COMP_ARG_A
425 static GLuint r200_primary_alpha
[] =
427 R200_TXA_ARG_A_DIFFUSE_ALPHA
,
428 R200_TXA_ARG_A_DIFFUSE_ALPHA
| R200_TXA_COMP_ARG_A
431 /* GL_ZERO table - indices 0-1
432 * GL_ONE table - indices 1-2
434 static GLuint r200_zero_alpha
[] =
437 R200_TXA_ARG_A_ZERO
| R200_TXA_COMP_ARG_A
,
442 /* Extract the arg from slot A, shift it into the correct argument slot
443 * and set the corresponding complement bit.
445 #define R200_COLOR_ARG( n, arg ) \
448 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
449 << R200_TXC_ARG_##arg##_SHIFT); \
451 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
452 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
455 #define R200_ALPHA_ARG( n, arg ) \
458 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
459 << R200_TXA_ARG_##arg##_SHIFT); \
461 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
462 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
466 /* ================================================================
467 * Texture unit state management
470 static GLboolean
r200UpdateTextureEnv( GLcontext
*ctx
, int unit
)
472 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
473 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
474 GLuint color_combine
, alpha_combine
;
475 GLuint color_scale
= rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] &
476 ~(R200_TXC_SCALE_MASK
);
477 GLuint alpha_scale
= rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] &
478 ~(R200_TXA_DOT_ALPHA
| R200_TXA_SCALE_MASK
);
480 /* texUnit->_Current can be NULL if and only if the texture unit is
481 * not actually enabled.
483 assert( (texUnit
->_ReallyEnabled
== 0)
484 || (texUnit
->_Current
!= NULL
) );
486 if ( R200_DEBUG
& DEBUG_TEXTURE
) {
487 fprintf( stderr
, "%s( %p, %d )\n", __FUNCTION__
, (void *)ctx
, unit
);
490 /* Set the texture environment state. Isn't this nice and clean?
491 * The chip will automagically set the texture alpha to 0xff when
492 * the texture format does not include an alpha component. This
493 * reduces the amount of special-casing we have to do, alpha-only
494 * textures being a notable exception.
496 /* Don't cache these results.
498 rmesa
->state
.texture
.unit
[unit
].format
= 0;
499 rmesa
->state
.texture
.unit
[unit
].envMode
= 0;
501 if ( !texUnit
->_ReallyEnabled
) {
503 color_combine
= R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
504 | R200_TXC_ARG_C_DIFFUSE_COLOR
| R200_TXC_OP_MADD
;
505 alpha_combine
= R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
506 | R200_TXA_ARG_C_DIFFUSE_ALPHA
| R200_TXA_OP_MADD
;
509 color_combine
= R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
510 | R200_TXC_ARG_C_R0_COLOR
| R200_TXC_OP_MADD
;
511 alpha_combine
= R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
512 | R200_TXA_ARG_C_R0_ALPHA
| R200_TXA_OP_MADD
;
516 GLuint color_arg
[3], alpha_arg
[3];
518 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
519 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
520 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
521 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
525 * Extract the color and alpha combine function arguments.
527 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
528 const GLint op
= texUnit
->_CurrentCombine
->OperandRGB
[i
] - GL_SRC_COLOR
;
531 switch ( texUnit
->_CurrentCombine
->SourceRGB
[i
] ) {
533 color_arg
[i
] = r200_register_color
[op
][unit
];
536 color_arg
[i
] = r200_tfactor_color
[op
];
538 case GL_PRIMARY_COLOR
:
539 color_arg
[i
] = r200_primary_color
[op
];
543 color_arg
[i
] = r200_primary_color
[op
];
545 color_arg
[i
] = r200_register_color
[op
][0];
548 color_arg
[i
] = r200_zero_color
[op
];
551 color_arg
[i
] = r200_zero_color
[op
+1];
558 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
559 const GLint op
= texUnit
->_CurrentCombine
->OperandA
[i
] - GL_SRC_ALPHA
;
562 switch ( texUnit
->_CurrentCombine
->SourceA
[i
] ) {
564 alpha_arg
[i
] = r200_register_alpha
[op
][unit
];
567 alpha_arg
[i
] = r200_tfactor_alpha
[op
];
569 case GL_PRIMARY_COLOR
:
570 alpha_arg
[i
] = r200_primary_alpha
[op
];
574 alpha_arg
[i
] = r200_primary_alpha
[op
];
576 alpha_arg
[i
] = r200_register_alpha
[op
][0];
579 alpha_arg
[i
] = r200_zero_alpha
[op
];
582 alpha_arg
[i
] = r200_zero_alpha
[op
+1];
590 * Build up the color and alpha combine functions.
592 switch ( texUnit
->_CurrentCombine
->ModeRGB
) {
594 color_combine
= (R200_TXC_ARG_A_ZERO
|
595 R200_TXC_ARG_B_ZERO
|
597 R200_COLOR_ARG( 0, C
);
600 color_combine
= (R200_TXC_ARG_C_ZERO
|
602 R200_COLOR_ARG( 0, A
);
603 R200_COLOR_ARG( 1, B
);
606 color_combine
= (R200_TXC_ARG_B_ZERO
|
607 R200_TXC_COMP_ARG_B
|
609 R200_COLOR_ARG( 0, A
);
610 R200_COLOR_ARG( 1, C
);
613 color_combine
= (R200_TXC_ARG_B_ZERO
|
614 R200_TXC_COMP_ARG_B
|
615 R200_TXC_BIAS_ARG_C
| /* new */
616 R200_TXC_OP_MADD
); /* was ADDSIGNED */
617 R200_COLOR_ARG( 0, A
);
618 R200_COLOR_ARG( 1, C
);
621 color_combine
= (R200_TXC_ARG_B_ZERO
|
622 R200_TXC_COMP_ARG_B
|
625 R200_COLOR_ARG( 0, A
);
626 R200_COLOR_ARG( 1, C
);
629 color_combine
= (R200_TXC_OP_LERP
);
630 R200_COLOR_ARG( 0, B
);
631 R200_COLOR_ARG( 1, A
);
632 R200_COLOR_ARG( 2, C
);
635 case GL_DOT3_RGB_EXT
:
636 case GL_DOT3_RGBA_EXT
:
637 /* The EXT version of the DOT3 extension does not support the
638 * scale factor, but the ARB version (and the version in OpenGL
646 /* DOT3 works differently on R200 than on R100. On R100, just
647 * setting the DOT3 mode did everything for you. On R200, the
648 * driver has to enable the biasing and scale in the inputs to
649 * put them in the proper [-1,1] range. This is what the 4x and
650 * the -0.5 in the DOT3 spec do. The post-scale is then set
654 color_combine
= (R200_TXC_ARG_C_ZERO
|
656 R200_TXC_BIAS_ARG_A
|
657 R200_TXC_BIAS_ARG_B
|
658 R200_TXC_SCALE_ARG_A
|
659 R200_TXC_SCALE_ARG_B
);
660 R200_COLOR_ARG( 0, A
);
661 R200_COLOR_ARG( 1, B
);
664 case GL_MODULATE_ADD_ATI
:
665 color_combine
= (R200_TXC_OP_MADD
);
666 R200_COLOR_ARG( 0, A
);
667 R200_COLOR_ARG( 1, C
);
668 R200_COLOR_ARG( 2, B
);
670 case GL_MODULATE_SIGNED_ADD_ATI
:
671 color_combine
= (R200_TXC_BIAS_ARG_C
| /* new */
672 R200_TXC_OP_MADD
); /* was ADDSIGNED */
673 R200_COLOR_ARG( 0, A
);
674 R200_COLOR_ARG( 1, C
);
675 R200_COLOR_ARG( 2, B
);
677 case GL_MODULATE_SUBTRACT_ATI
:
678 color_combine
= (R200_TXC_NEG_ARG_C
|
680 R200_COLOR_ARG( 0, A
);
681 R200_COLOR_ARG( 1, C
);
682 R200_COLOR_ARG( 2, B
);
688 switch ( texUnit
->_CurrentCombine
->ModeA
) {
690 alpha_combine
= (R200_TXA_ARG_A_ZERO
|
691 R200_TXA_ARG_B_ZERO
|
693 R200_ALPHA_ARG( 0, C
);
696 alpha_combine
= (R200_TXA_ARG_C_ZERO
|
698 R200_ALPHA_ARG( 0, A
);
699 R200_ALPHA_ARG( 1, B
);
702 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
703 R200_TXA_COMP_ARG_B
|
705 R200_ALPHA_ARG( 0, A
);
706 R200_ALPHA_ARG( 1, C
);
709 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
710 R200_TXA_COMP_ARG_B
|
711 R200_TXA_BIAS_ARG_C
| /* new */
712 R200_TXA_OP_MADD
); /* was ADDSIGNED */
713 R200_ALPHA_ARG( 0, A
);
714 R200_ALPHA_ARG( 1, C
);
717 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
718 R200_TXA_COMP_ARG_B
|
721 R200_ALPHA_ARG( 0, A
);
722 R200_ALPHA_ARG( 1, C
);
725 alpha_combine
= (R200_TXA_OP_LERP
);
726 R200_ALPHA_ARG( 0, B
);
727 R200_ALPHA_ARG( 1, A
);
728 R200_ALPHA_ARG( 2, C
);
731 case GL_MODULATE_ADD_ATI
:
732 alpha_combine
= (R200_TXA_OP_MADD
);
733 R200_ALPHA_ARG( 0, A
);
734 R200_ALPHA_ARG( 1, C
);
735 R200_ALPHA_ARG( 2, B
);
737 case GL_MODULATE_SIGNED_ADD_ATI
:
738 alpha_combine
= (R200_TXA_BIAS_ARG_C
| /* new */
739 R200_TXA_OP_MADD
); /* was ADDSIGNED */
740 R200_ALPHA_ARG( 0, A
);
741 R200_ALPHA_ARG( 1, C
);
742 R200_ALPHA_ARG( 2, B
);
744 case GL_MODULATE_SUBTRACT_ATI
:
745 alpha_combine
= (R200_TXA_NEG_ARG_C
|
747 R200_ALPHA_ARG( 0, A
);
748 R200_ALPHA_ARG( 1, C
);
749 R200_ALPHA_ARG( 2, B
);
755 if ( (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
756 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ) {
757 alpha_scale
|= R200_TXA_DOT_ALPHA
;
762 * Apply the scale factor.
764 color_scale
|= (RGBshift
<< R200_TXC_SCALE_SHIFT
);
765 alpha_scale
|= (Ashift
<< R200_TXA_SCALE_SHIFT
);
771 if ( rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND
] != color_combine
||
772 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND
] != alpha_combine
||
773 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] != color_scale
||
774 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] != alpha_scale
) {
775 R200_STATECHANGE( rmesa
, pix
[unit
] );
776 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND
] = color_combine
;
777 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND
] = alpha_combine
;
778 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] = color_scale
;
779 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] = alpha_scale
;
785 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
786 R200_MIN_FILTER_MASK | \
787 R200_MAG_FILTER_MASK | \
788 R200_MAX_ANISO_MASK | \
790 R200_YUV_TEMPERATURE_MASK | \
791 R200_CLAMP_S_MASK | \
792 R200_CLAMP_T_MASK | \
793 R200_BORDER_MODE_D3D )
795 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
796 R200_TXFORMAT_HEIGHT_MASK | \
797 R200_TXFORMAT_FORMAT_MASK | \
798 R200_TXFORMAT_F5_WIDTH_MASK | \
799 R200_TXFORMAT_F5_HEIGHT_MASK | \
800 R200_TXFORMAT_ALPHA_IN_MAP | \
801 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
802 R200_TXFORMAT_NON_POWER2)
804 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
805 R200_TEXCOORD_MASK | \
806 R200_CLAMP_Q_MASK | \
807 R200_VOLUME_FILTER_MASK)
810 static void import_tex_obj_state( r200ContextPtr rmesa
,
812 r200TexObjPtr texobj
)
814 GLuint
*cmd
= R200_DB_STATE( tex
[unit
] );
816 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
817 cmd
[TEX_PP_TXFILTER
] |= texobj
->pp_txfilter
& TEXOBJ_TXFILTER_MASK
;
818 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
819 cmd
[TEX_PP_TXFORMAT
] |= texobj
->pp_txformat
& TEXOBJ_TXFORMAT_MASK
;
820 cmd
[TEX_PP_TXFORMAT_X
] &= ~TEXOBJ_TXFORMAT_X_MASK
;
821 cmd
[TEX_PP_TXFORMAT_X
] |= texobj
->pp_txformat_x
& TEXOBJ_TXFORMAT_X_MASK
;
822 cmd
[TEX_PP_TXSIZE
] = texobj
->pp_txsize
; /* NPOT only! */
823 cmd
[TEX_PP_TXPITCH
] = texobj
->pp_txpitch
; /* NPOT only! */
824 cmd
[TEX_PP_TXOFFSET
] = texobj
->pp_txoffset
;
825 cmd
[TEX_PP_BORDER_COLOR
] = texobj
->pp_border_color
;
826 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.tex
[unit
] );
828 if (texobj
->base
.tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
829 GLuint
*cube_cmd
= R200_DB_STATE( cube
[unit
] );
830 GLuint bytesPerFace
= texobj
->base
.totalSize
/ 6;
831 ASSERT(texobj
->totalSize
% 6 == 0);
832 cube_cmd
[CUBE_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
833 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F1
] = texobj
->pp_txoffset
+ 1 * bytesPerFace
;
834 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F2
] = texobj
->pp_txoffset
+ 2 * bytesPerFace
;
835 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F3
] = texobj
->pp_txoffset
+ 3 * bytesPerFace
;
836 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F4
] = texobj
->pp_txoffset
+ 4 * bytesPerFace
;
837 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F5
] = texobj
->pp_txoffset
+ 5 * bytesPerFace
;
838 R200_DB_STATECHANGE( rmesa
, &rmesa
->hw
.cube
[unit
] );
841 texobj
->dirty_state
&= ~(1<<unit
);
845 static void set_texgen_matrix( r200ContextPtr rmesa
,
847 const GLfloat
*s_plane
,
848 const GLfloat
*t_plane
,
849 const GLfloat
*r_plane
,
850 const GLfloat
*q_plane
)
874 _math_matrix_loadf( &(rmesa
->TexGenMatrix
[unit
]), m
);
875 _math_matrix_analyse( &(rmesa
->TexGenMatrix
[unit
]) );
876 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<<unit
;
881 * Returns GL_FALSE if fallback required.
883 static GLboolean
r200_validate_texgen( GLcontext
*ctx
, GLuint unit
)
885 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
886 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
887 GLuint inputshift
= R200_TEXGEN_0_INPUT_SHIFT
+ unit
*4;
890 GLboolean mixed_fallback
= GL_FALSE
;
891 static const GLfloat I
[16] = {
896 static const GLfloat reflect
[16] = {
902 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
903 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
904 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
905 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
906 tgi
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] & ~(R200_TEXGEN_INPUT_MASK
<<
908 tgcm
= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] & ~(R200_TEXGEN_COMP_MASK
<<
912 fprintf(stderr
, "%s unit %d\n", __FUNCTION__
, unit
);
914 if (texUnit
->TexGenEnabled
& S_BIT
) {
915 mode
= texUnit
->GenModeS
;
917 tgcm
|= R200_TEXGEN_COMP_S
<< (unit
* 4);
920 if (texUnit
->TexGenEnabled
& T_BIT
) {
921 if (texUnit
->GenModeT
!= mode
)
922 mixed_fallback
= GL_TRUE
;
924 tgcm
|= R200_TEXGEN_COMP_T
<< (unit
* 4);
927 if (texUnit
->TexGenEnabled
& R_BIT
) {
928 if (texUnit
->GenModeR
!= mode
)
929 mixed_fallback
= GL_TRUE
;
931 tgcm
|= R200_TEXGEN_COMP_R
<< (unit
* 4);
934 if (texUnit
->TexGenEnabled
& Q_BIT
) {
935 if (texUnit
->GenModeQ
!= mode
)
936 mixed_fallback
= GL_TRUE
;
938 tgcm
|= R200_TEXGEN_COMP_Q
<< (unit
* 4);
941 if (mixed_fallback
) {
942 if (R200_DEBUG
& DEBUG_FALLBACKS
)
943 fprintf(stderr
, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
944 texUnit
->TexGenEnabled
, texUnit
->GenModeS
, texUnit
->GenModeT
,
945 texUnit
->GenModeR
, texUnit
->GenModeQ
);
950 case GL_OBJECT_LINEAR
:
951 tgi
|= R200_TEXGEN_INPUT_OBJ
<< inputshift
;
952 set_texgen_matrix( rmesa
, unit
,
953 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->ObjectPlaneS
: I
,
954 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->ObjectPlaneT
: I
+ 4,
955 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->ObjectPlaneR
: I
+ 8,
956 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->ObjectPlaneQ
: I
+ 12);
960 tgi
|= R200_TEXGEN_INPUT_EYE
<< inputshift
;
961 set_texgen_matrix( rmesa
, unit
,
962 (texUnit
->TexGenEnabled
& S_BIT
) ? texUnit
->EyePlaneS
: I
,
963 (texUnit
->TexGenEnabled
& T_BIT
) ? texUnit
->EyePlaneT
: I
+ 4,
964 (texUnit
->TexGenEnabled
& R_BIT
) ? texUnit
->EyePlaneR
: I
+ 8,
965 (texUnit
->TexGenEnabled
& Q_BIT
) ? texUnit
->EyePlaneQ
: I
+ 12);
968 case GL_REFLECTION_MAP_NV
:
969 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
970 tgi
|= R200_TEXGEN_INPUT_EYE_REFLECT
<<inputshift
;
971 set_texgen_matrix( rmesa
, unit
,
972 (texUnit
->TexGenEnabled
& S_BIT
) ? reflect
: I
,
973 (texUnit
->TexGenEnabled
& T_BIT
) ? reflect
+ 4 : I
+ 4,
974 (texUnit
->TexGenEnabled
& R_BIT
) ? reflect
+ 8 : I
+ 8,
978 case GL_NORMAL_MAP_NV
:
979 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
980 tgi
|= R200_TEXGEN_INPUT_EYE_NORMAL
<<inputshift
;
984 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
985 tgi
|= R200_TEXGEN_INPUT_SPHERE
<<inputshift
;
986 /* GL_SPHERE_MAP doesn't appear to work. */
990 /* All texgen units were disabled, so just pass coords through. */
991 tgi
|= unit
<< inputshift
;
995 /* Unsupported mode, fallback:
997 if (R200_DEBUG
& DEBUG_FALLBACKS
)
998 fprintf(stderr
, "fallback unsupported texgen, %d\n",
1003 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
1004 rmesa
->TexGenCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
1006 if (tgi
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] ||
1007 tgcm
!= rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
])
1009 R200_STATECHANGE(rmesa
, tcg
);
1010 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_1
] = tgi
;
1011 rmesa
->hw
.tcg
.cmd
[TCG_TEX_PROC_CTL_2
] = tgcm
;
1018 static void disable_tex( GLcontext
*ctx
, int unit
)
1020 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1022 if (rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<<unit
)) {
1023 /* Texture unit disabled */
1024 if ( rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
1025 /* The old texture is no longer bound to this texture unit.
1029 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&= ~(1UL << unit
);
1030 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
1033 R200_STATECHANGE( rmesa
, ctx
);
1034 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~((R200_TEX_0_ENABLE
|
1035 R200_TEX_BLEND_0_ENABLE
) << unit
);
1036 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_BLEND_0_ENABLE
;
1038 R200_STATECHANGE( rmesa
, vtx
);
1039 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
1041 if (rmesa
->TclFallback
& (R200_TCL_FALLBACK_TEXGEN_0
<<unit
)) {
1042 TCL_FALLBACK( ctx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), GL_FALSE
);
1045 /* Actually want to keep all units less than max active texture
1046 * enabled, right? Fix this for >2 texunits.
1048 /* FIXME: What should happen here if r200UpdateTextureEnv fails? */
1050 r200UpdateTextureEnv( ctx
, unit
);
1054 GLuint tmp
= rmesa
->TexGenEnabled
;
1056 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<<unit
);
1057 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<<unit
);
1058 rmesa
->TexGenNeedNormals
[unit
] = GL_FALSE
;
1059 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1061 if (tmp
!= rmesa
->TexGenEnabled
) {
1062 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1063 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1069 static void set_re_cntl_d3d( GLcontext
*ctx
, int unit
, GLboolean use_d3d
)
1071 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1075 re_cntl
= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] & ~(R200_VTX_STQ0_D3D
<< (2 * unit
));
1077 re_cntl
|= R200_VTX_STQ0_D3D
<< (2 * unit
);
1079 if ( re_cntl
!= rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] ) {
1080 R200_STATECHANGE( rmesa
, set
);
1081 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] = re_cntl
;
1085 static GLboolean
enable_tex_2d( GLcontext
*ctx
, int unit
)
1087 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1088 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1089 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1090 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1092 /* Need to load the 2d images associated with this unit.
1094 if (t
->pp_txformat
& R200_TXFORMAT_NON_POWER2
) {
1095 t
->pp_txformat
&= ~R200_TXFORMAT_NON_POWER2
;
1096 t
->base
.dirty_images
[0] = ~0;
1099 ASSERT(tObj
->Target
== GL_TEXTURE_2D
|| tObj
->Target
== GL_TEXTURE_1D
);
1101 if ( t
->base
.dirty_images
[0] ) {
1102 R200_FIREVERTICES( rmesa
);
1103 r200SetTexImages( rmesa
, tObj
);
1104 r200UploadTexImages( rmesa
, (r200TexObjPtr
) tObj
->DriverData
, 0 );
1105 if ( !t
->base
.memBlock
)
1109 set_re_cntl_d3d( ctx
, unit
, GL_FALSE
);
1114 #if ENABLE_HW_3D_TEXTURE
1115 static GLboolean
enable_tex_3d( GLcontext
*ctx
, int unit
)
1117 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1118 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1119 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1120 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1122 /* Need to load the 3d images associated with this unit.
1124 if (t
->pp_txformat
& R200_TXFORMAT_NON_POWER2
) {
1125 t
->pp_txformat
&= ~R200_TXFORMAT_NON_POWER2
;
1126 t
->base
.dirty_images
[0] = ~0;
1129 ASSERT(tObj
->Target
== GL_TEXTURE_3D
);
1131 /* R100 & R200 do not support mipmaps for 3D textures.
1133 if ( (tObj
->MinFilter
!= GL_NEAREST
) && (tObj
->MinFilter
!= GL_LINEAR
) ) {
1137 if ( t
->base
.dirty_images
[0] ) {
1138 R200_FIREVERTICES( rmesa
);
1139 r200SetTexImages( rmesa
, tObj
);
1140 r200UploadTexImages( rmesa
, (r200TexObjPtr
) tObj
->DriverData
, 0 );
1141 if ( !t
->base
.memBlock
)
1145 set_re_cntl_d3d( ctx
, unit
, GL_TRUE
);
1151 static GLboolean
enable_tex_cube( GLcontext
*ctx
, int unit
)
1153 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1154 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1155 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1156 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1159 /* Need to load the 2d images associated with this unit.
1161 if (t
->pp_txformat
& R200_TXFORMAT_NON_POWER2
) {
1162 t
->pp_txformat
&= ~R200_TXFORMAT_NON_POWER2
;
1163 for (face
= 0; face
< 6; face
++)
1164 t
->base
.dirty_images
[face
] = ~0;
1167 ASSERT(tObj
->Target
== GL_TEXTURE_CUBE_MAP
);
1169 if ( t
->base
.dirty_images
[0] || t
->base
.dirty_images
[1] ||
1170 t
->base
.dirty_images
[2] || t
->base
.dirty_images
[3] ||
1171 t
->base
.dirty_images
[4] || t
->base
.dirty_images
[5] ) {
1173 R200_FIREVERTICES( rmesa
);
1174 /* layout memory space, once for all faces */
1175 r200SetTexImages( rmesa
, tObj
);
1178 /* upload (per face) */
1179 for (face
= 0; face
< 6; face
++) {
1180 if (t
->base
.dirty_images
[face
]) {
1181 r200UploadTexImages( rmesa
, (r200TexObjPtr
) tObj
->DriverData
, face
);
1185 if ( !t
->base
.memBlock
) {
1186 /* texmem alloc failed, use s/w fallback */
1190 set_re_cntl_d3d( ctx
, unit
, GL_TRUE
);
1195 static GLboolean
enable_tex_rect( GLcontext
*ctx
, int unit
)
1197 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1198 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1199 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1200 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1202 if (!(t
->pp_txformat
& R200_TXFORMAT_NON_POWER2
)) {
1203 t
->pp_txformat
|= R200_TXFORMAT_NON_POWER2
;
1204 t
->base
.dirty_images
[0] = ~0;
1207 ASSERT(tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
1209 if ( t
->base
.dirty_images
[0] ) {
1210 R200_FIREVERTICES( rmesa
);
1211 r200SetTexImages( rmesa
, tObj
);
1212 r200UploadTexImages( rmesa
, (r200TexObjPtr
) tObj
->DriverData
, 0 );
1213 if ( !t
->base
.memBlock
&& !rmesa
->prefer_gart_client_texturing
)
1217 set_re_cntl_d3d( ctx
, unit
, GL_FALSE
);
1223 static GLboolean
update_tex_common( GLcontext
*ctx
, int unit
)
1225 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1226 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1227 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1228 r200TexObjPtr t
= (r200TexObjPtr
) tObj
->DriverData
;
1231 /* Fallback if there's a texture border */
1232 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 )
1235 /* Update state if this is a different texture object to last
1238 if ( rmesa
->state
.texture
.unit
[unit
].texobj
!= t
) {
1239 if ( rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
1240 /* The old texture is no longer bound to this texture unit.
1244 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&=
1248 rmesa
->state
.texture
.unit
[unit
].texobj
= t
;
1249 t
->base
.bound
|= (1UL << unit
);
1250 t
->dirty_state
|= 1<<unit
;
1251 driUpdateTextureLRU( (driTextureObject
*) t
); /* XXX: should be locked! */
1257 if ( 1|| !(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<<unit
))) {
1258 R200_STATECHANGE( rmesa
, ctx
);
1259 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= (R200_TEX_0_ENABLE
|
1260 R200_TEX_BLEND_0_ENABLE
) << unit
;
1262 R200_STATECHANGE( rmesa
, vtx
);
1263 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &= ~(7 << (unit
* 3));
1264 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] |= 4 << (unit
* 3);
1266 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1269 if (t
->dirty_state
& (1<<unit
)) {
1270 import_tex_obj_state( rmesa
, unit
, t
);
1273 if (rmesa
->recheck_texgen
[unit
]) {
1274 GLboolean fallback
= !r200_validate_texgen( ctx
, unit
);
1275 TCL_FALLBACK( ctx
, (R200_TCL_FALLBACK_TEXGEN_0
<<unit
), fallback
);
1276 rmesa
->recheck_texgen
[unit
] = 0;
1277 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1280 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1281 if ( rmesa
->state
.texture
.unit
[unit
].format
!= format
||
1282 rmesa
->state
.texture
.unit
[unit
].envMode
!= texUnit
->EnvMode
) {
1283 rmesa
->state
.texture
.unit
[unit
].format
= format
;
1284 rmesa
->state
.texture
.unit
[unit
].envMode
= texUnit
->EnvMode
;
1285 if ( ! r200UpdateTextureEnv( ctx
, unit
) ) {
1290 FALLBACK( rmesa
, R200_FALLBACK_BORDER_MODE
, t
->border_fallback
);
1291 return !t
->border_fallback
;
1296 static GLboolean
r200UpdateTextureUnit( GLcontext
*ctx
, int unit
)
1298 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1300 if ( texUnit
->_ReallyEnabled
& (TEXTURE_RECT_BIT
) ) {
1301 return (enable_tex_rect( ctx
, unit
) &&
1302 update_tex_common( ctx
, unit
));
1304 else if ( texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
) ) {
1305 return (enable_tex_2d( ctx
, unit
) &&
1306 update_tex_common( ctx
, unit
));
1308 #if ENABLE_HW_3D_TEXTURE
1309 else if ( texUnit
->_ReallyEnabled
& (TEXTURE_3D_BIT
) ) {
1310 return (enable_tex_3d( ctx
, unit
) &&
1311 update_tex_common( ctx
, unit
));
1314 else if ( texUnit
->_ReallyEnabled
& (TEXTURE_CUBE_BIT
) ) {
1315 return (enable_tex_cube( ctx
, unit
) &&
1316 update_tex_common( ctx
, unit
));
1318 else if ( texUnit
->_ReallyEnabled
) {
1322 disable_tex( ctx
, unit
);
1328 void r200UpdateTextureState( GLcontext
*ctx
)
1330 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
1334 ok
= (r200UpdateTextureUnit( ctx
, 0 ) &&
1335 r200UpdateTextureUnit( ctx
, 1 ) &&
1336 r200UpdateTextureUnit( ctx
, 2 ) &&
1337 r200UpdateTextureUnit( ctx
, 3 ) &&
1338 r200UpdateTextureUnit( ctx
, 4 ) &&
1339 r200UpdateTextureUnit( ctx
, 5 ));
1341 FALLBACK( rmesa
, R200_FALLBACK_TEXTURE
, !ok
);
1343 if (rmesa
->TclFallback
)
1344 r200ChooseVertexState( ctx
);
1347 if (rmesa
->r200Screen
->chipset
& R200_CHIPSET_REAL_R200
) {
1350 * T0 hang workaround -------------
1351 * not needed for r200 derivatives?
1353 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_ENABLE_MASK
) == R200_TEX_0_ENABLE
&&
1354 (rmesa
->hw
.tex
[0].cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) > R200_MIN_FILTER_LINEAR
) {
1356 R200_STATECHANGE(rmesa
, ctx
);
1357 R200_STATECHANGE(rmesa
, tex
[1]);
1358 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_1_ENABLE
;
1359 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
1360 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] |= 0x08000000;
1363 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
) &&
1364 (rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] & 0x08000000)) {
1365 R200_STATECHANGE(rmesa
, tex
[1]);
1366 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &= ~0x08000000;
1370 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1371 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1372 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1373 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1374 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1375 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1376 R200_MIN_FILTER_LINEAR)) {
1377 R200_STATECHANGE(rmesa, ctx);
1378 R200_STATECHANGE(rmesa, tex[i+1]);
1379 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1380 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1381 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1384 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1385 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1386 R200_STATECHANGE(rmesa, tex[i+1]);
1387 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1393 * Texture cache LRU hang workaround -------------
1394 * not needed for r200 derivatives?
1397 /* While the cases below attempt to only enable the workaround in the
1398 * specific cases necessary, they were insufficient. See bugzilla #1519,
1399 * #729, #814. Tests with quake3 showed no impact on performance.
1404 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) &&
1405 ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1407 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1408 ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1410 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1411 ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1417 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) &&
1418 ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1420 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1421 ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1423 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1424 ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1430 if (dbg
!= rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
]) {
1431 R200_STATECHANGE( rmesa
, tam
);
1432 rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
] = dbg
;
1433 if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg
);