Remove CVS keywords.
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_texstate.c
1 /**************************************************************************
2
3 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4 VA Linux Systems Inc., Fremont, California.
5
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 **************************************************************************/
29
30 /*
31 * Authors:
32 * Kevin E. Martin <martin@valinux.com>
33 * Gareth Hughes <gareth@valinux.com>
34 */
35
36 #include "main/glheader.h"
37 #include "main/imports.h"
38 #include "main/colormac.h"
39 #include "main/context.h"
40 #include "main/macros.h"
41 #include "main/texformat.h"
42 #include "main/texobj.h"
43 #include "main/enums.h"
44
45 #include "radeon_context.h"
46 #include "radeon_state.h"
47 #include "radeon_ioctl.h"
48 #include "radeon_swtcl.h"
49 #include "radeon_tex.h"
50 #include "radeon_tcl.h"
51
52
53 #define RADEON_TXFORMAT_A8 RADEON_TXFORMAT_I8
54 #define RADEON_TXFORMAT_L8 RADEON_TXFORMAT_I8
55 #define RADEON_TXFORMAT_AL88 RADEON_TXFORMAT_AI88
56 #define RADEON_TXFORMAT_YCBCR RADEON_TXFORMAT_YVYU422
57 #define RADEON_TXFORMAT_YCBCR_REV RADEON_TXFORMAT_VYUY422
58 #define RADEON_TXFORMAT_RGB_DXT1 RADEON_TXFORMAT_DXT1
59 #define RADEON_TXFORMAT_RGBA_DXT1 RADEON_TXFORMAT_DXT1
60 #define RADEON_TXFORMAT_RGBA_DXT3 RADEON_TXFORMAT_DXT23
61 #define RADEON_TXFORMAT_RGBA_DXT5 RADEON_TXFORMAT_DXT45
62
63 #define _COLOR(f) \
64 [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, 0 }
65 #define _COLOR_REV(f) \
66 [ MESA_FORMAT_ ## f ## _REV ] = { RADEON_TXFORMAT_ ## f, 0 }
67 #define _ALPHA(f) \
68 [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f | RADEON_TXFORMAT_ALPHA_IN_MAP, 0 }
69 #define _ALPHA_REV(f) \
70 [ MESA_FORMAT_ ## f ## _REV ] = { RADEON_TXFORMAT_ ## f | RADEON_TXFORMAT_ALPHA_IN_MAP, 0 }
71 #define _YUV(f) \
72 [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, RADEON_YUV_TO_RGB }
73 #define _INVALID(f) \
74 [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
75 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
76 && (tx_table[f].format != 0xffffffff) )
77
78 static const struct {
79 GLuint format, filter;
80 }
81 tx_table[] =
82 {
83 _ALPHA(RGBA8888),
84 _ALPHA_REV(RGBA8888),
85 _ALPHA(ARGB8888),
86 _ALPHA_REV(ARGB8888),
87 [ MESA_FORMAT_RGB888 ] = { RADEON_TXFORMAT_ARGB8888, 0 },
88 _COLOR(RGB565),
89 _COLOR_REV(RGB565),
90 _ALPHA(ARGB4444),
91 _ALPHA_REV(ARGB4444),
92 _ALPHA(ARGB1555),
93 _ALPHA_REV(ARGB1555),
94 _ALPHA(AL88),
95 _ALPHA_REV(AL88),
96 _ALPHA(A8),
97 _COLOR(L8),
98 _ALPHA(I8),
99 _INVALID(CI8),
100 _YUV(YCBCR),
101 _YUV(YCBCR_REV),
102 _INVALID(RGB_FXT1),
103 _INVALID(RGBA_FXT1),
104 _COLOR(RGB_DXT1),
105 _ALPHA(RGBA_DXT1),
106 _ALPHA(RGBA_DXT3),
107 _ALPHA(RGBA_DXT5),
108 };
109
110 #undef _COLOR
111 #undef _ALPHA
112 #undef _INVALID
113
114 /**
115 * This function computes the number of bytes of storage needed for
116 * the given texture object (all mipmap levels, all cube faces).
117 * The \c image[face][level].x/y/width/height parameters for upload/blitting
118 * are computed here. \c pp_txfilter, \c pp_txformat, etc. will be set here
119 * too.
120 *
121 * \param rmesa Context pointer
122 * \param tObj GL texture object whose images are to be posted to
123 * hardware state.
124 */
125 static void radeonSetTexImages( radeonContextPtr rmesa,
126 struct gl_texture_object *tObj )
127 {
128 radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData;
129 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
130 GLint curOffset, blitWidth;
131 GLint i, texelBytes;
132 GLint numLevels;
133 GLint log2Width, log2Height, log2Depth;
134
135 /* Set the hardware texture format
136 */
137 if ( !t->image_override ) {
138 t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK |
139 RADEON_TXFORMAT_ALPHA_IN_MAP);
140 t->pp_txfilter &= ~RADEON_YUV_TO_RGB;
141
142 if ( VALID_FORMAT( baseImage->TexFormat->MesaFormat ) ) {
143 t->pp_txformat |= tx_table[ baseImage->TexFormat->MesaFormat ].format;
144 t->pp_txfilter |= tx_table[ baseImage->TexFormat->MesaFormat ].filter;
145 }
146 else {
147 _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
148 return;
149 }
150 }
151
152 texelBytes = baseImage->TexFormat->TexelBytes;
153
154 /* Compute which mipmap levels we really want to send to the hardware.
155 */
156
157 if (tObj->Target != GL_TEXTURE_CUBE_MAP)
158 driCalculateTextureFirstLastLevel( (driTextureObject *) t );
159 else {
160 /* r100 can't handle mipmaps for cube/3d textures, so don't waste
161 memory for them */
162 t->base.firstLevel = t->base.lastLevel = tObj->BaseLevel;
163 }
164 log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2;
165 log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
166 log2Depth = tObj->Image[0][t->base.firstLevel]->DepthLog2;
167
168 numLevels = t->base.lastLevel - t->base.firstLevel + 1;
169
170 assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
171
172 /* Calculate mipmap offsets and dimensions for blitting (uploading)
173 * The idea is that we lay out the mipmap levels within a block of
174 * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
175 */
176 curOffset = 0;
177 blitWidth = BLIT_WIDTH_BYTES;
178 t->tile_bits = 0;
179
180 /* figure out if this texture is suitable for tiling. */
181 if (texelBytes && (tObj->Target != GL_TEXTURE_RECTANGLE_NV)) {
182 if (rmesa->texmicrotile && (baseImage->Height > 1)) {
183 /* allow 32 (bytes) x 1 mip (which will use two times the space
184 the non-tiled version would use) max if base texture is large enough */
185 if ((numLevels == 1) ||
186 (((baseImage->Width * texelBytes / baseImage->Height) <= 32) &&
187 (baseImage->Width * texelBytes > 64)) ||
188 ((baseImage->Width * texelBytes / baseImage->Height) <= 16)) {
189 /* R100 has two microtile bits (only the txoffset reg, not the blitter)
190 weird: X2 + OPT: 32bit correct, 16bit completely hosed
191 X2: 32bit correct, 16bit correct
192 OPT: 32bit large mips correct, small mips hosed, 16bit completely hosed */
193 t->tile_bits |= RADEON_TXO_MICRO_TILE_X2 /*| RADEON_TXO_MICRO_TILE_OPT*/;
194 }
195 }
196 if ((baseImage->Width * texelBytes >= 256) && (baseImage->Height >= 16)) {
197 /* R100 disables macro tiling only if mip width is smaller than 256 bytes, and not
198 in the case if height is smaller than 16 (not 100% sure), as does the r200,
199 so need to disable macro tiling in that case */
200 if ((numLevels == 1) || ((baseImage->Width * texelBytes / baseImage->Height) <= 4)) {
201 t->tile_bits |= RADEON_TXO_MACRO_TILE;
202 }
203 }
204 }
205
206 for (i = 0; i < numLevels; i++) {
207 const struct gl_texture_image *texImage;
208 GLuint size;
209
210 texImage = tObj->Image[0][i + t->base.firstLevel];
211 if ( !texImage )
212 break;
213
214 /* find image size in bytes */
215 if (texImage->IsCompressed) {
216 /* need to calculate the size AFTER padding even though the texture is
217 submitted without padding.
218 Only handle pot textures currently - don't know if npot is even possible,
219 size calculation would certainly need (trivial) adjustments.
220 Align (and later pad) to 32byte, not sure what that 64byte blit width is
221 good for? */
222 if ((t->pp_txformat & RADEON_TXFORMAT_FORMAT_MASK) == RADEON_TXFORMAT_DXT1) {
223 /* RGB_DXT1/RGBA_DXT1, 8 bytes per block */
224 if ((texImage->Width + 3) < 8) /* width one block */
225 size = texImage->CompressedSize * 4;
226 else if ((texImage->Width + 3) < 16)
227 size = texImage->CompressedSize * 2;
228 else size = texImage->CompressedSize;
229 }
230 else /* DXT3/5, 16 bytes per block */
231 if ((texImage->Width + 3) < 8)
232 size = texImage->CompressedSize * 2;
233 else size = texImage->CompressedSize;
234 }
235 else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
236 size = ((texImage->Width * texelBytes + 63) & ~63) * texImage->Height;
237 }
238 else if (t->tile_bits & RADEON_TXO_MICRO_TILE_X2) {
239 /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
240 though the actual offset may be different (if texture is less than
241 32 bytes width) to the untiled case */
242 int w = (texImage->Width * texelBytes * 2 + 31) & ~31;
243 size = (w * ((texImage->Height + 1) / 2)) * texImage->Depth;
244 blitWidth = MAX2(texImage->Width, 64 / texelBytes);
245 }
246 else {
247 int w = (texImage->Width * texelBytes + 31) & ~31;
248 size = w * texImage->Height * texImage->Depth;
249 blitWidth = MAX2(texImage->Width, 64 / texelBytes);
250 }
251 assert(size > 0);
252
253 /* Align to 32-byte offset. It is faster to do this unconditionally
254 * (no branch penalty).
255 */
256
257 curOffset = (curOffset + 0x1f) & ~0x1f;
258
259 if (texelBytes) {
260 t->image[0][i].x = curOffset; /* fix x and y coords up later together with offset */
261 t->image[0][i].y = 0;
262 t->image[0][i].width = MIN2(size / texelBytes, blitWidth);
263 t->image[0][i].height = (size / texelBytes) / t->image[0][i].width;
264 }
265 else {
266 t->image[0][i].x = curOffset % BLIT_WIDTH_BYTES;
267 t->image[0][i].y = curOffset / BLIT_WIDTH_BYTES;
268 t->image[0][i].width = MIN2(size, BLIT_WIDTH_BYTES);
269 t->image[0][i].height = size / t->image[0][i].width;
270 }
271
272 #if 0
273 /* for debugging only and only applicable to non-rectangle targets */
274 assert(size % t->image[0][i].width == 0);
275 assert(t->image[0][i].x == 0
276 || (size < BLIT_WIDTH_BYTES && t->image[0][i].height == 1));
277 #endif
278
279 if (0)
280 fprintf(stderr,
281 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
282 i, texImage->Width, texImage->Height,
283 t->image[0][i].x, t->image[0][i].y,
284 t->image[0][i].width, t->image[0][i].height, size, curOffset);
285
286 curOffset += size;
287
288 }
289
290 /* Align the total size of texture memory block.
291 */
292 t->base.totalSize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
293
294 /* Setup remaining cube face blits, if needed */
295 if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
296 const GLuint faceSize = t->base.totalSize;
297 GLuint face;
298 /* reuse face 0 x/y/width/height - just update the offset when uploading */
299 for (face = 1; face < 6; face++) {
300 for (i = 0; i < numLevels; i++) {
301 t->image[face][i].x = t->image[0][i].x;
302 t->image[face][i].y = t->image[0][i].y;
303 t->image[face][i].width = t->image[0][i].width;
304 t->image[face][i].height = t->image[0][i].height;
305 }
306 }
307 t->base.totalSize = 6 * faceSize; /* total texmem needed */
308 }
309
310 /* Hardware state:
311 */
312 t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK;
313 t->pp_txfilter |= (numLevels - 1) << RADEON_MAX_MIP_LEVEL_SHIFT;
314
315 t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK |
316 RADEON_TXFORMAT_HEIGHT_MASK |
317 RADEON_TXFORMAT_CUBIC_MAP_ENABLE |
318 RADEON_TXFORMAT_F5_WIDTH_MASK |
319 RADEON_TXFORMAT_F5_HEIGHT_MASK);
320 t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) |
321 (log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT));
322
323 if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
324 assert(log2Width == log2Height);
325 t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_F5_WIDTH_SHIFT) |
326 (log2Height << RADEON_TXFORMAT_F5_HEIGHT_SHIFT) |
327 (RADEON_TXFORMAT_CUBIC_MAP_ENABLE));
328 t->pp_cubic_faces = ((log2Width << RADEON_FACE_WIDTH_1_SHIFT) |
329 (log2Height << RADEON_FACE_HEIGHT_1_SHIFT) |
330 (log2Width << RADEON_FACE_WIDTH_2_SHIFT) |
331 (log2Height << RADEON_FACE_HEIGHT_2_SHIFT) |
332 (log2Width << RADEON_FACE_WIDTH_3_SHIFT) |
333 (log2Height << RADEON_FACE_HEIGHT_3_SHIFT) |
334 (log2Width << RADEON_FACE_WIDTH_4_SHIFT) |
335 (log2Height << RADEON_FACE_HEIGHT_4_SHIFT));
336 }
337
338 t->pp_txsize = (((tObj->Image[0][t->base.firstLevel]->Width - 1) << 0) |
339 ((tObj->Image[0][t->base.firstLevel]->Height - 1) << 16));
340
341 /* Only need to round to nearest 32 for textures, but the blitter
342 * requires 64-byte aligned pitches, and we may/may not need the
343 * blitter. NPOT only!
344 */
345 if ( !t->image_override ) {
346 if (baseImage->IsCompressed)
347 t->pp_txpitch = (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63);
348 else
349 t->pp_txpitch = ((tObj->Image[0][t->base.firstLevel]->Width * texelBytes) + 63) & ~(63);
350 t->pp_txpitch -= 32;
351 }
352
353 t->dirty_state = TEX_ALL;
354
355 /* FYI: radeonUploadTexImages( rmesa, t ); used to be called here */
356 }
357
358
359
360 /* ================================================================
361 * Texture combine functions
362 */
363
364 /* GL_ARB_texture_env_combine support
365 */
366
367 /* The color tables have combine functions for GL_SRC_COLOR,
368 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
369 */
370 static GLuint radeon_texture_color[][RADEON_MAX_TEXTURE_UNITS] =
371 {
372 {
373 RADEON_COLOR_ARG_A_T0_COLOR,
374 RADEON_COLOR_ARG_A_T1_COLOR,
375 RADEON_COLOR_ARG_A_T2_COLOR
376 },
377 {
378 RADEON_COLOR_ARG_A_T0_COLOR | RADEON_COMP_ARG_A,
379 RADEON_COLOR_ARG_A_T1_COLOR | RADEON_COMP_ARG_A,
380 RADEON_COLOR_ARG_A_T2_COLOR | RADEON_COMP_ARG_A
381 },
382 {
383 RADEON_COLOR_ARG_A_T0_ALPHA,
384 RADEON_COLOR_ARG_A_T1_ALPHA,
385 RADEON_COLOR_ARG_A_T2_ALPHA
386 },
387 {
388 RADEON_COLOR_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A,
389 RADEON_COLOR_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A,
390 RADEON_COLOR_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A
391 },
392 };
393
394 static GLuint radeon_tfactor_color[] =
395 {
396 RADEON_COLOR_ARG_A_TFACTOR_COLOR,
397 RADEON_COLOR_ARG_A_TFACTOR_COLOR | RADEON_COMP_ARG_A,
398 RADEON_COLOR_ARG_A_TFACTOR_ALPHA,
399 RADEON_COLOR_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A
400 };
401
402 static GLuint radeon_primary_color[] =
403 {
404 RADEON_COLOR_ARG_A_DIFFUSE_COLOR,
405 RADEON_COLOR_ARG_A_DIFFUSE_COLOR | RADEON_COMP_ARG_A,
406 RADEON_COLOR_ARG_A_DIFFUSE_ALPHA,
407 RADEON_COLOR_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A
408 };
409
410 static GLuint radeon_previous_color[] =
411 {
412 RADEON_COLOR_ARG_A_CURRENT_COLOR,
413 RADEON_COLOR_ARG_A_CURRENT_COLOR | RADEON_COMP_ARG_A,
414 RADEON_COLOR_ARG_A_CURRENT_ALPHA,
415 RADEON_COLOR_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A
416 };
417
418 /* GL_ZERO table - indices 0-3
419 * GL_ONE table - indices 1-4
420 */
421 static GLuint radeon_zero_color[] =
422 {
423 RADEON_COLOR_ARG_A_ZERO,
424 RADEON_COLOR_ARG_A_ZERO | RADEON_COMP_ARG_A,
425 RADEON_COLOR_ARG_A_ZERO,
426 RADEON_COLOR_ARG_A_ZERO | RADEON_COMP_ARG_A,
427 RADEON_COLOR_ARG_A_ZERO
428 };
429
430
431 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
432 */
433 static GLuint radeon_texture_alpha[][RADEON_MAX_TEXTURE_UNITS] =
434 {
435 {
436 RADEON_ALPHA_ARG_A_T0_ALPHA,
437 RADEON_ALPHA_ARG_A_T1_ALPHA,
438 RADEON_ALPHA_ARG_A_T2_ALPHA
439 },
440 {
441 RADEON_ALPHA_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A,
442 RADEON_ALPHA_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A,
443 RADEON_ALPHA_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A
444 },
445 };
446
447 static GLuint radeon_tfactor_alpha[] =
448 {
449 RADEON_ALPHA_ARG_A_TFACTOR_ALPHA,
450 RADEON_ALPHA_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A
451 };
452
453 static GLuint radeon_primary_alpha[] =
454 {
455 RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA,
456 RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A
457 };
458
459 static GLuint radeon_previous_alpha[] =
460 {
461 RADEON_ALPHA_ARG_A_CURRENT_ALPHA,
462 RADEON_ALPHA_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A
463 };
464
465 /* GL_ZERO table - indices 0-1
466 * GL_ONE table - indices 1-2
467 */
468 static GLuint radeon_zero_alpha[] =
469 {
470 RADEON_ALPHA_ARG_A_ZERO,
471 RADEON_ALPHA_ARG_A_ZERO | RADEON_COMP_ARG_A,
472 RADEON_ALPHA_ARG_A_ZERO
473 };
474
475
476 /* Extract the arg from slot A, shift it into the correct argument slot
477 * and set the corresponding complement bit.
478 */
479 #define RADEON_COLOR_ARG( n, arg ) \
480 do { \
481 color_combine |= \
482 ((color_arg[n] & RADEON_COLOR_ARG_MASK) \
483 << RADEON_COLOR_ARG_##arg##_SHIFT); \
484 color_combine |= \
485 ((color_arg[n] >> RADEON_COMP_ARG_SHIFT) \
486 << RADEON_COMP_ARG_##arg##_SHIFT); \
487 } while (0)
488
489 #define RADEON_ALPHA_ARG( n, arg ) \
490 do { \
491 alpha_combine |= \
492 ((alpha_arg[n] & RADEON_ALPHA_ARG_MASK) \
493 << RADEON_ALPHA_ARG_##arg##_SHIFT); \
494 alpha_combine |= \
495 ((alpha_arg[n] >> RADEON_COMP_ARG_SHIFT) \
496 << RADEON_COMP_ARG_##arg##_SHIFT); \
497 } while (0)
498
499
500 /* ================================================================
501 * Texture unit state management
502 */
503
504 static GLboolean radeonUpdateTextureEnv( GLcontext *ctx, int unit )
505 {
506 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
507 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
508 GLuint color_combine, alpha_combine;
509 const GLuint color_combine0 = RADEON_COLOR_ARG_A_ZERO | RADEON_COLOR_ARG_B_ZERO
510 | RADEON_COLOR_ARG_C_CURRENT_COLOR | RADEON_BLEND_CTL_ADD
511 | RADEON_SCALE_1X | RADEON_CLAMP_TX;
512 const GLuint alpha_combine0 = RADEON_ALPHA_ARG_A_ZERO | RADEON_ALPHA_ARG_B_ZERO
513 | RADEON_ALPHA_ARG_C_CURRENT_ALPHA | RADEON_BLEND_CTL_ADD
514 | RADEON_SCALE_1X | RADEON_CLAMP_TX;
515
516
517 /* texUnit->_Current can be NULL if and only if the texture unit is
518 * not actually enabled.
519 */
520 assert( (texUnit->_ReallyEnabled == 0)
521 || (texUnit->_Current != NULL) );
522
523 if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
524 fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, (void *)ctx, unit );
525 }
526
527 /* Set the texture environment state. Isn't this nice and clean?
528 * The chip will automagically set the texture alpha to 0xff when
529 * the texture format does not include an alpha component. This
530 * reduces the amount of special-casing we have to do, alpha-only
531 * textures being a notable exception. Doesn't work for luminance
532 * textures realized with I8 and ALPHA_IN_MAP not set neither (on r100).
533 */
534 /* Don't cache these results.
535 */
536 rmesa->state.texture.unit[unit].format = 0;
537 rmesa->state.texture.unit[unit].envMode = 0;
538
539 if ( !texUnit->_ReallyEnabled ) {
540 color_combine = color_combine0;
541 alpha_combine = alpha_combine0;
542 }
543 else {
544 GLuint color_arg[3], alpha_arg[3];
545 GLuint i;
546 const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
547 const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
548 GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB;
549 GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA;
550
551
552 /* Step 1:
553 * Extract the color and alpha combine function arguments.
554 */
555 for ( i = 0 ; i < numColorArgs ; i++ ) {
556 const GLint op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR;
557 const GLuint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i];
558 assert(op >= 0);
559 assert(op <= 3);
560 switch ( srcRGBi ) {
561 case GL_TEXTURE:
562 if (texUnit->_Current->Image[0][0]->_BaseFormat == GL_ALPHA)
563 color_arg[i] = radeon_zero_color[op];
564 else
565 color_arg[i] = radeon_texture_color[op][unit];
566 break;
567 case GL_CONSTANT:
568 color_arg[i] = radeon_tfactor_color[op];
569 break;
570 case GL_PRIMARY_COLOR:
571 color_arg[i] = radeon_primary_color[op];
572 break;
573 case GL_PREVIOUS:
574 color_arg[i] = radeon_previous_color[op];
575 break;
576 case GL_ZERO:
577 color_arg[i] = radeon_zero_color[op];
578 break;
579 case GL_ONE:
580 color_arg[i] = radeon_zero_color[op+1];
581 break;
582 case GL_TEXTURE0:
583 case GL_TEXTURE1:
584 case GL_TEXTURE2: {
585 GLuint txunit = srcRGBi - GL_TEXTURE0;
586 if (ctx->Texture.Unit[txunit]._Current->Image[0][0]->_BaseFormat == GL_ALPHA)
587 color_arg[i] = radeon_zero_color[op];
588 else
589 /* implement ogl 1.4/1.5 core spec here, not specification of
590 * GL_ARB_texture_env_crossbar (which would require disabling blending
591 * instead of undefined results when referencing not enabled texunit) */
592 color_arg[i] = radeon_texture_color[op][txunit];
593 }
594 break;
595 default:
596 return GL_FALSE;
597 }
598 }
599
600 for ( i = 0 ; i < numAlphaArgs ; i++ ) {
601 const GLint op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA;
602 const GLuint srcAi = texUnit->_CurrentCombine->SourceA[i];
603 assert(op >= 0);
604 assert(op <= 1);
605 switch ( srcAi ) {
606 case GL_TEXTURE:
607 if (texUnit->_Current->Image[0][0]->_BaseFormat == GL_LUMINANCE)
608 alpha_arg[i] = radeon_zero_alpha[op+1];
609 else
610 alpha_arg[i] = radeon_texture_alpha[op][unit];
611 break;
612 case GL_CONSTANT:
613 alpha_arg[i] = radeon_tfactor_alpha[op];
614 break;
615 case GL_PRIMARY_COLOR:
616 alpha_arg[i] = radeon_primary_alpha[op];
617 break;
618 case GL_PREVIOUS:
619 alpha_arg[i] = radeon_previous_alpha[op];
620 break;
621 case GL_ZERO:
622 alpha_arg[i] = radeon_zero_alpha[op];
623 break;
624 case GL_ONE:
625 alpha_arg[i] = radeon_zero_alpha[op+1];
626 break;
627 case GL_TEXTURE0:
628 case GL_TEXTURE1:
629 case GL_TEXTURE2: {
630 GLuint txunit = srcAi - GL_TEXTURE0;
631 if (ctx->Texture.Unit[txunit]._Current->Image[0][0]->_BaseFormat == GL_LUMINANCE)
632 alpha_arg[i] = radeon_zero_alpha[op+1];
633 else
634 alpha_arg[i] = radeon_texture_alpha[op][txunit];
635 }
636 break;
637 default:
638 return GL_FALSE;
639 }
640 }
641
642 /* Step 2:
643 * Build up the color and alpha combine functions.
644 */
645 switch ( texUnit->_CurrentCombine->ModeRGB ) {
646 case GL_REPLACE:
647 color_combine = (RADEON_COLOR_ARG_A_ZERO |
648 RADEON_COLOR_ARG_B_ZERO |
649 RADEON_BLEND_CTL_ADD |
650 RADEON_CLAMP_TX);
651 RADEON_COLOR_ARG( 0, C );
652 break;
653 case GL_MODULATE:
654 color_combine = (RADEON_COLOR_ARG_C_ZERO |
655 RADEON_BLEND_CTL_ADD |
656 RADEON_CLAMP_TX);
657 RADEON_COLOR_ARG( 0, A );
658 RADEON_COLOR_ARG( 1, B );
659 break;
660 case GL_ADD:
661 color_combine = (RADEON_COLOR_ARG_B_ZERO |
662 RADEON_COMP_ARG_B |
663 RADEON_BLEND_CTL_ADD |
664 RADEON_CLAMP_TX);
665 RADEON_COLOR_ARG( 0, A );
666 RADEON_COLOR_ARG( 1, C );
667 break;
668 case GL_ADD_SIGNED:
669 color_combine = (RADEON_COLOR_ARG_B_ZERO |
670 RADEON_COMP_ARG_B |
671 RADEON_BLEND_CTL_ADDSIGNED |
672 RADEON_CLAMP_TX);
673 RADEON_COLOR_ARG( 0, A );
674 RADEON_COLOR_ARG( 1, C );
675 break;
676 case GL_SUBTRACT:
677 color_combine = (RADEON_COLOR_ARG_B_ZERO |
678 RADEON_COMP_ARG_B |
679 RADEON_BLEND_CTL_SUBTRACT |
680 RADEON_CLAMP_TX);
681 RADEON_COLOR_ARG( 0, A );
682 RADEON_COLOR_ARG( 1, C );
683 break;
684 case GL_INTERPOLATE:
685 color_combine = (RADEON_BLEND_CTL_BLEND |
686 RADEON_CLAMP_TX);
687 RADEON_COLOR_ARG( 0, B );
688 RADEON_COLOR_ARG( 1, A );
689 RADEON_COLOR_ARG( 2, C );
690 break;
691
692 case GL_DOT3_RGB_EXT:
693 case GL_DOT3_RGBA_EXT:
694 /* The EXT version of the DOT3 extension does not support the
695 * scale factor, but the ARB version (and the version in OpenGL
696 * 1.3) does.
697 */
698 RGBshift = 0;
699 /* FALLTHROUGH */
700
701 case GL_DOT3_RGB:
702 case GL_DOT3_RGBA:
703 /* The R100 / RV200 only support a 1X multiplier in hardware
704 * w/the ARB version.
705 */
706 if ( RGBshift != (RADEON_SCALE_1X >> RADEON_SCALE_SHIFT) ) {
707 return GL_FALSE;
708 }
709
710 RGBshift += 2;
711 if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT)
712 || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ) {
713 /* is it necessary to set this or will it be ignored anyway? */
714 Ashift = RGBshift;
715 }
716
717 color_combine = (RADEON_COLOR_ARG_C_ZERO |
718 RADEON_BLEND_CTL_DOT3 |
719 RADEON_CLAMP_TX);
720 RADEON_COLOR_ARG( 0, A );
721 RADEON_COLOR_ARG( 1, B );
722 break;
723
724 case GL_MODULATE_ADD_ATI:
725 color_combine = (RADEON_BLEND_CTL_ADD |
726 RADEON_CLAMP_TX);
727 RADEON_COLOR_ARG( 0, A );
728 RADEON_COLOR_ARG( 1, C );
729 RADEON_COLOR_ARG( 2, B );
730 break;
731 case GL_MODULATE_SIGNED_ADD_ATI:
732 color_combine = (RADEON_BLEND_CTL_ADDSIGNED |
733 RADEON_CLAMP_TX);
734 RADEON_COLOR_ARG( 0, A );
735 RADEON_COLOR_ARG( 1, C );
736 RADEON_COLOR_ARG( 2, B );
737 break;
738 case GL_MODULATE_SUBTRACT_ATI:
739 color_combine = (RADEON_BLEND_CTL_SUBTRACT |
740 RADEON_CLAMP_TX);
741 RADEON_COLOR_ARG( 0, A );
742 RADEON_COLOR_ARG( 1, C );
743 RADEON_COLOR_ARG( 2, B );
744 break;
745 default:
746 return GL_FALSE;
747 }
748
749 switch ( texUnit->_CurrentCombine->ModeA ) {
750 case GL_REPLACE:
751 alpha_combine = (RADEON_ALPHA_ARG_A_ZERO |
752 RADEON_ALPHA_ARG_B_ZERO |
753 RADEON_BLEND_CTL_ADD |
754 RADEON_CLAMP_TX);
755 RADEON_ALPHA_ARG( 0, C );
756 break;
757 case GL_MODULATE:
758 alpha_combine = (RADEON_ALPHA_ARG_C_ZERO |
759 RADEON_BLEND_CTL_ADD |
760 RADEON_CLAMP_TX);
761 RADEON_ALPHA_ARG( 0, A );
762 RADEON_ALPHA_ARG( 1, B );
763 break;
764 case GL_ADD:
765 alpha_combine = (RADEON_ALPHA_ARG_B_ZERO |
766 RADEON_COMP_ARG_B |
767 RADEON_BLEND_CTL_ADD |
768 RADEON_CLAMP_TX);
769 RADEON_ALPHA_ARG( 0, A );
770 RADEON_ALPHA_ARG( 1, C );
771 break;
772 case GL_ADD_SIGNED:
773 alpha_combine = (RADEON_ALPHA_ARG_B_ZERO |
774 RADEON_COMP_ARG_B |
775 RADEON_BLEND_CTL_ADDSIGNED |
776 RADEON_CLAMP_TX);
777 RADEON_ALPHA_ARG( 0, A );
778 RADEON_ALPHA_ARG( 1, C );
779 break;
780 case GL_SUBTRACT:
781 alpha_combine = (RADEON_COLOR_ARG_B_ZERO |
782 RADEON_COMP_ARG_B |
783 RADEON_BLEND_CTL_SUBTRACT |
784 RADEON_CLAMP_TX);
785 RADEON_ALPHA_ARG( 0, A );
786 RADEON_ALPHA_ARG( 1, C );
787 break;
788 case GL_INTERPOLATE:
789 alpha_combine = (RADEON_BLEND_CTL_BLEND |
790 RADEON_CLAMP_TX);
791 RADEON_ALPHA_ARG( 0, B );
792 RADEON_ALPHA_ARG( 1, A );
793 RADEON_ALPHA_ARG( 2, C );
794 break;
795
796 case GL_MODULATE_ADD_ATI:
797 alpha_combine = (RADEON_BLEND_CTL_ADD |
798 RADEON_CLAMP_TX);
799 RADEON_ALPHA_ARG( 0, A );
800 RADEON_ALPHA_ARG( 1, C );
801 RADEON_ALPHA_ARG( 2, B );
802 break;
803 case GL_MODULATE_SIGNED_ADD_ATI:
804 alpha_combine = (RADEON_BLEND_CTL_ADDSIGNED |
805 RADEON_CLAMP_TX);
806 RADEON_ALPHA_ARG( 0, A );
807 RADEON_ALPHA_ARG( 1, C );
808 RADEON_ALPHA_ARG( 2, B );
809 break;
810 case GL_MODULATE_SUBTRACT_ATI:
811 alpha_combine = (RADEON_BLEND_CTL_SUBTRACT |
812 RADEON_CLAMP_TX);
813 RADEON_ALPHA_ARG( 0, A );
814 RADEON_ALPHA_ARG( 1, C );
815 RADEON_ALPHA_ARG( 2, B );
816 break;
817 default:
818 return GL_FALSE;
819 }
820
821 if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGB_EXT)
822 || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGB) ) {
823 alpha_combine |= RADEON_DOT_ALPHA_DONT_REPLICATE;
824 }
825
826 /* Step 3:
827 * Apply the scale factor.
828 */
829 color_combine |= (RGBshift << RADEON_SCALE_SHIFT);
830 alpha_combine |= (Ashift << RADEON_SCALE_SHIFT);
831
832 /* All done!
833 */
834 }
835
836 if ( rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] != color_combine ||
837 rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] != alpha_combine ) {
838 RADEON_STATECHANGE( rmesa, tex[unit] );
839 rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] = color_combine;
840 rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] = alpha_combine;
841 }
842
843 return GL_TRUE;
844 }
845
846 void radeonSetTexOffset(__DRIcontext * pDRICtx, GLint texname,
847 unsigned long long offset, GLint depth, GLuint pitch)
848 {
849 radeonContextPtr rmesa = pDRICtx->driverPrivate;
850 struct gl_texture_object *tObj =
851 _mesa_lookup_texture(rmesa->glCtx, texname);
852 radeonTexObjPtr t;
853
854 if (tObj == NULL)
855 return;
856
857 t = (radeonTexObjPtr) tObj->DriverData;
858
859 t->image_override = GL_TRUE;
860
861 if (!offset)
862 return;
863
864 t->pp_txoffset = offset;
865 t->pp_txpitch = pitch - 32;
866
867 switch (depth) {
868 case 32:
869 t->pp_txformat = tx_table[MESA_FORMAT_ARGB8888].format;
870 t->pp_txfilter |= tx_table[MESA_FORMAT_ARGB8888].filter;
871 break;
872 case 24:
873 default:
874 t->pp_txformat = tx_table[MESA_FORMAT_RGB888].format;
875 t->pp_txfilter |= tx_table[MESA_FORMAT_RGB888].filter;
876 break;
877 case 16:
878 t->pp_txformat = tx_table[MESA_FORMAT_RGB565].format;
879 t->pp_txfilter |= tx_table[MESA_FORMAT_RGB565].filter;
880 break;
881 }
882 }
883
884 #define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK | \
885 RADEON_MIN_FILTER_MASK | \
886 RADEON_MAG_FILTER_MASK | \
887 RADEON_MAX_ANISO_MASK | \
888 RADEON_YUV_TO_RGB | \
889 RADEON_YUV_TEMPERATURE_MASK | \
890 RADEON_CLAMP_S_MASK | \
891 RADEON_CLAMP_T_MASK | \
892 RADEON_BORDER_MODE_D3D )
893
894 #define TEXOBJ_TXFORMAT_MASK (RADEON_TXFORMAT_WIDTH_MASK | \
895 RADEON_TXFORMAT_HEIGHT_MASK | \
896 RADEON_TXFORMAT_FORMAT_MASK | \
897 RADEON_TXFORMAT_F5_WIDTH_MASK | \
898 RADEON_TXFORMAT_F5_HEIGHT_MASK | \
899 RADEON_TXFORMAT_ALPHA_IN_MAP | \
900 RADEON_TXFORMAT_CUBIC_MAP_ENABLE | \
901 RADEON_TXFORMAT_NON_POWER2)
902
903
904 static void import_tex_obj_state( radeonContextPtr rmesa,
905 int unit,
906 radeonTexObjPtr texobj )
907 {
908 /* do not use RADEON_DB_STATE to avoid stale texture caches */
909 int *cmd = &rmesa->hw.tex[unit].cmd[TEX_CMD_0];
910 GLuint se_coord_fmt = rmesa->hw.set.cmd[SET_SE_COORDFMT];
911
912 RADEON_STATECHANGE( rmesa, tex[unit] );
913
914 cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
915 cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK;
916 cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
917 cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
918 cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset;
919 cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
920
921 if (texobj->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
922 GLuint *txr_cmd = RADEON_DB_STATE( txr[unit] );
923 txr_cmd[TXR_PP_TEX_SIZE] = texobj->pp_txsize; /* NPOT only! */
924 txr_cmd[TXR_PP_TEX_PITCH] = texobj->pp_txpitch; /* NPOT only! */
925 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.txr[unit] );
926 se_coord_fmt |= RADEON_VTX_ST0_NONPARAMETRIC << unit;
927 }
928 else {
929 se_coord_fmt &= ~(RADEON_VTX_ST0_NONPARAMETRIC << unit);
930
931 if (texobj->base.tObj->Target == GL_TEXTURE_CUBE_MAP) {
932 int *cube_cmd = &rmesa->hw.cube[unit].cmd[CUBE_CMD_0];
933 GLuint bytesPerFace = texobj->base.totalSize / 6;
934 ASSERT(texobj->base.totalSize % 6 == 0);
935
936 RADEON_STATECHANGE( rmesa, cube[unit] );
937 cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
938 /* dont know if this setup conforms to OpenGL..
939 * at least it matches the behavior of mesa software renderer
940 */
941 cube_cmd[CUBE_PP_CUBIC_OFFSET_0] = texobj->pp_txoffset; /* right */
942 cube_cmd[CUBE_PP_CUBIC_OFFSET_1] = texobj->pp_txoffset + 1 * bytesPerFace; /* left */
943 cube_cmd[CUBE_PP_CUBIC_OFFSET_2] = texobj->pp_txoffset + 2 * bytesPerFace; /* top */
944 cube_cmd[CUBE_PP_CUBIC_OFFSET_3] = texobj->pp_txoffset + 3 * bytesPerFace; /* bottom */
945 cube_cmd[CUBE_PP_CUBIC_OFFSET_4] = texobj->pp_txoffset + 4 * bytesPerFace; /* front */
946 cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset + 5 * bytesPerFace; /* back */
947 }
948 }
949
950 if (se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT]) {
951 RADEON_STATECHANGE( rmesa, set );
952 rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt;
953 }
954
955 texobj->dirty_state &= ~(1<<unit);
956 }
957
958
959
960
961 static void set_texgen_matrix( radeonContextPtr rmesa,
962 GLuint unit,
963 const GLfloat *s_plane,
964 const GLfloat *t_plane,
965 const GLfloat *r_plane,
966 const GLfloat *q_plane )
967 {
968 rmesa->TexGenMatrix[unit].m[0] = s_plane[0];
969 rmesa->TexGenMatrix[unit].m[4] = s_plane[1];
970 rmesa->TexGenMatrix[unit].m[8] = s_plane[2];
971 rmesa->TexGenMatrix[unit].m[12] = s_plane[3];
972
973 rmesa->TexGenMatrix[unit].m[1] = t_plane[0];
974 rmesa->TexGenMatrix[unit].m[5] = t_plane[1];
975 rmesa->TexGenMatrix[unit].m[9] = t_plane[2];
976 rmesa->TexGenMatrix[unit].m[13] = t_plane[3];
977
978 rmesa->TexGenMatrix[unit].m[2] = r_plane[0];
979 rmesa->TexGenMatrix[unit].m[6] = r_plane[1];
980 rmesa->TexGenMatrix[unit].m[10] = r_plane[2];
981 rmesa->TexGenMatrix[unit].m[14] = r_plane[3];
982
983 rmesa->TexGenMatrix[unit].m[3] = q_plane[0];
984 rmesa->TexGenMatrix[unit].m[7] = q_plane[1];
985 rmesa->TexGenMatrix[unit].m[11] = q_plane[2];
986 rmesa->TexGenMatrix[unit].m[15] = q_plane[3];
987
988 rmesa->TexGenEnabled |= RADEON_TEXMAT_0_ENABLE << unit;
989 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
990 }
991
992 /* Returns GL_FALSE if fallback required.
993 */
994 static GLboolean radeon_validate_texgen( GLcontext *ctx, GLuint unit )
995 {
996 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
997 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
998 GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
999 GLuint tmp = rmesa->TexGenEnabled;
1000 static const GLfloat reflect[16] = {
1001 -1, 0, 0, 0,
1002 0, -1, 0, 0,
1003 0, 0, -1, 0,
1004 0, 0, 0, 1 };
1005
1006 rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE << unit);
1007 rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE << unit);
1008 rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK << inputshift);
1009 rmesa->TexGenNeedNormals[unit] = 0;
1010
1011 if ((texUnit->TexGenEnabled & (S_BIT|T_BIT|R_BIT|Q_BIT)) == 0) {
1012 /* Disabled, no fallback:
1013 */
1014 rmesa->TexGenEnabled |=
1015 (RADEON_TEXGEN_INPUT_TEXCOORD_0 + unit) << inputshift;
1016 return GL_TRUE;
1017 }
1018 /* the r100 cannot do texgen for some coords and not for others
1019 * we do not detect such cases (certainly can't do it here) and just
1020 * ASSUME that when S and T are texgen enabled we do not need other
1021 * non-texgen enabled coords, no matter if the R and Q bits are texgen
1022 * enabled. Still check for mixed mode texgen for all coords.
1023 */
1024 else if ( (texUnit->TexGenEnabled & S_BIT) &&
1025 (texUnit->TexGenEnabled & T_BIT) &&
1026 (texUnit->GenModeS == texUnit->GenModeT) ) {
1027 if ( ((texUnit->TexGenEnabled & R_BIT) &&
1028 (texUnit->GenModeS != texUnit->GenModeR)) ||
1029 ((texUnit->TexGenEnabled & Q_BIT) &&
1030 (texUnit->GenModeS != texUnit->GenModeQ)) ) {
1031 /* Mixed modes, fallback:
1032 */
1033 if (RADEON_DEBUG & DEBUG_FALLBACKS)
1034 fprintf(stderr, "fallback mixed texgen\n");
1035 return GL_FALSE;
1036 }
1037 rmesa->TexGenEnabled |= RADEON_TEXGEN_TEXMAT_0_ENABLE << unit;
1038 }
1039 else {
1040 /* some texgen mode not including both S and T bits */
1041 if (RADEON_DEBUG & DEBUG_FALLBACKS)
1042 fprintf(stderr, "fallback mixed texgen/nontexgen\n");
1043 return GL_FALSE;
1044 }
1045
1046 if ((texUnit->TexGenEnabled & (R_BIT | Q_BIT)) != 0) {
1047 /* need this here for vtxfmt presumably. Argh we need to set
1048 this from way too many places, would be much easier if we could leave
1049 tcl q coord always enabled as on r200) */
1050 RADEON_STATECHANGE( rmesa, tcl );
1051 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_Q_BIT(unit);
1052 }
1053
1054 switch (texUnit->GenModeS) {
1055 case GL_OBJECT_LINEAR:
1056 rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_OBJ << inputshift;
1057 set_texgen_matrix( rmesa, unit,
1058 texUnit->ObjectPlaneS,
1059 texUnit->ObjectPlaneT,
1060 texUnit->ObjectPlaneR,
1061 texUnit->ObjectPlaneQ);
1062 break;
1063
1064 case GL_EYE_LINEAR:
1065 rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE << inputshift;
1066 set_texgen_matrix( rmesa, unit,
1067 texUnit->EyePlaneS,
1068 texUnit->EyePlaneT,
1069 texUnit->EyePlaneR,
1070 texUnit->EyePlaneQ);
1071 break;
1072
1073 case GL_REFLECTION_MAP_NV:
1074 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1075 rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_REFLECT << inputshift;
1076 /* TODO: unknown if this is needed/correct */
1077 set_texgen_matrix( rmesa, unit, reflect, reflect + 4,
1078 reflect + 8, reflect + 12 );
1079 break;
1080
1081 case GL_NORMAL_MAP_NV:
1082 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1083 rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_NORMAL << inputshift;
1084 break;
1085
1086 case GL_SPHERE_MAP:
1087 /* the mode which everyone uses :-( */
1088 default:
1089 /* Unsupported mode, fallback:
1090 */
1091 if (RADEON_DEBUG & DEBUG_FALLBACKS)
1092 fprintf(stderr, "fallback GL_SPHERE_MAP\n");
1093 return GL_FALSE;
1094 }
1095
1096 if (tmp != rmesa->TexGenEnabled) {
1097 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1098 }
1099
1100 return GL_TRUE;
1101 }
1102
1103
1104 static void disable_tex( GLcontext *ctx, int unit )
1105 {
1106 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1107
1108 if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit)) {
1109 /* Texture unit disabled */
1110 if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
1111 /* The old texture is no longer bound to this texture unit.
1112 * Mark it as such.
1113 */
1114
1115 rmesa->state.texture.unit[unit].texobj->base.bound &= ~(1UL << unit);
1116 rmesa->state.texture.unit[unit].texobj = NULL;
1117 }
1118
1119 RADEON_STATECHANGE( rmesa, ctx );
1120 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &=
1121 ~((RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit);
1122
1123 RADEON_STATECHANGE( rmesa, tcl );
1124 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_ST_BIT(unit) |
1125 RADEON_Q_BIT(unit));
1126
1127 if (rmesa->TclFallback & (RADEON_TCL_FALLBACK_TEXGEN_0<<unit)) {
1128 TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
1129 rmesa->recheck_texgen[unit] = GL_TRUE;
1130 }
1131
1132 if (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) {
1133 /* this seems to be a genuine (r100 only?) hw bug. Need to remove the
1134 cubic_map bit on unit 2 when the unit is disabled, otherwise every
1135 2nd (2d) mipmap on unit 0 will be broken (may not be needed for other
1136 units, better be safe than sorry though).*/
1137 RADEON_STATECHANGE( rmesa, tex[unit] );
1138 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= ~RADEON_TXFORMAT_CUBIC_MAP_ENABLE;
1139 }
1140
1141 {
1142 GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
1143 GLuint tmp = rmesa->TexGenEnabled;
1144
1145 rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit);
1146 rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit);
1147 rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift);
1148 rmesa->TexGenNeedNormals[unit] = 0;
1149 rmesa->TexGenEnabled |=
1150 (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
1151
1152 if (tmp != rmesa->TexGenEnabled) {
1153 rmesa->recheck_texgen[unit] = GL_TRUE;
1154 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1155 }
1156 }
1157 }
1158 }
1159
1160 static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
1161 {
1162 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1163 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1164 struct gl_texture_object *tObj = texUnit->_Current;
1165 radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
1166
1167 /* Need to load the 2d images associated with this unit.
1168 */
1169 if (t->pp_txformat & RADEON_TXFORMAT_NON_POWER2) {
1170 t->pp_txformat &= ~RADEON_TXFORMAT_NON_POWER2;
1171 t->base.dirty_images[0] = ~0;
1172 }
1173
1174 ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
1175
1176 if ( t->base.dirty_images[0] ) {
1177 RADEON_FIREVERTICES( rmesa );
1178 radeonSetTexImages( rmesa, tObj );
1179 radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 );
1180 if ( !t->base.memBlock && !t->image_override )
1181 return GL_FALSE;
1182 }
1183
1184 return GL_TRUE;
1185 }
1186
1187 static GLboolean enable_tex_cube( GLcontext *ctx, int unit )
1188 {
1189 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1190 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1191 struct gl_texture_object *tObj = texUnit->_Current;
1192 radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
1193 GLuint face;
1194
1195 /* Need to load the 2d images associated with this unit.
1196 */
1197 if (t->pp_txformat & RADEON_TXFORMAT_NON_POWER2) {
1198 t->pp_txformat &= ~RADEON_TXFORMAT_NON_POWER2;
1199 for (face = 0; face < 6; face++)
1200 t->base.dirty_images[face] = ~0;
1201 }
1202
1203 ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP);
1204
1205 if ( t->base.dirty_images[0] || t->base.dirty_images[1] ||
1206 t->base.dirty_images[2] || t->base.dirty_images[3] ||
1207 t->base.dirty_images[4] || t->base.dirty_images[5] ) {
1208 /* flush */
1209 RADEON_FIREVERTICES( rmesa );
1210 /* layout memory space, once for all faces */
1211 radeonSetTexImages( rmesa, tObj );
1212 }
1213
1214 /* upload (per face) */
1215 for (face = 0; face < 6; face++) {
1216 if (t->base.dirty_images[face]) {
1217 radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, face );
1218 }
1219 }
1220
1221 if ( !t->base.memBlock ) {
1222 /* texmem alloc failed, use s/w fallback */
1223 return GL_FALSE;
1224 }
1225
1226 return GL_TRUE;
1227 }
1228
1229 static GLboolean enable_tex_rect( GLcontext *ctx, int unit )
1230 {
1231 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1232 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1233 struct gl_texture_object *tObj = texUnit->_Current;
1234 radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
1235
1236 if (!(t->pp_txformat & RADEON_TXFORMAT_NON_POWER2)) {
1237 t->pp_txformat |= RADEON_TXFORMAT_NON_POWER2;
1238 t->base.dirty_images[0] = ~0;
1239 }
1240
1241 ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
1242
1243 if ( t->base.dirty_images[0] ) {
1244 RADEON_FIREVERTICES( rmesa );
1245 radeonSetTexImages( rmesa, tObj );
1246 radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 );
1247 if ( !t->base.memBlock &&
1248 !t->image_override /* && !rmesa->prefer_gart_client_texturing FIXME */ ) {
1249 fprintf(stderr, "%s: upload failed\n", __FUNCTION__);
1250 return GL_FALSE;
1251 }
1252 }
1253
1254 return GL_TRUE;
1255 }
1256
1257
1258 static GLboolean update_tex_common( GLcontext *ctx, int unit )
1259 {
1260 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1261 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1262 struct gl_texture_object *tObj = texUnit->_Current;
1263 radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
1264 GLenum format;
1265
1266 /* Fallback if there's a texture border */
1267 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
1268 fprintf(stderr, "%s: border\n", __FUNCTION__);
1269 return GL_FALSE;
1270 }
1271 /* yuv conversion only works in first unit */
1272 if (unit != 0 && (t->pp_txfilter & RADEON_YUV_TO_RGB))
1273 return GL_FALSE;
1274
1275 /* Update state if this is a different texture object to last
1276 * time.
1277 */
1278 if ( rmesa->state.texture.unit[unit].texobj != t ) {
1279 if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
1280 /* The old texture is no longer bound to this texture unit.
1281 * Mark it as such.
1282 */
1283
1284 rmesa->state.texture.unit[unit].texobj->base.bound &=
1285 ~(1UL << unit);
1286 }
1287
1288 rmesa->state.texture.unit[unit].texobj = t;
1289 t->base.bound |= (1UL << unit);
1290 t->dirty_state |= 1<<unit;
1291 driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
1292 }
1293
1294
1295 /* Newly enabled?
1296 */
1297 if ( !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit))) {
1298 RADEON_STATECHANGE( rmesa, ctx );
1299 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=
1300 (RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit;
1301
1302 RADEON_STATECHANGE( rmesa, tcl );
1303
1304 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_ST_BIT(unit);
1305
1306 rmesa->recheck_texgen[unit] = GL_TRUE;
1307 }
1308
1309 if (t->dirty_state & (1<<unit)) {
1310 import_tex_obj_state( rmesa, unit, t );
1311 /* may need to update texture matrix (for texrect adjustments) */
1312 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1313 }
1314
1315 if (rmesa->recheck_texgen[unit]) {
1316 GLboolean fallback = !radeon_validate_texgen( ctx, unit );
1317 TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
1318 rmesa->recheck_texgen[unit] = 0;
1319 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1320 }
1321
1322 format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
1323 if ( rmesa->state.texture.unit[unit].format != format ||
1324 rmesa->state.texture.unit[unit].envMode != texUnit->EnvMode ) {
1325 rmesa->state.texture.unit[unit].format = format;
1326 rmesa->state.texture.unit[unit].envMode = texUnit->EnvMode;
1327 if ( ! radeonUpdateTextureEnv( ctx, unit ) ) {
1328 return GL_FALSE;
1329 }
1330 }
1331
1332 FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback );
1333 return !t->border_fallback;
1334 }
1335
1336
1337
1338 static GLboolean radeonUpdateTextureUnit( GLcontext *ctx, int unit )
1339 {
1340 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1341
1342 if ( texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT) ) {
1343 return (enable_tex_rect( ctx, unit ) &&
1344 update_tex_common( ctx, unit ));
1345 }
1346 else if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
1347 return (enable_tex_2d( ctx, unit ) &&
1348 update_tex_common( ctx, unit ));
1349 }
1350 else if ( texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT) ) {
1351 return (enable_tex_cube( ctx, unit ) &&
1352 update_tex_common( ctx, unit ));
1353 }
1354 else if ( texUnit->_ReallyEnabled ) {
1355 return GL_FALSE;
1356 }
1357 else {
1358 disable_tex( ctx, unit );
1359 return GL_TRUE;
1360 }
1361 }
1362
1363 void radeonUpdateTextureState( GLcontext *ctx )
1364 {
1365 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1366 GLboolean ok;
1367
1368 ok = (radeonUpdateTextureUnit( ctx, 0 ) &&
1369 radeonUpdateTextureUnit( ctx, 1 ) &&
1370 radeonUpdateTextureUnit( ctx, 2 ));
1371
1372 FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, !ok );
1373
1374 if (rmesa->TclFallback)
1375 radeonChooseVertexState( ctx );
1376 }