1 /* $XFree86: xc/lib/GL/mesa/src/drv/r300/r300_texstate.c,v 1.3 2003/02/15 22:18:47 dawes Exp $ */
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
33 * Keith Whitwell <keith@tungstengraphics.com>
40 #include "texformat.h"
43 #include "r300_context.h"
44 #include "r300_state.h"
45 #include "r300_ioctl.h"
46 #include "radeon_ioctl.h"
47 //#include "r300_swtcl.h"
49 //#include "r300_tcl.h"
52 #define R200_TXFORMAT_A8 R200_TXFORMAT_I8
53 #define R200_TXFORMAT_L8 R200_TXFORMAT_I8
54 #define R200_TXFORMAT_AL88 R200_TXFORMAT_AI88
55 #define R200_TXFORMAT_YCBCR R200_TXFORMAT_YVYU422
56 #define R200_TXFORMAT_YCBCR_REV R200_TXFORMAT_VYUY422
59 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, 0 }
60 #define _COLOR_REV(f) \
61 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f, 0 }
63 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
64 #define _ALPHA_REV(f) \
65 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
67 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, R200_YUV_TO_RGB }
69 [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
70 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_YCBCR_REV) \
73 #define _ASSIGN(entry, format) \
74 [ MESA_FORMAT_ ## entry ] = { format, 0, 1}
77 GLuint format
, filter
;
100 static const struct {
101 GLuint format
, filter
, flag
;
104 * Note that the _REV formats are the same as the non-REV formats.
105 * This is because the REV and non-REV formats are identical as a
106 * byte string, but differ when accessed as 16-bit or 32-bit words
107 * depending on the endianness of the host. Since the textures are
108 * transferred to the R300 as a byte string (i.e. without any
109 * byte-swapping), the R300 sees the REV and non-REV formats
110 * identically. -- paulus
112 _ASSIGN(RGBA8888
, R300_EASY_TX_FORMAT(Y
, Z
, W
, X
, W8Z8Y8X8
)),
113 _ASSIGN(RGBA8888_REV
, R300_EASY_TX_FORMAT(Y
, Z
, W
, X
, W8Z8Y8X8
)),
114 _ASSIGN(ARGB8888
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W8Z8Y8X8
)),
115 _ASSIGN(ARGB8888_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W8Z8Y8X8
)),
116 _ASSIGN(RGB888
, 0xffffffff),
117 _ASSIGN(RGB565
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z5Y6X5
)),
118 _ASSIGN(RGB565_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z5Y6X5
)),
119 _ASSIGN(ARGB4444
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W4Z4Y4X4
)),
120 _ASSIGN(ARGB4444_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W4Z4Y4X4
)),
121 _ASSIGN(ARGB1555
, R300_EASY_TX_FORMAT(Z
, Y
, X
, W
, W1Z5Y5X5
)),
122 _ASSIGN(ARGB1555_REV
, R300_EASY_TX_FORMAT(Z
, Y
, X
, W
, W1Z5Y5X5
)),
123 _ASSIGN(AL88
, R300_EASY_TX_FORMAT(Y
, Y
, Y
, X
, Y8X8
)),
124 _ASSIGN(AL88_REV
, R300_EASY_TX_FORMAT(Y
, Y
, Y
, X
, Y8X8
)),
125 _ASSIGN(RGB332
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z3Y3X2
)),
126 _ASSIGN(A8
, R300_EASY_TX_FORMAT(ZERO
, ZERO
, ZERO
, X
, X8
)),
127 _ASSIGN(L8
, R300_EASY_TX_FORMAT(X
, X
, X
, ONE
, X8
)),
128 _ASSIGN(I8
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X8
)),
129 _ASSIGN(CI8
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X8
)),
130 _ASSIGN(YCBCR
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, G8R8_G8B8
)|R300_TX_FORMAT_YUV_MODE
),
131 _ASSIGN(YCBCR_REV
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, G8R8_G8B8
)|R300_TX_FORMAT_YUV_MODE
),
141 * This function computes the number of bytes of storage needed for
142 * the given texture object (all mipmap levels, all cube faces).
143 * The \c image[face][level].x/y/width/height parameters for upload/blitting
144 * are computed here. \c filter, \c format, etc. will be set here
147 * \param rmesa Context pointer
148 * \param tObj GL texture object whose images are to be posted to
151 static void r300SetTexImages(r300ContextPtr rmesa
,
152 struct gl_texture_object
*tObj
)
154 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
155 const struct gl_texture_image
*baseImage
=
156 tObj
->Image
[0][tObj
->BaseLevel
];
160 GLint log2Width
, log2Height
, log2Depth
;
162 /* Set the hardware texture format
165 t
->format
&= ~(R200_TXFORMAT_FORMAT_MASK
|
166 R200_TXFORMAT_ALPHA_IN_MAP
);
168 t
->filter
&= ~R200_YUV_TO_RGB
;
170 if (VALID_FORMAT(baseImage
->TexFormat
->MesaFormat
)) {
172 tx_table
[baseImage
->TexFormat
->MesaFormat
].format
;
175 tx_table
[baseImage
->TexFormat
->MesaFormat
].filter
;
178 _mesa_problem(NULL
, "unexpected texture format in %s",
183 /* Compute which mipmap levels we really want to send to the hardware.
186 driCalculateTextureFirstLastLevel((driTextureObject
*) t
);
187 log2Width
= tObj
->Image
[0][t
->base
.firstLevel
]->WidthLog2
;
188 log2Height
= tObj
->Image
[0][t
->base
.firstLevel
]->HeightLog2
;
189 log2Depth
= tObj
->Image
[0][t
->base
.firstLevel
]->DepthLog2
;
191 numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
193 assert(numLevels
<= RADEON_MAX_TEXTURE_LEVELS
);
195 /* Calculate mipmap offsets and dimensions for blitting (uploading)
196 * The idea is that we lay out the mipmap levels within a block of
197 * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
201 for (i
= 0; i
< numLevels
; i
++) {
202 const struct gl_texture_image
*texImage
;
205 texImage
= tObj
->Image
[0][i
+ t
->base
.firstLevel
];
209 /* find image size in bytes */
210 if (texImage
->IsCompressed
) {
211 size
= texImage
->CompressedSize
;
212 } else if (tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
) {
215 texImage
->TexFormat
->TexelBytes
+ 63)
216 & ~63) * texImage
->Height
;
219 texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
222 size
= w
* texImage
->Height
* texImage
->Depth
;
227 fprintf(stderr
, "w=%d h=%d d=%d tb=%d intFormat=%d\n", texImage
->Width
, texImage
->Height
,
228 texImage
->Depth
, texImage
->TexFormat
->TexelBytes
,
229 texImage
->IntFormat
);
231 /* Align to 32-byte offset. It is faster to do this unconditionally
232 * (no branch penalty).
235 curOffset
= (curOffset
+ 0x1f) & ~0x1f;
237 t
->image
[0][i
].x
= curOffset
% BLIT_WIDTH_BYTES
;
238 t
->image
[0][i
].y
= curOffset
/ BLIT_WIDTH_BYTES
;
239 t
->image
[0][i
].width
= MIN2(size
, BLIT_WIDTH_BYTES
);
240 t
->image
[0][i
].height
= size
/ t
->image
[0][i
].width
;
243 /* for debugging only and only applicable to non-rectangle targets */
244 assert(size
% t
->image
[0][i
].width
== 0);
245 assert(t
->image
[0][i
].x
== 0
246 || (size
< BLIT_WIDTH_BYTES
247 && t
->image
[0][i
].height
== 1));
252 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
253 i
, texImage
->Width
, texImage
->Height
,
254 t
->image
[0][i
].x
, t
->image
[0][i
].y
,
255 t
->image
[0][i
].width
, t
->image
[0][i
].height
,
262 /* Align the total size of texture memory block.
265 (curOffset
+ RADEON_OFFSET_MASK
) & ~RADEON_OFFSET_MASK
;
267 /* Setup remaining cube face blits, if needed */
268 if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
269 /* Round totalSize up to multiple of BLIT_WIDTH_BYTES */
270 const GLuint faceSize
=
271 (t
->base
.totalSize
+ BLIT_WIDTH_BYTES
- 1)
272 & ~(BLIT_WIDTH_BYTES
- 1);
273 const GLuint lines
= faceSize
/ BLIT_WIDTH_BYTES
;
275 /* reuse face 0 x/y/width/height - just adjust y */
276 for (face
= 1; face
< 6; face
++) {
277 for (i
= 0; i
< numLevels
; i
++) {
278 t
->image
[face
][i
].x
= t
->image
[0][i
].x
;
279 t
->image
[face
][i
].y
=
280 t
->image
[0][i
].y
+ face
* lines
;
281 t
->image
[face
][i
].width
= t
->image
[0][i
].width
;
282 t
->image
[face
][i
].height
=
283 t
->image
[0][i
].height
;
286 t
->base
.totalSize
= 6 * faceSize
; /* total texmem needed */
292 t
->filter
&= ~R200_MAX_MIP_LEVEL_MASK
;
293 t
->filter
|= (numLevels
- 1) << R200_MAX_MIP_LEVEL_SHIFT
;
296 t
->format
&= ~(R200_TXFORMAT_WIDTH_MASK
|
297 R200_TXFORMAT_HEIGHT_MASK
|
298 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
299 R200_TXFORMAT_F5_WIDTH_MASK
|
300 R200_TXFORMAT_F5_HEIGHT_MASK
);
301 t
->format
|= ((log2Width
<< R200_TXFORMAT_WIDTH_SHIFT
) |
302 (log2Height
<< R200_TXFORMAT_HEIGHT_SHIFT
));
305 t
->format_x
&= ~(R200_DEPTH_LOG2_MASK
| R200_TEXCOORD_MASK
);
306 if (tObj
->Target
== GL_TEXTURE_3D
) {
307 t
->format_x
|= (log2Depth
<< R200_DEPTH_LOG2_SHIFT
);
308 t
->format_x
|= R200_TEXCOORD_VOLUME
;
309 } else if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
310 ASSERT(log2Width
== log2Height
);
311 t
->format
|= ((log2Width
<< R200_TXFORMAT_F5_WIDTH_SHIFT
) |
312 (log2Height
<< R200_TXFORMAT_F5_HEIGHT_SHIFT
)
313 | (R200_TXFORMAT_CUBIC_MAP_ENABLE
));
314 t
->format_x
|= R200_TEXCOORD_CUBIC_ENV
;
315 t
->pp_cubic_faces
= ((log2Width
<< R200_FACE_WIDTH_1_SHIFT
) |
316 (log2Height
<< R200_FACE_HEIGHT_1_SHIFT
) |
317 (log2Width
<< R200_FACE_WIDTH_2_SHIFT
) |
318 (log2Height
<< R200_FACE_HEIGHT_2_SHIFT
) |
319 (log2Width
<< R200_FACE_WIDTH_3_SHIFT
) |
320 (log2Height
<< R200_FACE_HEIGHT_3_SHIFT
) |
321 (log2Width
<< R200_FACE_WIDTH_4_SHIFT
) |
322 (log2Height
<< R200_FACE_HEIGHT_4_SHIFT
));
325 t
->size
= (((tObj
->Image
[0][t
->base
.firstLevel
]->Width
- 1) << R300_TX_WIDTHMASK_SHIFT
)
326 |((tObj
->Image
[0][t
->base
.firstLevel
]->Height
- 1) << R300_TX_HEIGHTMASK_SHIFT
)
327 |((log2Width
>log2Height
)?log2Width
:log2Height
)<<R300_TX_SIZE_SHIFT
);
329 /* Only need to round to nearest 32 for textures, but the blitter
330 * requires 64-byte aligned pitches, and we may/may not need the
331 * blitter. NPOT only!
333 if (baseImage
->IsCompressed
)
335 (tObj
->Image
[0][t
->base
.firstLevel
]->Width
+ 63) & ~(63);
338 ((tObj
->Image
[0][t
->base
.firstLevel
]->Width
*
339 baseImage
->TexFormat
->TexelBytes
) + 63) & ~(63);
342 t
->dirty_state
= TEX_ALL
;
344 /* FYI: r300UploadTexImages( rmesa, t ) used to be called here */
347 /* ================================================================
348 * Texture combine functions
351 /* GL_ARB_texture_env_combine support
354 /* The color tables have combine functions for GL_SRC_COLOR,
355 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
357 static GLuint r300_register_color
[][R200_MAX_TEXTURE_UNITS
] = {
359 R200_TXC_ARG_A_R0_COLOR
,
360 R200_TXC_ARG_A_R1_COLOR
,
361 R200_TXC_ARG_A_R2_COLOR
,
362 R200_TXC_ARG_A_R3_COLOR
,
363 R200_TXC_ARG_A_R4_COLOR
,
364 R200_TXC_ARG_A_R5_COLOR
},
366 R200_TXC_ARG_A_R0_COLOR
| R200_TXC_COMP_ARG_A
,
367 R200_TXC_ARG_A_R1_COLOR
| R200_TXC_COMP_ARG_A
,
368 R200_TXC_ARG_A_R2_COLOR
| R200_TXC_COMP_ARG_A
,
369 R200_TXC_ARG_A_R3_COLOR
| R200_TXC_COMP_ARG_A
,
370 R200_TXC_ARG_A_R4_COLOR
| R200_TXC_COMP_ARG_A
,
371 R200_TXC_ARG_A_R5_COLOR
| R200_TXC_COMP_ARG_A
},
373 R200_TXC_ARG_A_R0_ALPHA
,
374 R200_TXC_ARG_A_R1_ALPHA
,
375 R200_TXC_ARG_A_R2_ALPHA
,
376 R200_TXC_ARG_A_R3_ALPHA
,
377 R200_TXC_ARG_A_R4_ALPHA
,
378 R200_TXC_ARG_A_R5_ALPHA
},
380 R200_TXC_ARG_A_R0_ALPHA
| R200_TXC_COMP_ARG_A
,
381 R200_TXC_ARG_A_R1_ALPHA
| R200_TXC_COMP_ARG_A
,
382 R200_TXC_ARG_A_R2_ALPHA
| R200_TXC_COMP_ARG_A
,
383 R200_TXC_ARG_A_R3_ALPHA
| R200_TXC_COMP_ARG_A
,
384 R200_TXC_ARG_A_R4_ALPHA
| R200_TXC_COMP_ARG_A
,
385 R200_TXC_ARG_A_R5_ALPHA
| R200_TXC_COMP_ARG_A
},
388 static GLuint r300_tfactor_color
[] = {
389 R200_TXC_ARG_A_TFACTOR_COLOR
,
390 R200_TXC_ARG_A_TFACTOR_COLOR
| R200_TXC_COMP_ARG_A
,
391 R200_TXC_ARG_A_TFACTOR_ALPHA
,
392 R200_TXC_ARG_A_TFACTOR_ALPHA
| R200_TXC_COMP_ARG_A
395 static GLuint r300_primary_color
[] = {
396 R200_TXC_ARG_A_DIFFUSE_COLOR
,
397 R200_TXC_ARG_A_DIFFUSE_COLOR
| R200_TXC_COMP_ARG_A
,
398 R200_TXC_ARG_A_DIFFUSE_ALPHA
,
399 R200_TXC_ARG_A_DIFFUSE_ALPHA
| R200_TXC_COMP_ARG_A
402 /* GL_ZERO table - indices 0-3
403 * GL_ONE table - indices 1-4
405 static GLuint r300_zero_color
[] = {
407 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
409 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
413 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
415 static GLuint r300_register_alpha
[][R200_MAX_TEXTURE_UNITS
] = {
417 R200_TXA_ARG_A_R0_ALPHA
,
418 R200_TXA_ARG_A_R1_ALPHA
,
419 R200_TXA_ARG_A_R2_ALPHA
,
420 R200_TXA_ARG_A_R3_ALPHA
,
421 R200_TXA_ARG_A_R4_ALPHA
,
422 R200_TXA_ARG_A_R5_ALPHA
},
424 R200_TXA_ARG_A_R0_ALPHA
| R200_TXA_COMP_ARG_A
,
425 R200_TXA_ARG_A_R1_ALPHA
| R200_TXA_COMP_ARG_A
,
426 R200_TXA_ARG_A_R2_ALPHA
| R200_TXA_COMP_ARG_A
,
427 R200_TXA_ARG_A_R3_ALPHA
| R200_TXA_COMP_ARG_A
,
428 R200_TXA_ARG_A_R4_ALPHA
| R200_TXA_COMP_ARG_A
,
429 R200_TXA_ARG_A_R5_ALPHA
| R200_TXA_COMP_ARG_A
},
432 static GLuint r300_tfactor_alpha
[] = {
433 R200_TXA_ARG_A_TFACTOR_ALPHA
,
434 R200_TXA_ARG_A_TFACTOR_ALPHA
| R200_TXA_COMP_ARG_A
437 static GLuint r300_primary_alpha
[] = {
438 R200_TXA_ARG_A_DIFFUSE_ALPHA
,
439 R200_TXA_ARG_A_DIFFUSE_ALPHA
| R200_TXA_COMP_ARG_A
442 /* GL_ZERO table - indices 0-1
443 * GL_ONE table - indices 1-2
445 static GLuint r300_zero_alpha
[] = {
447 R200_TXA_ARG_A_ZERO
| R200_TXA_COMP_ARG_A
,
451 /* Extract the arg from slot A, shift it into the correct argument slot
452 * and set the corresponding complement bit.
454 #define R200_COLOR_ARG( n, arg ) \
457 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
458 << R200_TXC_ARG_##arg##_SHIFT); \
460 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
461 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
464 #define R200_ALPHA_ARG( n, arg ) \
467 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
468 << R200_TXA_ARG_##arg##_SHIFT); \
470 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
471 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
474 /* ================================================================
475 * Texture unit state management
478 static GLboolean
r300UpdateTextureEnv(GLcontext
* ctx
, int unit
)
480 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
481 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
482 GLuint color_combine
, alpha_combine
;
484 #if 0 /* disable for now.. */
485 GLuint color_scale
= rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] &
486 ~(R200_TXC_SCALE_MASK
);
487 GLuint alpha_scale
= rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] &
488 ~(R200_TXA_DOT_ALPHA
| R200_TXA_SCALE_MASK
);
491 GLuint color_scale
=0, alpha_scale
=0;
493 /* texUnit->_Current can be NULL if and only if the texture unit is
494 * not actually enabled.
496 assert((texUnit
->_ReallyEnabled
== 0)
497 || (texUnit
->_Current
!= NULL
));
499 if (RADEON_DEBUG
& DEBUG_TEXTURE
) {
500 fprintf(stderr
, "%s( %p, %d )\n", __FUNCTION__
, (void *)ctx
,
504 /* Set the texture environment state. Isn't this nice and clean?
505 * The chip will automagically set the texture alpha to 0xff when
506 * the texture format does not include an alpha component. This
507 * reduces the amount of special-casing we have to do, alpha-only
508 * textures being a notable exception.
510 /* Don't cache these results.
513 rmesa
->state
.texture
.unit
[unit
].format
= 0;
515 rmesa
->state
.texture
.unit
[unit
].envMode
= 0;
518 if (!texUnit
->_ReallyEnabled
) {
521 R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
|
522 R200_TXC_ARG_C_DIFFUSE_COLOR
| R200_TXC_OP_MADD
;
524 R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
|
525 R200_TXA_ARG_C_DIFFUSE_ALPHA
| R200_TXA_OP_MADD
;
528 R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
|
529 R200_TXC_ARG_C_R0_COLOR
| R200_TXC_OP_MADD
;
531 R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
|
532 R200_TXA_ARG_C_R0_ALPHA
| R200_TXA_OP_MADD
;
535 GLuint color_arg
[3], alpha_arg
[3];
537 const GLuint numColorArgs
=
538 texUnit
->_CurrentCombine
->_NumArgsRGB
;
539 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
540 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
541 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
544 * Extract the color and alpha combine function arguments.
546 for (i
= 0; i
< numColorArgs
; i
++) {
548 texUnit
->_CurrentCombine
->OperandRGB
[i
] -
552 switch (texUnit
->_CurrentCombine
->SourceRGB
[i
]) {
554 color_arg
[i
] = r300_register_color
[op
][unit
];
557 color_arg
[i
] = r300_tfactor_color
[op
];
559 case GL_PRIMARY_COLOR
:
560 color_arg
[i
] = r300_primary_color
[op
];
564 color_arg
[i
] = r300_primary_color
[op
];
567 r300_register_color
[op
][0];
570 color_arg
[i
] = r300_zero_color
[op
];
573 color_arg
[i
] = r300_zero_color
[op
+ 1];
580 for (i
= 0; i
< numAlphaArgs
; i
++) {
582 texUnit
->_CurrentCombine
->OperandA
[i
] -
586 switch (texUnit
->_CurrentCombine
->SourceA
[i
]) {
588 alpha_arg
[i
] = r300_register_alpha
[op
][unit
];
591 alpha_arg
[i
] = r300_tfactor_alpha
[op
];
593 case GL_PRIMARY_COLOR
:
594 alpha_arg
[i
] = r300_primary_alpha
[op
];
598 alpha_arg
[i
] = r300_primary_alpha
[op
];
601 r300_register_alpha
[op
][0];
604 alpha_arg
[i
] = r300_zero_alpha
[op
];
607 alpha_arg
[i
] = r300_zero_alpha
[op
+ 1];
615 * Build up the color and alpha combine functions.
617 switch (texUnit
->_CurrentCombine
->ModeRGB
) {
619 color_combine
= (R200_TXC_ARG_A_ZERO
|
620 R200_TXC_ARG_B_ZERO
|
622 R200_COLOR_ARG(0, C
);
625 color_combine
= (R200_TXC_ARG_C_ZERO
|
627 R200_COLOR_ARG(0, A
);
628 R200_COLOR_ARG(1, B
);
631 color_combine
= (R200_TXC_ARG_B_ZERO
|
632 R200_TXC_COMP_ARG_B
|
634 R200_COLOR_ARG(0, A
);
635 R200_COLOR_ARG(1, C
);
638 color_combine
= (R200_TXC_ARG_B_ZERO
| R200_TXC_COMP_ARG_B
| R200_TXC_BIAS_ARG_C
| /* new */
639 R200_TXC_OP_MADD
); /* was ADDSIGNED */
640 R200_COLOR_ARG(0, A
);
641 R200_COLOR_ARG(1, C
);
644 color_combine
= (R200_TXC_ARG_B_ZERO
|
645 R200_TXC_COMP_ARG_B
|
646 R200_TXC_NEG_ARG_C
| R200_TXC_OP_MADD
);
647 R200_COLOR_ARG(0, A
);
648 R200_COLOR_ARG(1, C
);
651 color_combine
= (R200_TXC_OP_LERP
);
652 R200_COLOR_ARG(0, B
);
653 R200_COLOR_ARG(1, A
);
654 R200_COLOR_ARG(2, C
);
657 case GL_DOT3_RGB_EXT
:
658 case GL_DOT3_RGBA_EXT
:
659 /* The EXT version of the DOT3 extension does not support the
660 * scale factor, but the ARB version (and the version in OpenGL
668 /* DOT3 works differently on R200 than on R100. On R100, just
669 * setting the DOT3 mode did everything for you. On R200, the
670 * driver has to enable the biasing and scale in the inputs to
671 * put them in the proper [-1,1] range. This is what the 4x and
672 * the -0.5 in the DOT3 spec do. The post-scale is then set
676 color_combine
= (R200_TXC_ARG_C_ZERO
|
678 R200_TXC_BIAS_ARG_A
|
679 R200_TXC_BIAS_ARG_B
|
680 R200_TXC_SCALE_ARG_A
|
681 R200_TXC_SCALE_ARG_B
);
682 R200_COLOR_ARG(0, A
);
683 R200_COLOR_ARG(1, B
);
686 case GL_MODULATE_ADD_ATI
:
687 color_combine
= (R200_TXC_OP_MADD
);
688 R200_COLOR_ARG(0, A
);
689 R200_COLOR_ARG(1, C
);
690 R200_COLOR_ARG(2, B
);
692 case GL_MODULATE_SIGNED_ADD_ATI
:
693 color_combine
= (R200_TXC_BIAS_ARG_C
| /* new */
694 R200_TXC_OP_MADD
); /* was ADDSIGNED */
695 R200_COLOR_ARG(0, A
);
696 R200_COLOR_ARG(1, C
);
697 R200_COLOR_ARG(2, B
);
699 case GL_MODULATE_SUBTRACT_ATI
:
700 color_combine
= (R200_TXC_NEG_ARG_C
| R200_TXC_OP_MADD
);
701 R200_COLOR_ARG(0, A
);
702 R200_COLOR_ARG(1, C
);
703 R200_COLOR_ARG(2, B
);
709 switch (texUnit
->_CurrentCombine
->ModeA
) {
711 alpha_combine
= (R200_TXA_ARG_A_ZERO
|
712 R200_TXA_ARG_B_ZERO
|
714 R200_ALPHA_ARG(0, C
);
717 alpha_combine
= (R200_TXA_ARG_C_ZERO
|
719 R200_ALPHA_ARG(0, A
);
720 R200_ALPHA_ARG(1, B
);
723 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
724 R200_TXA_COMP_ARG_B
|
726 R200_ALPHA_ARG(0, A
);
727 R200_ALPHA_ARG(1, C
);
730 alpha_combine
= (R200_TXA_ARG_B_ZERO
| R200_TXA_COMP_ARG_B
| R200_TXA_BIAS_ARG_C
| /* new */
731 R200_TXA_OP_MADD
); /* was ADDSIGNED */
732 R200_ALPHA_ARG(0, A
);
733 R200_ALPHA_ARG(1, C
);
736 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
737 R200_TXA_COMP_ARG_B
|
738 R200_TXA_NEG_ARG_C
| R200_TXA_OP_MADD
);
739 R200_ALPHA_ARG(0, A
);
740 R200_ALPHA_ARG(1, C
);
743 alpha_combine
= (R200_TXA_OP_LERP
);
744 R200_ALPHA_ARG(0, B
);
745 R200_ALPHA_ARG(1, A
);
746 R200_ALPHA_ARG(2, C
);
749 case GL_MODULATE_ADD_ATI
:
750 alpha_combine
= (R200_TXA_OP_MADD
);
751 R200_ALPHA_ARG(0, A
);
752 R200_ALPHA_ARG(1, C
);
753 R200_ALPHA_ARG(2, B
);
755 case GL_MODULATE_SIGNED_ADD_ATI
:
756 alpha_combine
= (R200_TXA_BIAS_ARG_C
| /* new */
757 R200_TXA_OP_MADD
); /* was ADDSIGNED */
758 R200_ALPHA_ARG(0, A
);
759 R200_ALPHA_ARG(1, C
);
760 R200_ALPHA_ARG(2, B
);
762 case GL_MODULATE_SUBTRACT_ATI
:
763 alpha_combine
= (R200_TXA_NEG_ARG_C
| R200_TXA_OP_MADD
);
764 R200_ALPHA_ARG(0, A
);
765 R200_ALPHA_ARG(1, C
);
766 R200_ALPHA_ARG(2, B
);
772 if ((texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
773 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
)) {
774 alpha_scale
|= R200_TXA_DOT_ALPHA
;
779 * Apply the scale factor.
781 color_scale
|= (RGBshift
<< R200_TXC_SCALE_SHIFT
);
782 alpha_scale
|= (Ashift
<< R200_TXA_SCALE_SHIFT
);
789 fprintf(stderr
, "color_combine=%08x alpha_combine=%08x color_scale=%08x alpha_scale=%08x\n",
790 color_combine
, alpha_combine
, color_scale
, alpha_scale
);
794 if (rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND
] != color_combine
||
795 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND
] != alpha_combine
||
796 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] != color_scale
||
797 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] != alpha_scale
) {
798 R300_STATECHANGE(rmesa
, pix
[unit
]);
799 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND
] = color_combine
;
800 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND
] = alpha_combine
;
801 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] = color_scale
;
802 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] = alpha_scale
;
810 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
811 R200_MIN_FILTER_MASK | \
812 R200_MAG_FILTER_MASK | \
813 R200_MAX_ANISO_MASK | \
815 R200_YUV_TEMPERATURE_MASK | \
816 R200_CLAMP_S_MASK | \
817 R200_CLAMP_T_MASK | \
818 R200_BORDER_MODE_D3D )
820 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
821 R200_TXFORMAT_HEIGHT_MASK | \
822 R200_TXFORMAT_FORMAT_MASK | \
823 R200_TXFORMAT_F5_WIDTH_MASK | \
824 R200_TXFORMAT_F5_HEIGHT_MASK | \
825 R200_TXFORMAT_ALPHA_IN_MAP | \
826 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
827 R200_TXFORMAT_NON_POWER2)
829 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
830 R200_TEXCOORD_MASK | \
831 R200_CLAMP_Q_MASK | \
832 R200_VOLUME_FILTER_MASK)
834 static void import_tex_obj_state(r300ContextPtr rmesa
,
835 int unit
, r300TexObjPtr texobj
)
837 #if 0 /* needs fixing.. or should be done elsewhere */
838 GLuint
*cmd
= R300_DB_STATE(tex
[unit
]);
840 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
841 cmd
[TEX_PP_TXFILTER
] |= texobj
->filter
& TEXOBJ_TXFILTER_MASK
;
842 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
843 cmd
[TEX_PP_TXFORMAT
] |= texobj
->format
& TEXOBJ_TXFORMAT_MASK
;
844 cmd
[TEX_PP_TXFORMAT_X
] &= ~TEXOBJ_TXFORMAT_X_MASK
;
845 cmd
[TEX_PP_TXFORMAT_X
] |=
846 texobj
->format_x
& TEXOBJ_TXFORMAT_X_MASK
;
847 cmd
[TEX_PP_TXSIZE
] = texobj
->size
; /* NPOT only! */
848 cmd
[TEX_PP_TXPITCH
] = texobj
->pitch
; /* NPOT only! */
849 cmd
[TEX_PP_TXOFFSET
] = texobj
->pp_txoffset
;
850 cmd
[TEX_PP_BORDER_COLOR
] = texobj
->pp_border_color
;
851 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.tex
[unit
]);
853 if (texobj
->base
.tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
854 GLuint
*cube_cmd
= R200_DB_STATE(cube
[unit
]);
855 GLuint bytesPerFace
= texobj
->base
.totalSize
/ 6;
856 ASSERT(texobj
->totalSize
% 6 == 0);
857 cube_cmd
[CUBE_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
858 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F1
] =
859 texobj
->pp_txoffset
+ 1 * bytesPerFace
;
860 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F2
] =
861 texobj
->pp_txoffset
+ 2 * bytesPerFace
;
862 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F3
] =
863 texobj
->pp_txoffset
+ 3 * bytesPerFace
;
864 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F4
] =
865 texobj
->pp_txoffset
+ 4 * bytesPerFace
;
866 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F5
] =
867 texobj
->pp_txoffset
+ 5 * bytesPerFace
;
868 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.cube
[unit
]);
871 texobj
->dirty_state
&= ~(1 << unit
);
875 static void set_texgen_matrix(r300ContextPtr rmesa
,
877 const GLfloat
* s_plane
,
878 const GLfloat
* t_plane
, const GLfloat
* r_plane
)
880 static const GLfloat scale_identity
[4] = { 1, 1, 1, 1 };
882 if (!TEST_EQ_4V(s_plane
, scale_identity
) ||
883 !TEST_EQ_4V(t_plane
, scale_identity
) ||
884 !TEST_EQ_4V(r_plane
, scale_identity
)) {
885 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<< unit
;
886 rmesa
->TexGenMatrix
[unit
].m
[0] = s_plane
[0];
887 rmesa
->TexGenMatrix
[unit
].m
[4] = s_plane
[1];
888 rmesa
->TexGenMatrix
[unit
].m
[8] = s_plane
[2];
889 rmesa
->TexGenMatrix
[unit
].m
[12] = s_plane
[3];
891 rmesa
->TexGenMatrix
[unit
].m
[1] = t_plane
[0];
892 rmesa
->TexGenMatrix
[unit
].m
[5] = t_plane
[1];
893 rmesa
->TexGenMatrix
[unit
].m
[9] = t_plane
[2];
894 rmesa
->TexGenMatrix
[unit
].m
[13] = t_plane
[3];
896 /* NOTE: r_plane goes in the 4th row, not 3rd! */
897 rmesa
->TexGenMatrix
[unit
].m
[3] = r_plane
[0];
898 rmesa
->TexGenMatrix
[unit
].m
[7] = r_plane
[1];
899 rmesa
->TexGenMatrix
[unit
].m
[11] = r_plane
[2];
900 rmesa
->TexGenMatrix
[unit
].m
[15] = r_plane
[3];
902 //rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
906 /* Need this special matrix to get correct reflection map coords */
907 static void set_texgen_reflection_matrix(r300ContextPtr rmesa
, GLuint unit
)
909 static const GLfloat m
[16] = {
915 _math_matrix_loadf(&(rmesa
->TexGenMatrix
[unit
]), m
);
916 _math_matrix_analyse(&(rmesa
->TexGenMatrix
[unit
]));
917 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<< unit
;
920 /* Need this special matrix to get correct normal map coords */
921 static void set_texgen_normal_map_matrix(r300ContextPtr rmesa
, GLuint unit
)
923 static const GLfloat m
[16] = {
929 _math_matrix_loadf(&(rmesa
->TexGenMatrix
[unit
]), m
);
930 _math_matrix_analyse(&(rmesa
->TexGenMatrix
[unit
]));
931 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<< unit
;
934 /* Ignoring the Q texcoord for now.
936 * Returns GL_FALSE if fallback required.
938 static GLboolean
r300_validate_texgen(GLcontext
* ctx
, GLuint unit
)
940 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
941 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
942 GLuint inputshift
= R200_TEXGEN_0_INPUT_SHIFT
+ unit
* 4;
943 GLuint tmp
= rmesa
->TexGenEnabled
;
945 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
946 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
);
947 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<< unit
);
948 rmesa
->TexGenInputs
&= ~(R200_TEXGEN_INPUT_MASK
<< inputshift
);
949 rmesa
->TexGenNeedNormals
[unit
] = 0;
952 fprintf(stderr
, "%s unit %d\n", __FUNCTION__
, unit
);
954 if ((texUnit
->TexGenEnabled
& (S_BIT
| T_BIT
| R_BIT
)) == 0) {
955 /* Disabled, no fallback:
957 rmesa
->TexGenInputs
|=
958 (R200_TEXGEN_INPUT_TEXCOORD_0
+ unit
) << inputshift
;
960 } else if (texUnit
->TexGenEnabled
& Q_BIT
) {
961 /* Very easy to do this, in fact would remove a fallback case
962 * elsewhere, but I haven't done it yet... Fallback:
964 /*fprintf(stderr, "fallback Q_BIT\n"); */
966 } else if (texUnit
->TexGenEnabled
== (S_BIT
| T_BIT
) &&
967 texUnit
->GenModeS
== texUnit
->GenModeT
) {
969 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
971 } else if (texUnit
->TexGenEnabled
== (S_BIT
| T_BIT
| R_BIT
) &&
972 texUnit
->GenModeS
== texUnit
->GenModeT
&&
973 texUnit
->GenModeT
== texUnit
->GenModeR
) {
975 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
978 /* Mixed modes, fallback:
980 /* fprintf(stderr, "fallback mixed texgen\n"); */
984 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
986 switch (texUnit
->GenModeS
) {
987 case GL_OBJECT_LINEAR
:
988 rmesa
->TexGenInputs
|= R200_TEXGEN_INPUT_OBJ
<< inputshift
;
989 set_texgen_matrix(rmesa
, unit
,
990 texUnit
->ObjectPlaneS
,
991 texUnit
->ObjectPlaneT
, texUnit
->ObjectPlaneR
);
995 rmesa
->TexGenInputs
|= R200_TEXGEN_INPUT_EYE
<< inputshift
;
996 set_texgen_matrix(rmesa
, unit
,
998 texUnit
->EyePlaneT
, texUnit
->EyePlaneR
);
1001 case GL_REFLECTION_MAP_NV
:
1002 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1003 rmesa
->TexGenInputs
|=
1004 R200_TEXGEN_INPUT_EYE_REFLECT
<< inputshift
;
1005 set_texgen_reflection_matrix(rmesa
, unit
);
1008 case GL_NORMAL_MAP_NV
:
1009 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1010 rmesa
->TexGenInputs
|=
1011 R200_TEXGEN_INPUT_EYE_NORMAL
<< inputshift
;
1012 set_texgen_normal_map_matrix(rmesa
, unit
);
1016 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1017 rmesa
->TexGenInputs
|= R200_TEXGEN_INPUT_SPHERE
<< inputshift
;
1021 /* Unsupported mode, fallback:
1023 /* fprintf(stderr, "fallback unsupported texgen\n"); */
1027 rmesa
->TexGenCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
1029 if (tmp
!= rmesa
->TexGenEnabled
) {
1030 //rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1036 static void disable_tex(GLcontext
* ctx
, int unit
)
1038 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1040 #if 0 /* This needs to be redone.. or done elsewhere */
1041 if (rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<< unit
)) {
1042 /* Texture unit disabled */
1043 if (rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
1044 /* The old texture is no longer bound to this texture unit.
1048 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&=
1050 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
1053 R300_STATECHANGE(rmesa
, ctx
);
1054 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~((R200_TEX_0_ENABLE
|
1055 R200_TEX_BLEND_0_ENABLE
) <<
1057 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_BLEND_0_ENABLE
;
1059 R300_STATECHANGE(rmesa
, tcl
);
1060 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &=
1063 if (rmesa
->radeon
.TclFallback
& (RADEON_TCL_FALLBACK_TEXGEN_0
<< unit
)) {
1064 TCL_FALLBACK(ctx
, (RADEON_TCL_FALLBACK_TEXGEN_0
<< unit
),
1068 /* Actually want to keep all units less than max active texture
1069 * enabled, right? Fix this for >2 texunits.
1071 /* FIXME: What should happen here if r300UpdateTextureEnv fails? */
1073 r300UpdateTextureEnv(ctx
, unit
);
1077 R200_TEXGEN_0_INPUT_SHIFT
+ unit
* 4;
1078 GLuint tmp
= rmesa
->TexGenEnabled
;
1080 rmesa
->TexGenEnabled
&=
1081 ~(R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
);
1082 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<< unit
);
1083 rmesa
->TexGenEnabled
&=
1084 ~(R200_TEXGEN_INPUT_MASK
<< inputshift
);
1085 rmesa
->TexGenNeedNormals
[unit
] = 0;
1086 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1087 rmesa
->TexGenInputs
&=
1088 ~(R200_TEXGEN_INPUT_MASK
<< inputshift
);
1090 if (tmp
!= rmesa
->TexGenEnabled
) {
1091 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1092 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1099 static GLboolean
enable_tex_2d(GLcontext
* ctx
, int unit
)
1101 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1102 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1103 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1104 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1106 /* Need to load the 2d images associated with this unit.
1109 if (t
->format
& R200_TXFORMAT_NON_POWER2
) {
1110 t
->format
&= ~R200_TXFORMAT_NON_POWER2
;
1111 t
->base
.dirty_images
[0] = ~0;
1115 ASSERT(tObj
->Target
== GL_TEXTURE_2D
|| tObj
->Target
== GL_TEXTURE_1D
);
1117 if (t
->base
.dirty_images
[0]) {
1118 R300_FIREVERTICES(rmesa
);
1119 r300SetTexImages(rmesa
, tObj
);
1120 r300UploadTexImages(rmesa
, (r300TexObjPtr
) tObj
->DriverData
, 0);
1121 if (!t
->base
.memBlock
)
1128 #if ENABLE_HW_3D_TEXTURE
1129 static GLboolean
enable_tex_3d(GLcontext
* ctx
, int unit
)
1131 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1132 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1133 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1134 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1136 /* Need to load the 3d images associated with this unit.
1138 if (t
->format
& R200_TXFORMAT_NON_POWER2
) {
1139 t
->format
&= ~R200_TXFORMAT_NON_POWER2
;
1140 t
->base
.dirty_images
[0] = ~0;
1143 ASSERT(tObj
->Target
== GL_TEXTURE_3D
);
1145 /* R100 & R200 do not support mipmaps for 3D textures.
1147 if ((tObj
->MinFilter
!= GL_NEAREST
) && (tObj
->MinFilter
!= GL_LINEAR
)) {
1151 if (t
->base
.dirty_images
[0]) {
1152 R300_FIREVERTICES(rmesa
);
1153 r300SetTexImages(rmesa
, tObj
);
1154 r300UploadTexImages(rmesa
, (r300TexObjPtr
) tObj
->DriverData
, 0);
1155 if (!t
->base
.memBlock
)
1163 static GLboolean
enable_tex_cube(GLcontext
* ctx
, int unit
)
1165 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1166 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1167 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1168 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1171 /* Need to load the 2d images associated with this unit.
1173 if (t
->format
& R200_TXFORMAT_NON_POWER2
) {
1174 t
->format
&= ~R200_TXFORMAT_NON_POWER2
;
1175 for (face
= 0; face
< 6; face
++)
1176 t
->base
.dirty_images
[face
] = ~0;
1179 ASSERT(tObj
->Target
== GL_TEXTURE_CUBE_MAP
);
1181 if (t
->base
.dirty_images
[0] || t
->base
.dirty_images
[1] ||
1182 t
->base
.dirty_images
[2] || t
->base
.dirty_images
[3] ||
1183 t
->base
.dirty_images
[4] || t
->base
.dirty_images
[5]) {
1185 R300_FIREVERTICES(rmesa
);
1186 /* layout memory space, once for all faces */
1187 r300SetTexImages(rmesa
, tObj
);
1190 /* upload (per face) */
1191 for (face
= 0; face
< 6; face
++) {
1192 if (t
->base
.dirty_images
[face
]) {
1193 r300UploadTexImages(rmesa
,
1194 (r300TexObjPtr
) tObj
->DriverData
,
1199 if (!t
->base
.memBlock
) {
1200 /* texmem alloc failed, use s/w fallback */
1207 static GLboolean
enable_tex_rect(GLcontext
* ctx
, int unit
)
1209 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1210 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1211 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1212 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1215 if (!(t
->format
& R200_TXFORMAT_NON_POWER2
)) {
1216 t
->format
|= R200_TXFORMAT_NON_POWER2
;
1217 t
->base
.dirty_images
[0] = ~0;
1221 ASSERT(tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
);
1223 if (t
->base
.dirty_images
[0]) {
1224 R300_FIREVERTICES(rmesa
);
1225 r300SetTexImages(rmesa
, tObj
);
1226 r300UploadTexImages(rmesa
, (r300TexObjPtr
) tObj
->DriverData
, 0);
1227 if (!t
->base
.memBlock
&& !rmesa
->prefer_gart_client_texturing
)
1234 static GLboolean
update_tex_common(GLcontext
* ctx
, int unit
)
1236 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1237 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1238 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1239 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1242 /* Fallback if there's a texture border */
1243 if (tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0)
1246 /* Update state if this is a different texture object to last
1249 if (rmesa
->state
.texture
.unit
[unit
].texobj
!= t
) {
1250 if (rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
1251 /* The old texture is no longer bound to this texture unit.
1255 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&=
1259 rmesa
->state
.texture
.unit
[unit
].texobj
= t
;
1260 t
->base
.bound
|= (1UL << unit
);
1261 t
->dirty_state
|= 1 << unit
;
1262 driUpdateTextureLRU((driTextureObject
*) t
); /* XXX: should be locked! */
1265 #if 0 /* do elsewhere ? */
1270 cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<< unit
))) {
1271 R300_STATECHANGE(rmesa
, ctx
);
1272 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= (R200_TEX_0_ENABLE
|
1273 R200_TEX_BLEND_0_ENABLE
) <<
1276 R300_STATECHANGE(rmesa
, vtx
);
1277 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] |= 4 << (unit
* 3);
1279 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1282 if (t
->dirty_state
& (1 << unit
)) {
1283 import_tex_obj_state(rmesa
, unit
, t
);
1286 if (rmesa
->recheck_texgen
[unit
]) {
1287 GLboolean fallback
= !r300_validate_texgen(ctx
, unit
);
1288 TCL_FALLBACK(ctx
, (RADEON_TCL_FALLBACK_TEXGEN_0
<< unit
),
1290 rmesa
->recheck_texgen
[unit
] = 0;
1291 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1295 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1296 if (rmesa
->state
.texture
.unit
[unit
].format
!= format
||
1297 rmesa
->state
.texture
.unit
[unit
].envMode
!= texUnit
->EnvMode
) {
1298 //rmesa->state.texture.unit[unit].format = format;
1299 rmesa
->state
.texture
.unit
[unit
].envMode
= texUnit
->EnvMode
;
1300 if (!r300UpdateTextureEnv(ctx
, unit
)) {
1306 FALLBACK(&rmesa
->radeon
, RADEON_FALLBACK_BORDER_MODE
, t
->border_fallback
);
1309 return !t
->border_fallback
;
1312 static GLboolean
r300UpdateTextureUnit(GLcontext
* ctx
, int unit
)
1314 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1316 if (texUnit
->_ReallyEnabled
& (TEXTURE_RECT_BIT
)) {
1317 return (enable_tex_rect(ctx
, unit
) &&
1318 update_tex_common(ctx
, unit
));
1319 } else if (texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
)) {
1320 return (enable_tex_2d(ctx
, unit
) &&
1321 update_tex_common(ctx
, unit
));
1323 #if ENABLE_HW_3D_TEXTURE
1324 else if (texUnit
->_ReallyEnabled
& (TEXTURE_3D_BIT
)) {
1325 return (enable_tex_3d(ctx
, unit
) &&
1326 update_tex_common(ctx
, unit
));
1329 else if (texUnit
->_ReallyEnabled
& (TEXTURE_CUBE_BIT
)) {
1330 return (enable_tex_cube(ctx
, unit
) &&
1331 update_tex_common(ctx
, unit
));
1332 } else if (texUnit
->_ReallyEnabled
) {
1335 disable_tex(ctx
, unit
);
1340 void r300UpdateTextureState(GLcontext
* ctx
)
1342 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1347 ok
= (r300UpdateTextureUnit(ctx
, 0) &&
1348 r300UpdateTextureUnit(ctx
, 1) &&
1349 r300UpdateTextureUnit(ctx
, 2) &&
1350 r300UpdateTextureUnit(ctx
, 3) &&
1351 r300UpdateTextureUnit(ctx
, 4) &&
1352 r300UpdateTextureUnit(ctx
, 5) &&
1353 r300UpdateTextureUnit(ctx
, 6) &&
1354 r300UpdateTextureUnit(ctx
, 7)
1358 FALLBACK(&rmesa
->radeon
, RADEON_FALLBACK_TEXTURE
, !ok
);
1361 /* This needs correction, or just be done elsewhere
1362 if (rmesa->radeon.TclFallback)
1363 r300ChooseVertexState(ctx);
1366 #if 0 /* Workaround - disable.. */
1367 if (GET_CHIP(rmesa
->radeon
.radeonScreen
) == RADEON_CHIP_REAL_R200
) {
1369 * T0 hang workaround -------------
1370 * not needed for r200 derivatives?
1372 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_ENABLE_MASK
) ==
1374 && (rmesa
->hw
.tex
[0].
1375 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) >
1376 R200_MIN_FILTER_LINEAR
) {
1378 R300_STATECHANGE(rmesa
, ctx
);
1379 R300_STATECHANGE(rmesa
, tex
[1]);
1380 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_1_ENABLE
;
1381 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &=
1382 ~TEXOBJ_TXFORMAT_MASK
;
1383 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] |= 0x08000000;
1385 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
)
1386 && (rmesa
->hw
.tex
[1].
1387 cmd
[TEX_PP_TXFORMAT
] & 0x08000000)) {
1388 R300_STATECHANGE(rmesa
, tex
[1]);
1389 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &=
1394 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1395 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1396 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1397 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1398 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1399 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1400 R200_MIN_FILTER_LINEAR)) {
1401 R300_STATECHANGE(rmesa, ctx);
1402 R300_STATECHANGE(rmesa, tex[i+1]);
1403 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1404 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1405 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1408 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1409 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1410 R300_STATECHANGE(rmesa, tex[i+1]);
1411 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1417 * Texture cache LRU hang workaround -------------
1418 * not needed for r200 derivatives?
1422 if (((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
)) &&
1423 ((((rmesa
->hw
.tex
[0].
1424 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) & 0x04)
1426 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_2_ENABLE
)
1428 ((((rmesa
->hw
.tex
[2].
1429 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1431 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_4_ENABLE
)
1433 ((((rmesa
->hw
.tex
[4].
1434 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1439 if (((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_1_ENABLE
)) &&
1440 ((((rmesa
->hw
.tex
[1].
1441 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) & 0x04)
1443 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_3_ENABLE
)
1445 ((((rmesa
->hw
.tex
[3].
1446 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1448 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_5_ENABLE
)
1450 ((((rmesa
->hw
.tex
[5].
1451 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1456 if (dbg
!= rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
]) {
1457 R300_STATECHANGE(rmesa
, tam
);
1458 rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
] = dbg
;
1460 printf("TEXCACHE LRU HANG WORKAROUND %x\n",