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
;
103 _ASSIGN(RGBA8888
, R300_EASY_TX_FORMAT(Y
, Z
, W
, X
, W8Z8Y8X8
)),
104 _ASSIGN(RGBA8888_REV
, R300_EASY_TX_FORMAT(Z
, Y
, X
, W
, W8Z8Y8X8
)),
105 _ASSIGN(ARGB8888
, R300_EASY_TX_FORMAT(X
, Y
, Z
, W
, W8Z8Y8X8
)),
106 _ASSIGN(ARGB8888_REV
, R300_EASY_TX_FORMAT(W
, Z
, Y
, X
, W8Z8Y8X8
)),
107 _ASSIGN(RGB888
, 0xffffffff),
108 _ASSIGN(RGB565
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, Z5Y6X5
)),
109 _ASSIGN(RGB565_REV
, 0xffffff01),
110 _ASSIGN(ARGB4444
, R300_EASY_TX_FORMAT(Y
, Z
, W
, X
, W4Z4Y4X4
)),
111 _ASSIGN(ARGB4444_REV
, 0xffffff02),
112 _ASSIGN(ARGB1555
, R300_EASY_TX_FORMAT(Z
, Y
, X
, W
, W1Z5Y5X5
)),
113 _ASSIGN(ARGB1555_REV
, 0xffffff04),
114 _ASSIGN(AL88
, R300_EASY_TX_FORMAT(Y
, Y
, Y
, X
, Y8X8
)),
115 _ASSIGN(AL88_REV
, 0xffffff05),
116 _ASSIGN(A8
, 0xffffff06),
117 _ASSIGN(L8
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X8
)),
118 _ASSIGN(I8
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X8
)),
119 _ASSIGN(CI8
, R300_EASY_TX_FORMAT(X
, X
, X
, X
, X8
)),
120 _ASSIGN(YCBCR
, R300_EASY_TX_FORMAT(X
, Y
, Z
, ONE
, G8R8_G8B8
)|R300_TX_FORMAT_YUV_MODE
),
121 _ASSIGN(YCBCR_REV
, 0xffffff08),
131 * This function computes the number of bytes of storage needed for
132 * the given texture object (all mipmap levels, all cube faces).
133 * The \c image[face][level].x/y/width/height parameters for upload/blitting
134 * are computed here. \c filter, \c format, etc. will be set here
137 * \param rmesa Context pointer
138 * \param tObj GL texture object whose images are to be posted to
141 static void r300SetTexImages(r300ContextPtr rmesa
,
142 struct gl_texture_object
*tObj
)
144 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
145 const struct gl_texture_image
*baseImage
=
146 tObj
->Image
[0][tObj
->BaseLevel
];
150 GLint log2Width
, log2Height
, log2Depth
;
152 /* Set the hardware texture format
155 t
->format
&= ~(R200_TXFORMAT_FORMAT_MASK
|
156 R200_TXFORMAT_ALPHA_IN_MAP
);
158 t
->filter
&= ~R200_YUV_TO_RGB
;
160 if (VALID_FORMAT(baseImage
->TexFormat
->MesaFormat
)) {
162 tx_table
[baseImage
->TexFormat
->MesaFormat
].format
;
165 tx_table
[baseImage
->TexFormat
->MesaFormat
].filter
;
168 _mesa_problem(NULL
, "unexpected texture format in %s",
173 /* Compute which mipmap levels we really want to send to the hardware.
176 driCalculateTextureFirstLastLevel((driTextureObject
*) t
);
177 log2Width
= tObj
->Image
[0][t
->base
.firstLevel
]->WidthLog2
;
178 log2Height
= tObj
->Image
[0][t
->base
.firstLevel
]->HeightLog2
;
179 log2Depth
= tObj
->Image
[0][t
->base
.firstLevel
]->DepthLog2
;
181 numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
183 assert(numLevels
<= RADEON_MAX_TEXTURE_LEVELS
);
185 /* Calculate mipmap offsets and dimensions for blitting (uploading)
186 * The idea is that we lay out the mipmap levels within a block of
187 * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
191 for (i
= 0; i
< numLevels
; i
++) {
192 const struct gl_texture_image
*texImage
;
195 texImage
= tObj
->Image
[0][i
+ t
->base
.firstLevel
];
199 /* find image size in bytes */
200 if (texImage
->IsCompressed
) {
201 size
= texImage
->CompressedSize
;
202 } else if (tObj
->Target
== GL_TEXTURE_RECTANGLE_NV
) {
205 texImage
->TexFormat
->TexelBytes
+ 63)
206 & ~63) * texImage
->Height
;
209 texImage
->Width
* texImage
->TexFormat
->TexelBytes
;
212 size
= w
* texImage
->Height
* texImage
->Depth
;
217 fprintf(stderr
, "w=%d h=%d d=%d tb=%d intFormat=%d\n", texImage
->Width
, texImage
->Height
,
218 texImage
->Depth
, texImage
->TexFormat
->TexelBytes
,
219 texImage
->IntFormat
);
221 /* Align to 32-byte offset. It is faster to do this unconditionally
222 * (no branch penalty).
225 curOffset
= (curOffset
+ 0x1f) & ~0x1f;
227 t
->image
[0][i
].x
= curOffset
% BLIT_WIDTH_BYTES
;
228 t
->image
[0][i
].y
= curOffset
/ BLIT_WIDTH_BYTES
;
229 t
->image
[0][i
].width
= MIN2(size
, BLIT_WIDTH_BYTES
);
230 t
->image
[0][i
].height
= size
/ t
->image
[0][i
].width
;
233 /* for debugging only and only applicable to non-rectangle targets */
234 assert(size
% t
->image
[0][i
].width
== 0);
235 assert(t
->image
[0][i
].x
== 0
236 || (size
< BLIT_WIDTH_BYTES
237 && t
->image
[0][i
].height
== 1));
242 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
243 i
, texImage
->Width
, texImage
->Height
,
244 t
->image
[0][i
].x
, t
->image
[0][i
].y
,
245 t
->image
[0][i
].width
, t
->image
[0][i
].height
,
252 /* Align the total size of texture memory block.
255 (curOffset
+ RADEON_OFFSET_MASK
) & ~RADEON_OFFSET_MASK
;
257 /* Setup remaining cube face blits, if needed */
258 if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
259 /* Round totalSize up to multiple of BLIT_WIDTH_BYTES */
260 const GLuint faceSize
=
261 (t
->base
.totalSize
+ BLIT_WIDTH_BYTES
- 1)
262 & ~(BLIT_WIDTH_BYTES
- 1);
263 const GLuint lines
= faceSize
/ BLIT_WIDTH_BYTES
;
265 /* reuse face 0 x/y/width/height - just adjust y */
266 for (face
= 1; face
< 6; face
++) {
267 for (i
= 0; i
< numLevels
; i
++) {
268 t
->image
[face
][i
].x
= t
->image
[0][i
].x
;
269 t
->image
[face
][i
].y
=
270 t
->image
[0][i
].y
+ face
* lines
;
271 t
->image
[face
][i
].width
= t
->image
[0][i
].width
;
272 t
->image
[face
][i
].height
=
273 t
->image
[0][i
].height
;
276 t
->base
.totalSize
= 6 * faceSize
; /* total texmem needed */
282 t
->filter
&= ~R200_MAX_MIP_LEVEL_MASK
;
283 t
->filter
|= (numLevels
- 1) << R200_MAX_MIP_LEVEL_SHIFT
;
286 t
->format
&= ~(R200_TXFORMAT_WIDTH_MASK
|
287 R200_TXFORMAT_HEIGHT_MASK
|
288 R200_TXFORMAT_CUBIC_MAP_ENABLE
|
289 R200_TXFORMAT_F5_WIDTH_MASK
|
290 R200_TXFORMAT_F5_HEIGHT_MASK
);
291 t
->format
|= ((log2Width
<< R200_TXFORMAT_WIDTH_SHIFT
) |
292 (log2Height
<< R200_TXFORMAT_HEIGHT_SHIFT
));
295 t
->format_x
&= ~(R200_DEPTH_LOG2_MASK
| R200_TEXCOORD_MASK
);
296 if (tObj
->Target
== GL_TEXTURE_3D
) {
297 t
->format_x
|= (log2Depth
<< R200_DEPTH_LOG2_SHIFT
);
298 t
->format_x
|= R200_TEXCOORD_VOLUME
;
299 } else if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
300 ASSERT(log2Width
== log2Height
);
301 t
->format
|= ((log2Width
<< R200_TXFORMAT_F5_WIDTH_SHIFT
) |
302 (log2Height
<< R200_TXFORMAT_F5_HEIGHT_SHIFT
)
303 | (R200_TXFORMAT_CUBIC_MAP_ENABLE
));
304 t
->format_x
|= R200_TEXCOORD_CUBIC_ENV
;
305 t
->pp_cubic_faces
= ((log2Width
<< R200_FACE_WIDTH_1_SHIFT
) |
306 (log2Height
<< R200_FACE_HEIGHT_1_SHIFT
) |
307 (log2Width
<< R200_FACE_WIDTH_2_SHIFT
) |
308 (log2Height
<< R200_FACE_HEIGHT_2_SHIFT
) |
309 (log2Width
<< R200_FACE_WIDTH_3_SHIFT
) |
310 (log2Height
<< R200_FACE_HEIGHT_3_SHIFT
) |
311 (log2Width
<< R200_FACE_WIDTH_4_SHIFT
) |
312 (log2Height
<< R200_FACE_HEIGHT_4_SHIFT
));
315 t
->size
= (((tObj
->Image
[0][t
->base
.firstLevel
]->Width
- 1) << R300_TX_WIDTHMASK_SHIFT
)
316 |((tObj
->Image
[0][t
->base
.firstLevel
]->Height
- 1) << R300_TX_HEIGHTMASK_SHIFT
)
317 |((log2Width
>log2Height
)?log2Width
:log2Height
)<<R300_TX_SIZE_SHIFT
);
319 /* Only need to round to nearest 32 for textures, but the blitter
320 * requires 64-byte aligned pitches, and we may/may not need the
321 * blitter. NPOT only!
323 if (baseImage
->IsCompressed
)
325 (tObj
->Image
[0][t
->base
.firstLevel
]->Width
+ 63) & ~(63);
328 ((tObj
->Image
[0][t
->base
.firstLevel
]->Width
*
329 baseImage
->TexFormat
->TexelBytes
) + 63) & ~(63);
332 t
->dirty_state
= TEX_ALL
;
334 /* FYI: r300UploadTexImages( rmesa, t ) used to be called here */
337 /* ================================================================
338 * Texture combine functions
341 /* GL_ARB_texture_env_combine support
344 /* The color tables have combine functions for GL_SRC_COLOR,
345 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
347 static GLuint r300_register_color
[][R200_MAX_TEXTURE_UNITS
] = {
349 R200_TXC_ARG_A_R0_COLOR
,
350 R200_TXC_ARG_A_R1_COLOR
,
351 R200_TXC_ARG_A_R2_COLOR
,
352 R200_TXC_ARG_A_R3_COLOR
,
353 R200_TXC_ARG_A_R4_COLOR
,
354 R200_TXC_ARG_A_R5_COLOR
},
356 R200_TXC_ARG_A_R0_COLOR
| R200_TXC_COMP_ARG_A
,
357 R200_TXC_ARG_A_R1_COLOR
| R200_TXC_COMP_ARG_A
,
358 R200_TXC_ARG_A_R2_COLOR
| R200_TXC_COMP_ARG_A
,
359 R200_TXC_ARG_A_R3_COLOR
| R200_TXC_COMP_ARG_A
,
360 R200_TXC_ARG_A_R4_COLOR
| R200_TXC_COMP_ARG_A
,
361 R200_TXC_ARG_A_R5_COLOR
| R200_TXC_COMP_ARG_A
},
363 R200_TXC_ARG_A_R0_ALPHA
,
364 R200_TXC_ARG_A_R1_ALPHA
,
365 R200_TXC_ARG_A_R2_ALPHA
,
366 R200_TXC_ARG_A_R3_ALPHA
,
367 R200_TXC_ARG_A_R4_ALPHA
,
368 R200_TXC_ARG_A_R5_ALPHA
},
370 R200_TXC_ARG_A_R0_ALPHA
| R200_TXC_COMP_ARG_A
,
371 R200_TXC_ARG_A_R1_ALPHA
| R200_TXC_COMP_ARG_A
,
372 R200_TXC_ARG_A_R2_ALPHA
| R200_TXC_COMP_ARG_A
,
373 R200_TXC_ARG_A_R3_ALPHA
| R200_TXC_COMP_ARG_A
,
374 R200_TXC_ARG_A_R4_ALPHA
| R200_TXC_COMP_ARG_A
,
375 R200_TXC_ARG_A_R5_ALPHA
| R200_TXC_COMP_ARG_A
},
378 static GLuint r300_tfactor_color
[] = {
379 R200_TXC_ARG_A_TFACTOR_COLOR
,
380 R200_TXC_ARG_A_TFACTOR_COLOR
| R200_TXC_COMP_ARG_A
,
381 R200_TXC_ARG_A_TFACTOR_ALPHA
,
382 R200_TXC_ARG_A_TFACTOR_ALPHA
| R200_TXC_COMP_ARG_A
385 static GLuint r300_primary_color
[] = {
386 R200_TXC_ARG_A_DIFFUSE_COLOR
,
387 R200_TXC_ARG_A_DIFFUSE_COLOR
| R200_TXC_COMP_ARG_A
,
388 R200_TXC_ARG_A_DIFFUSE_ALPHA
,
389 R200_TXC_ARG_A_DIFFUSE_ALPHA
| R200_TXC_COMP_ARG_A
392 /* GL_ZERO table - indices 0-3
393 * GL_ONE table - indices 1-4
395 static GLuint r300_zero_color
[] = {
397 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
399 R200_TXC_ARG_A_ZERO
| R200_TXC_COMP_ARG_A
,
403 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
405 static GLuint r300_register_alpha
[][R200_MAX_TEXTURE_UNITS
] = {
407 R200_TXA_ARG_A_R0_ALPHA
,
408 R200_TXA_ARG_A_R1_ALPHA
,
409 R200_TXA_ARG_A_R2_ALPHA
,
410 R200_TXA_ARG_A_R3_ALPHA
,
411 R200_TXA_ARG_A_R4_ALPHA
,
412 R200_TXA_ARG_A_R5_ALPHA
},
414 R200_TXA_ARG_A_R0_ALPHA
| R200_TXA_COMP_ARG_A
,
415 R200_TXA_ARG_A_R1_ALPHA
| R200_TXA_COMP_ARG_A
,
416 R200_TXA_ARG_A_R2_ALPHA
| R200_TXA_COMP_ARG_A
,
417 R200_TXA_ARG_A_R3_ALPHA
| R200_TXA_COMP_ARG_A
,
418 R200_TXA_ARG_A_R4_ALPHA
| R200_TXA_COMP_ARG_A
,
419 R200_TXA_ARG_A_R5_ALPHA
| R200_TXA_COMP_ARG_A
},
422 static GLuint r300_tfactor_alpha
[] = {
423 R200_TXA_ARG_A_TFACTOR_ALPHA
,
424 R200_TXA_ARG_A_TFACTOR_ALPHA
| R200_TXA_COMP_ARG_A
427 static GLuint r300_primary_alpha
[] = {
428 R200_TXA_ARG_A_DIFFUSE_ALPHA
,
429 R200_TXA_ARG_A_DIFFUSE_ALPHA
| R200_TXA_COMP_ARG_A
432 /* GL_ZERO table - indices 0-1
433 * GL_ONE table - indices 1-2
435 static GLuint r300_zero_alpha
[] = {
437 R200_TXA_ARG_A_ZERO
| R200_TXA_COMP_ARG_A
,
441 /* Extract the arg from slot A, shift it into the correct argument slot
442 * and set the corresponding complement bit.
444 #define R200_COLOR_ARG( n, arg ) \
447 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
448 << R200_TXC_ARG_##arg##_SHIFT); \
450 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
451 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
454 #define R200_ALPHA_ARG( n, arg ) \
457 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
458 << R200_TXA_ARG_##arg##_SHIFT); \
460 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
461 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
464 /* ================================================================
465 * Texture unit state management
468 static GLboolean
r300UpdateTextureEnv(GLcontext
* ctx
, int unit
)
470 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
471 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
472 GLuint color_combine
, alpha_combine
;
474 #if 0 /* disable for now.. */
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
);
481 GLuint color_scale
=0, alpha_scale
=0;
483 /* texUnit->_Current can be NULL if and only if the texture unit is
484 * not actually enabled.
486 assert((texUnit
->_ReallyEnabled
== 0)
487 || (texUnit
->_Current
!= NULL
));
489 if (RADEON_DEBUG
& DEBUG_TEXTURE
) {
490 fprintf(stderr
, "%s( %p, %d )\n", __FUNCTION__
, (void *)ctx
,
494 /* Set the texture environment state. Isn't this nice and clean?
495 * The chip will automagically set the texture alpha to 0xff when
496 * the texture format does not include an alpha component. This
497 * reduces the amount of special-casing we have to do, alpha-only
498 * textures being a notable exception.
500 /* Don't cache these results.
503 rmesa
->state
.texture
.unit
[unit
].format
= 0;
505 rmesa
->state
.texture
.unit
[unit
].envMode
= 0;
508 if (!texUnit
->_ReallyEnabled
) {
511 R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
|
512 R200_TXC_ARG_C_DIFFUSE_COLOR
| R200_TXC_OP_MADD
;
514 R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
|
515 R200_TXA_ARG_C_DIFFUSE_ALPHA
| R200_TXA_OP_MADD
;
518 R200_TXC_ARG_A_ZERO
| R200_TXC_ARG_B_ZERO
|
519 R200_TXC_ARG_C_R0_COLOR
| R200_TXC_OP_MADD
;
521 R200_TXA_ARG_A_ZERO
| R200_TXA_ARG_B_ZERO
|
522 R200_TXA_ARG_C_R0_ALPHA
| R200_TXA_OP_MADD
;
525 GLuint color_arg
[3], alpha_arg
[3];
527 const GLuint numColorArgs
=
528 texUnit
->_CurrentCombine
->_NumArgsRGB
;
529 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
530 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
531 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
534 * Extract the color and alpha combine function arguments.
536 for (i
= 0; i
< numColorArgs
; i
++) {
538 texUnit
->_CurrentCombine
->OperandRGB
[i
] -
542 switch (texUnit
->_CurrentCombine
->SourceRGB
[i
]) {
544 color_arg
[i
] = r300_register_color
[op
][unit
];
547 color_arg
[i
] = r300_tfactor_color
[op
];
549 case GL_PRIMARY_COLOR
:
550 color_arg
[i
] = r300_primary_color
[op
];
554 color_arg
[i
] = r300_primary_color
[op
];
557 r300_register_color
[op
][0];
560 color_arg
[i
] = r300_zero_color
[op
];
563 color_arg
[i
] = r300_zero_color
[op
+ 1];
570 for (i
= 0; i
< numAlphaArgs
; i
++) {
572 texUnit
->_CurrentCombine
->OperandA
[i
] -
576 switch (texUnit
->_CurrentCombine
->SourceA
[i
]) {
578 alpha_arg
[i
] = r300_register_alpha
[op
][unit
];
581 alpha_arg
[i
] = r300_tfactor_alpha
[op
];
583 case GL_PRIMARY_COLOR
:
584 alpha_arg
[i
] = r300_primary_alpha
[op
];
588 alpha_arg
[i
] = r300_primary_alpha
[op
];
591 r300_register_alpha
[op
][0];
594 alpha_arg
[i
] = r300_zero_alpha
[op
];
597 alpha_arg
[i
] = r300_zero_alpha
[op
+ 1];
605 * Build up the color and alpha combine functions.
607 switch (texUnit
->_CurrentCombine
->ModeRGB
) {
609 color_combine
= (R200_TXC_ARG_A_ZERO
|
610 R200_TXC_ARG_B_ZERO
|
612 R200_COLOR_ARG(0, C
);
615 color_combine
= (R200_TXC_ARG_C_ZERO
|
617 R200_COLOR_ARG(0, A
);
618 R200_COLOR_ARG(1, B
);
621 color_combine
= (R200_TXC_ARG_B_ZERO
|
622 R200_TXC_COMP_ARG_B
|
624 R200_COLOR_ARG(0, A
);
625 R200_COLOR_ARG(1, C
);
628 color_combine
= (R200_TXC_ARG_B_ZERO
| R200_TXC_COMP_ARG_B
| R200_TXC_BIAS_ARG_C
| /* new */
629 R200_TXC_OP_MADD
); /* was ADDSIGNED */
630 R200_COLOR_ARG(0, A
);
631 R200_COLOR_ARG(1, C
);
634 color_combine
= (R200_TXC_ARG_B_ZERO
|
635 R200_TXC_COMP_ARG_B
|
636 R200_TXC_NEG_ARG_C
| R200_TXC_OP_MADD
);
637 R200_COLOR_ARG(0, A
);
638 R200_COLOR_ARG(1, C
);
641 color_combine
= (R200_TXC_OP_LERP
);
642 R200_COLOR_ARG(0, B
);
643 R200_COLOR_ARG(1, A
);
644 R200_COLOR_ARG(2, C
);
647 case GL_DOT3_RGB_EXT
:
648 case GL_DOT3_RGBA_EXT
:
649 /* The EXT version of the DOT3 extension does not support the
650 * scale factor, but the ARB version (and the version in OpenGL
658 /* DOT3 works differently on R200 than on R100. On R100, just
659 * setting the DOT3 mode did everything for you. On R200, the
660 * driver has to enable the biasing and scale in the inputs to
661 * put them in the proper [-1,1] range. This is what the 4x and
662 * the -0.5 in the DOT3 spec do. The post-scale is then set
666 color_combine
= (R200_TXC_ARG_C_ZERO
|
668 R200_TXC_BIAS_ARG_A
|
669 R200_TXC_BIAS_ARG_B
|
670 R200_TXC_SCALE_ARG_A
|
671 R200_TXC_SCALE_ARG_B
);
672 R200_COLOR_ARG(0, A
);
673 R200_COLOR_ARG(1, B
);
676 case GL_MODULATE_ADD_ATI
:
677 color_combine
= (R200_TXC_OP_MADD
);
678 R200_COLOR_ARG(0, A
);
679 R200_COLOR_ARG(1, C
);
680 R200_COLOR_ARG(2, B
);
682 case GL_MODULATE_SIGNED_ADD_ATI
:
683 color_combine
= (R200_TXC_BIAS_ARG_C
| /* new */
684 R200_TXC_OP_MADD
); /* was ADDSIGNED */
685 R200_COLOR_ARG(0, A
);
686 R200_COLOR_ARG(1, C
);
687 R200_COLOR_ARG(2, B
);
689 case GL_MODULATE_SUBTRACT_ATI
:
690 color_combine
= (R200_TXC_NEG_ARG_C
| R200_TXC_OP_MADD
);
691 R200_COLOR_ARG(0, A
);
692 R200_COLOR_ARG(1, C
);
693 R200_COLOR_ARG(2, B
);
699 switch (texUnit
->_CurrentCombine
->ModeA
) {
701 alpha_combine
= (R200_TXA_ARG_A_ZERO
|
702 R200_TXA_ARG_B_ZERO
|
704 R200_ALPHA_ARG(0, C
);
707 alpha_combine
= (R200_TXA_ARG_C_ZERO
|
709 R200_ALPHA_ARG(0, A
);
710 R200_ALPHA_ARG(1, B
);
713 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
714 R200_TXA_COMP_ARG_B
|
716 R200_ALPHA_ARG(0, A
);
717 R200_ALPHA_ARG(1, C
);
720 alpha_combine
= (R200_TXA_ARG_B_ZERO
| R200_TXA_COMP_ARG_B
| R200_TXA_BIAS_ARG_C
| /* new */
721 R200_TXA_OP_MADD
); /* was ADDSIGNED */
722 R200_ALPHA_ARG(0, A
);
723 R200_ALPHA_ARG(1, C
);
726 alpha_combine
= (R200_TXA_ARG_B_ZERO
|
727 R200_TXA_COMP_ARG_B
|
728 R200_TXA_NEG_ARG_C
| R200_TXA_OP_MADD
);
729 R200_ALPHA_ARG(0, A
);
730 R200_ALPHA_ARG(1, C
);
733 alpha_combine
= (R200_TXA_OP_LERP
);
734 R200_ALPHA_ARG(0, B
);
735 R200_ALPHA_ARG(1, A
);
736 R200_ALPHA_ARG(2, C
);
739 case GL_MODULATE_ADD_ATI
:
740 alpha_combine
= (R200_TXA_OP_MADD
);
741 R200_ALPHA_ARG(0, A
);
742 R200_ALPHA_ARG(1, C
);
743 R200_ALPHA_ARG(2, B
);
745 case GL_MODULATE_SIGNED_ADD_ATI
:
746 alpha_combine
= (R200_TXA_BIAS_ARG_C
| /* new */
747 R200_TXA_OP_MADD
); /* was ADDSIGNED */
748 R200_ALPHA_ARG(0, A
);
749 R200_ALPHA_ARG(1, C
);
750 R200_ALPHA_ARG(2, B
);
752 case GL_MODULATE_SUBTRACT_ATI
:
753 alpha_combine
= (R200_TXA_NEG_ARG_C
| R200_TXA_OP_MADD
);
754 R200_ALPHA_ARG(0, A
);
755 R200_ALPHA_ARG(1, C
);
756 R200_ALPHA_ARG(2, B
);
762 if ((texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
763 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
)) {
764 alpha_scale
|= R200_TXA_DOT_ALPHA
;
769 * Apply the scale factor.
771 color_scale
|= (RGBshift
<< R200_TXC_SCALE_SHIFT
);
772 alpha_scale
|= (Ashift
<< R200_TXA_SCALE_SHIFT
);
779 fprintf(stderr
, "color_combine=%08x alpha_combine=%08x color_scale=%08x alpha_scale=%08x\n",
780 color_combine
, alpha_combine
, color_scale
, alpha_scale
);
784 if (rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND
] != color_combine
||
785 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND
] != alpha_combine
||
786 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] != color_scale
||
787 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] != alpha_scale
) {
788 R300_STATECHANGE(rmesa
, pix
[unit
]);
789 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND
] = color_combine
;
790 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND
] = alpha_combine
;
791 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXCBLEND2
] = color_scale
;
792 rmesa
->hw
.pix
[unit
].cmd
[PIX_PP_TXABLEND2
] = alpha_scale
;
800 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
801 R200_MIN_FILTER_MASK | \
802 R200_MAG_FILTER_MASK | \
803 R200_MAX_ANISO_MASK | \
805 R200_YUV_TEMPERATURE_MASK | \
806 R200_CLAMP_S_MASK | \
807 R200_CLAMP_T_MASK | \
808 R200_BORDER_MODE_D3D )
810 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
811 R200_TXFORMAT_HEIGHT_MASK | \
812 R200_TXFORMAT_FORMAT_MASK | \
813 R200_TXFORMAT_F5_WIDTH_MASK | \
814 R200_TXFORMAT_F5_HEIGHT_MASK | \
815 R200_TXFORMAT_ALPHA_IN_MAP | \
816 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
817 R200_TXFORMAT_NON_POWER2)
819 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
820 R200_TEXCOORD_MASK | \
821 R200_CLAMP_Q_MASK | \
822 R200_VOLUME_FILTER_MASK)
824 static void import_tex_obj_state(r300ContextPtr rmesa
,
825 int unit
, r300TexObjPtr texobj
)
827 #if 0 /* needs fixing.. or should be done elsewhere */
828 GLuint
*cmd
= R300_DB_STATE(tex
[unit
]);
830 cmd
[TEX_PP_TXFILTER
] &= ~TEXOBJ_TXFILTER_MASK
;
831 cmd
[TEX_PP_TXFILTER
] |= texobj
->filter
& TEXOBJ_TXFILTER_MASK
;
832 cmd
[TEX_PP_TXFORMAT
] &= ~TEXOBJ_TXFORMAT_MASK
;
833 cmd
[TEX_PP_TXFORMAT
] |= texobj
->format
& TEXOBJ_TXFORMAT_MASK
;
834 cmd
[TEX_PP_TXFORMAT_X
] &= ~TEXOBJ_TXFORMAT_X_MASK
;
835 cmd
[TEX_PP_TXFORMAT_X
] |=
836 texobj
->format_x
& TEXOBJ_TXFORMAT_X_MASK
;
837 cmd
[TEX_PP_TXSIZE
] = texobj
->size
; /* NPOT only! */
838 cmd
[TEX_PP_TXPITCH
] = texobj
->pitch
; /* NPOT only! */
839 cmd
[TEX_PP_TXOFFSET
] = texobj
->pp_txoffset
;
840 cmd
[TEX_PP_BORDER_COLOR
] = texobj
->pp_border_color
;
841 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.tex
[unit
]);
843 if (texobj
->base
.tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
844 GLuint
*cube_cmd
= R200_DB_STATE(cube
[unit
]);
845 GLuint bytesPerFace
= texobj
->base
.totalSize
/ 6;
846 ASSERT(texobj
->totalSize
% 6 == 0);
847 cube_cmd
[CUBE_PP_CUBIC_FACES
] = texobj
->pp_cubic_faces
;
848 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F1
] =
849 texobj
->pp_txoffset
+ 1 * bytesPerFace
;
850 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F2
] =
851 texobj
->pp_txoffset
+ 2 * bytesPerFace
;
852 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F3
] =
853 texobj
->pp_txoffset
+ 3 * bytesPerFace
;
854 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F4
] =
855 texobj
->pp_txoffset
+ 4 * bytesPerFace
;
856 cube_cmd
[CUBE_PP_CUBIC_OFFSET_F5
] =
857 texobj
->pp_txoffset
+ 5 * bytesPerFace
;
858 R200_DB_STATECHANGE(rmesa
, &rmesa
->hw
.cube
[unit
]);
861 texobj
->dirty_state
&= ~(1 << unit
);
865 static void set_texgen_matrix(r300ContextPtr rmesa
,
867 const GLfloat
* s_plane
,
868 const GLfloat
* t_plane
, const GLfloat
* r_plane
)
870 static const GLfloat scale_identity
[4] = { 1, 1, 1, 1 };
872 if (!TEST_EQ_4V(s_plane
, scale_identity
) ||
873 !TEST_EQ_4V(t_plane
, scale_identity
) ||
874 !TEST_EQ_4V(r_plane
, scale_identity
)) {
875 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<< unit
;
876 rmesa
->TexGenMatrix
[unit
].m
[0] = s_plane
[0];
877 rmesa
->TexGenMatrix
[unit
].m
[4] = s_plane
[1];
878 rmesa
->TexGenMatrix
[unit
].m
[8] = s_plane
[2];
879 rmesa
->TexGenMatrix
[unit
].m
[12] = s_plane
[3];
881 rmesa
->TexGenMatrix
[unit
].m
[1] = t_plane
[0];
882 rmesa
->TexGenMatrix
[unit
].m
[5] = t_plane
[1];
883 rmesa
->TexGenMatrix
[unit
].m
[9] = t_plane
[2];
884 rmesa
->TexGenMatrix
[unit
].m
[13] = t_plane
[3];
886 /* NOTE: r_plane goes in the 4th row, not 3rd! */
887 rmesa
->TexGenMatrix
[unit
].m
[3] = r_plane
[0];
888 rmesa
->TexGenMatrix
[unit
].m
[7] = r_plane
[1];
889 rmesa
->TexGenMatrix
[unit
].m
[11] = r_plane
[2];
890 rmesa
->TexGenMatrix
[unit
].m
[15] = r_plane
[3];
892 //rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
896 /* Need this special matrix to get correct reflection map coords */
897 static void set_texgen_reflection_matrix(r300ContextPtr rmesa
, GLuint unit
)
899 static const GLfloat m
[16] = {
905 _math_matrix_loadf(&(rmesa
->TexGenMatrix
[unit
]), m
);
906 _math_matrix_analyse(&(rmesa
->TexGenMatrix
[unit
]));
907 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<< unit
;
910 /* Need this special matrix to get correct normal map coords */
911 static void set_texgen_normal_map_matrix(r300ContextPtr rmesa
, GLuint unit
)
913 static const GLfloat m
[16] = {
919 _math_matrix_loadf(&(rmesa
->TexGenMatrix
[unit
]), m
);
920 _math_matrix_analyse(&(rmesa
->TexGenMatrix
[unit
]));
921 rmesa
->TexGenEnabled
|= R200_TEXMAT_0_ENABLE
<< unit
;
924 /* Ignoring the Q texcoord for now.
926 * Returns GL_FALSE if fallback required.
928 static GLboolean
r300_validate_texgen(GLcontext
* ctx
, GLuint unit
)
930 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
931 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
932 GLuint inputshift
= R200_TEXGEN_0_INPUT_SHIFT
+ unit
* 4;
933 GLuint tmp
= rmesa
->TexGenEnabled
;
935 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
936 rmesa
->TexGenEnabled
&= ~(R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
);
937 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<< unit
);
938 rmesa
->TexGenInputs
&= ~(R200_TEXGEN_INPUT_MASK
<< inputshift
);
939 rmesa
->TexGenNeedNormals
[unit
] = 0;
942 fprintf(stderr
, "%s unit %d\n", __FUNCTION__
, unit
);
944 if ((texUnit
->TexGenEnabled
& (S_BIT
| T_BIT
| R_BIT
)) == 0) {
945 /* Disabled, no fallback:
947 rmesa
->TexGenInputs
|=
948 (R200_TEXGEN_INPUT_TEXCOORD_0
+ unit
) << inputshift
;
950 } else if (texUnit
->TexGenEnabled
& Q_BIT
) {
951 /* Very easy to do this, in fact would remove a fallback case
952 * elsewhere, but I haven't done it yet... Fallback:
954 /*fprintf(stderr, "fallback Q_BIT\n"); */
956 } else if (texUnit
->TexGenEnabled
== (S_BIT
| T_BIT
) &&
957 texUnit
->GenModeS
== texUnit
->GenModeT
) {
959 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
961 } else if (texUnit
->TexGenEnabled
== (S_BIT
| T_BIT
| R_BIT
) &&
962 texUnit
->GenModeS
== texUnit
->GenModeT
&&
963 texUnit
->GenModeT
== texUnit
->GenModeR
) {
965 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
968 /* Mixed modes, fallback:
970 /* fprintf(stderr, "fallback mixed texgen\n"); */
974 rmesa
->TexGenEnabled
|= R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
;
976 switch (texUnit
->GenModeS
) {
977 case GL_OBJECT_LINEAR
:
978 rmesa
->TexGenInputs
|= R200_TEXGEN_INPUT_OBJ
<< inputshift
;
979 set_texgen_matrix(rmesa
, unit
,
980 texUnit
->ObjectPlaneS
,
981 texUnit
->ObjectPlaneT
, texUnit
->ObjectPlaneR
);
985 rmesa
->TexGenInputs
|= R200_TEXGEN_INPUT_EYE
<< inputshift
;
986 set_texgen_matrix(rmesa
, unit
,
988 texUnit
->EyePlaneT
, texUnit
->EyePlaneR
);
991 case GL_REFLECTION_MAP_NV
:
992 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
993 rmesa
->TexGenInputs
|=
994 R200_TEXGEN_INPUT_EYE_REFLECT
<< inputshift
;
995 set_texgen_reflection_matrix(rmesa
, unit
);
998 case GL_NORMAL_MAP_NV
:
999 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1000 rmesa
->TexGenInputs
|=
1001 R200_TEXGEN_INPUT_EYE_NORMAL
<< inputshift
;
1002 set_texgen_normal_map_matrix(rmesa
, unit
);
1006 rmesa
->TexGenNeedNormals
[unit
] = GL_TRUE
;
1007 rmesa
->TexGenInputs
|= R200_TEXGEN_INPUT_SPHERE
<< inputshift
;
1011 /* Unsupported mode, fallback:
1013 /* fprintf(stderr, "fallback unsupported texgen\n"); */
1017 rmesa
->TexGenCompSel
|= R200_OUTPUT_TEX_0
<< unit
;
1019 if (tmp
!= rmesa
->TexGenEnabled
) {
1020 //rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1026 static void disable_tex(GLcontext
* ctx
, int unit
)
1028 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1030 #if 0 /* This needs to be redone.. or done elsewhere */
1031 if (rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<< unit
)) {
1032 /* Texture unit disabled */
1033 if (rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
1034 /* The old texture is no longer bound to this texture unit.
1038 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&=
1040 rmesa
->state
.texture
.unit
[unit
].texobj
= NULL
;
1043 R300_STATECHANGE(rmesa
, ctx
);
1044 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] &= ~((R200_TEX_0_ENABLE
|
1045 R200_TEX_BLEND_0_ENABLE
) <<
1047 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_BLEND_0_ENABLE
;
1049 R300_STATECHANGE(rmesa
, tcl
);
1050 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] &=
1053 if (rmesa
->radeon
.TclFallback
& (RADEON_TCL_FALLBACK_TEXGEN_0
<< unit
)) {
1054 TCL_FALLBACK(ctx
, (RADEON_TCL_FALLBACK_TEXGEN_0
<< unit
),
1058 /* Actually want to keep all units less than max active texture
1059 * enabled, right? Fix this for >2 texunits.
1061 /* FIXME: What should happen here if r300UpdateTextureEnv fails? */
1063 r300UpdateTextureEnv(ctx
, unit
);
1067 R200_TEXGEN_0_INPUT_SHIFT
+ unit
* 4;
1068 GLuint tmp
= rmesa
->TexGenEnabled
;
1070 rmesa
->TexGenEnabled
&=
1071 ~(R200_TEXGEN_TEXMAT_0_ENABLE
<< unit
);
1072 rmesa
->TexGenEnabled
&= ~(R200_TEXMAT_0_ENABLE
<< unit
);
1073 rmesa
->TexGenEnabled
&=
1074 ~(R200_TEXGEN_INPUT_MASK
<< inputshift
);
1075 rmesa
->TexGenNeedNormals
[unit
] = 0;
1076 rmesa
->TexGenCompSel
&= ~(R200_OUTPUT_TEX_0
<< unit
);
1077 rmesa
->TexGenInputs
&=
1078 ~(R200_TEXGEN_INPUT_MASK
<< inputshift
);
1080 if (tmp
!= rmesa
->TexGenEnabled
) {
1081 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1082 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1089 static GLboolean
enable_tex_2d(GLcontext
* ctx
, int unit
)
1091 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1092 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1093 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1094 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1096 /* Need to load the 2d images associated with this unit.
1098 if (t
->format
& R200_TXFORMAT_NON_POWER2
) {
1099 t
->format
&= ~R200_TXFORMAT_NON_POWER2
;
1100 t
->base
.dirty_images
[0] = ~0;
1103 ASSERT(tObj
->Target
== GL_TEXTURE_2D
|| tObj
->Target
== GL_TEXTURE_1D
);
1105 if (t
->base
.dirty_images
[0]) {
1106 R300_FIREVERTICES(rmesa
);
1107 r300SetTexImages(rmesa
, tObj
);
1108 r300UploadTexImages(rmesa
, (r300TexObjPtr
) tObj
->DriverData
, 0);
1109 if (!t
->base
.memBlock
)
1116 #if ENABLE_HW_3D_TEXTURE
1117 static GLboolean
enable_tex_3d(GLcontext
* ctx
, int unit
)
1119 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1120 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1121 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1122 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1124 /* Need to load the 3d images associated with this unit.
1126 if (t
->format
& R200_TXFORMAT_NON_POWER2
) {
1127 t
->format
&= ~R200_TXFORMAT_NON_POWER2
;
1128 t
->base
.dirty_images
[0] = ~0;
1131 ASSERT(tObj
->Target
== GL_TEXTURE_3D
);
1133 /* R100 & R200 do not support mipmaps for 3D textures.
1135 if ((tObj
->MinFilter
!= GL_NEAREST
) && (tObj
->MinFilter
!= GL_LINEAR
)) {
1139 if (t
->base
.dirty_images
[0]) {
1140 R300_FIREVERTICES(rmesa
);
1141 r300SetTexImages(rmesa
, tObj
);
1142 r300UploadTexImages(rmesa
, (r300TexObjPtr
) tObj
->DriverData
, 0);
1143 if (!t
->base
.memBlock
)
1151 static GLboolean
enable_tex_cube(GLcontext
* ctx
, int unit
)
1153 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1154 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1155 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1156 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1159 /* Need to load the 2d images associated with this unit.
1161 if (t
->format
& R200_TXFORMAT_NON_POWER2
) {
1162 t
->format
&= ~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 R300_FIREVERTICES(rmesa
);
1174 /* layout memory space, once for all faces */
1175 r300SetTexImages(rmesa
, tObj
);
1178 /* upload (per face) */
1179 for (face
= 0; face
< 6; face
++) {
1180 if (t
->base
.dirty_images
[face
]) {
1181 r300UploadTexImages(rmesa
,
1182 (r300TexObjPtr
) tObj
->DriverData
,
1187 if (!t
->base
.memBlock
) {
1188 /* texmem alloc failed, use s/w fallback */
1195 static GLboolean
enable_tex_rect(GLcontext
* ctx
, int unit
)
1197 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1198 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1199 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1200 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1202 if (!(t
->format
& R200_TXFORMAT_NON_POWER2
)) {
1203 t
->format
|= 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 R300_FIREVERTICES(rmesa
);
1211 r300SetTexImages(rmesa
, tObj
);
1212 r300UploadTexImages(rmesa
, (r300TexObjPtr
) tObj
->DriverData
, 0);
1213 if (!t
->base
.memBlock
&& !rmesa
->prefer_gart_client_texturing
)
1220 static GLboolean
update_tex_common(GLcontext
* ctx
, int unit
)
1222 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1223 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1224 struct gl_texture_object
*tObj
= texUnit
->_Current
;
1225 r300TexObjPtr t
= (r300TexObjPtr
) tObj
->DriverData
;
1228 /* Fallback if there's a texture border */
1229 if (tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0)
1232 /* Update state if this is a different texture object to last
1235 if (rmesa
->state
.texture
.unit
[unit
].texobj
!= t
) {
1236 if (rmesa
->state
.texture
.unit
[unit
].texobj
!= NULL
) {
1237 /* The old texture is no longer bound to this texture unit.
1241 rmesa
->state
.texture
.unit
[unit
].texobj
->base
.bound
&=
1245 rmesa
->state
.texture
.unit
[unit
].texobj
= t
;
1246 t
->base
.bound
|= (1UL << unit
);
1247 t
->dirty_state
|= 1 << unit
;
1248 driUpdateTextureLRU((driTextureObject
*) t
); /* XXX: should be locked! */
1251 #if 0 /* do elsewhere ? */
1256 cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
<< unit
))) {
1257 R300_STATECHANGE(rmesa
, ctx
);
1258 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= (R200_TEX_0_ENABLE
|
1259 R200_TEX_BLEND_0_ENABLE
) <<
1262 R300_STATECHANGE(rmesa
, vtx
);
1263 rmesa
->hw
.vtx
.cmd
[VTX_TCL_OUTPUT_VTXFMT_1
] |= 4 << (unit
* 3);
1265 rmesa
->recheck_texgen
[unit
] = GL_TRUE
;
1268 if (t
->dirty_state
& (1 << unit
)) {
1269 import_tex_obj_state(rmesa
, unit
, t
);
1272 if (rmesa
->recheck_texgen
[unit
]) {
1273 GLboolean fallback
= !r300_validate_texgen(ctx
, unit
);
1274 TCL_FALLBACK(ctx
, (RADEON_TCL_FALLBACK_TEXGEN_0
<< unit
),
1276 rmesa
->recheck_texgen
[unit
] = 0;
1277 rmesa
->NewGLState
|= _NEW_TEXTURE_MATRIX
;
1281 format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
1282 if (rmesa
->state
.texture
.unit
[unit
].format
!= format
||
1283 rmesa
->state
.texture
.unit
[unit
].envMode
!= texUnit
->EnvMode
) {
1284 //rmesa->state.texture.unit[unit].format = format;
1285 rmesa
->state
.texture
.unit
[unit
].envMode
= texUnit
->EnvMode
;
1286 if (!r300UpdateTextureEnv(ctx
, unit
)) {
1291 FALLBACK(&rmesa
->radeon
, RADEON_FALLBACK_BORDER_MODE
, t
->border_fallback
);
1292 return !t
->border_fallback
;
1295 static GLboolean
r300UpdateTextureUnit(GLcontext
* ctx
, int unit
)
1297 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
1299 if (texUnit
->_ReallyEnabled
& (TEXTURE_RECT_BIT
)) {
1300 return (enable_tex_rect(ctx
, unit
) &&
1301 update_tex_common(ctx
, unit
));
1302 } else if (texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
)) {
1303 return (enable_tex_2d(ctx
, unit
) &&
1304 update_tex_common(ctx
, unit
));
1306 #if ENABLE_HW_3D_TEXTURE
1307 else if (texUnit
->_ReallyEnabled
& (TEXTURE_3D_BIT
)) {
1308 return (enable_tex_3d(ctx
, unit
) &&
1309 update_tex_common(ctx
, unit
));
1312 else if (texUnit
->_ReallyEnabled
& (TEXTURE_CUBE_BIT
)) {
1313 return (enable_tex_cube(ctx
, unit
) &&
1314 update_tex_common(ctx
, unit
));
1315 } else if (texUnit
->_ReallyEnabled
) {
1318 disable_tex(ctx
, unit
);
1323 void r300UpdateTextureState(GLcontext
* ctx
)
1325 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
1330 ok
= (r300UpdateTextureUnit(ctx
, 0) &&
1331 r300UpdateTextureUnit(ctx
, 1) &&
1332 r300UpdateTextureUnit(ctx
, 2) &&
1333 r300UpdateTextureUnit(ctx
, 3) &&
1334 r300UpdateTextureUnit(ctx
, 4) &&
1335 r300UpdateTextureUnit(ctx
, 5) &&
1336 r300UpdateTextureUnit(ctx
, 6) &&
1337 r300UpdateTextureUnit(ctx
, 7)
1340 FALLBACK(&rmesa
->radeon
, RADEON_FALLBACK_TEXTURE
, !ok
);
1342 /* This needs correction, or just be done elsewhere
1343 if (rmesa->radeon.TclFallback)
1344 r300ChooseVertexState(ctx);
1347 #if 0 /* Workaround - disable.. */
1348 if (GET_CHIP(rmesa
->radeon
.radeonScreen
) == RADEON_CHIP_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
) ==
1355 && (rmesa
->hw
.tex
[0].
1356 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
) >
1357 R200_MIN_FILTER_LINEAR
) {
1359 R300_STATECHANGE(rmesa
, ctx
);
1360 R300_STATECHANGE(rmesa
, tex
[1]);
1361 rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] |= R200_TEX_1_ENABLE
;
1362 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &=
1363 ~TEXOBJ_TXFORMAT_MASK
;
1364 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] |= 0x08000000;
1366 if ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_1_ENABLE
)
1367 && (rmesa
->hw
.tex
[1].
1368 cmd
[TEX_PP_TXFORMAT
] & 0x08000000)) {
1369 R300_STATECHANGE(rmesa
, tex
[1]);
1370 rmesa
->hw
.tex
[1].cmd
[TEX_PP_TXFORMAT
] &=
1375 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1376 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1377 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1378 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1379 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1380 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1381 R200_MIN_FILTER_LINEAR)) {
1382 R300_STATECHANGE(rmesa, ctx);
1383 R300_STATECHANGE(rmesa, tex[i+1]);
1384 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1385 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1386 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1389 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1390 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1391 R300_STATECHANGE(rmesa, tex[i+1]);
1392 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1398 * Texture cache LRU hang workaround -------------
1399 * not needed for r200 derivatives?
1403 if (((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_0_ENABLE
)) &&
1404 ((((rmesa
->hw
.tex
[0].
1405 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) & 0x04)
1407 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_2_ENABLE
)
1409 ((((rmesa
->hw
.tex
[2].
1410 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1412 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_4_ENABLE
)
1414 ((((rmesa
->hw
.tex
[4].
1415 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1420 if (((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & (R200_TEX_1_ENABLE
)) &&
1421 ((((rmesa
->hw
.tex
[1].
1422 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) & 0x04)
1424 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_3_ENABLE
)
1426 ((((rmesa
->hw
.tex
[3].
1427 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1429 || ((rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & R200_TEX_5_ENABLE
)
1431 ((((rmesa
->hw
.tex
[5].
1432 cmd
[TEX_PP_TXFILTER
] & R200_MIN_FILTER_MASK
)) &
1437 if (dbg
!= rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
]) {
1438 R300_STATECHANGE(rmesa
, tam
);
1439 rmesa
->hw
.tam
.cmd
[TAM_DEBUG3
] = dbg
;
1441 printf("TEXCACHE LRU HANG WORKAROUND %x\n",