Bug #1588: abort if no palette format matches. (Egbert Eich, Stefan Dirsch)
[mesa.git] / src / mesa / drivers / dri / r200 / r200_texstate.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_texstate.c,v 1.3 2003/02/15 22:18:47 dawes Exp $ */
2 /*
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
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.
8
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:
16
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.
20
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.
28
29 **************************************************************************/
30
31 /*
32 * Authors:
33 * Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36 #include "glheader.h"
37 #include "imports.h"
38 #include "context.h"
39 #include "macros.h"
40 #include "texformat.h"
41 #include "enums.h"
42
43 #include "r200_context.h"
44 #include "r200_state.h"
45 #include "r200_ioctl.h"
46 #include "r200_swtcl.h"
47 #include "r200_tex.h"
48 #include "r200_tcl.h"
49
50
51 #define R200_TXFORMAT_A8 R200_TXFORMAT_I8
52 #define R200_TXFORMAT_L8 R200_TXFORMAT_I8
53 #define R200_TXFORMAT_AL88 R200_TXFORMAT_AI88
54 #define R200_TXFORMAT_YCBCR R200_TXFORMAT_YVYU422
55 #define R200_TXFORMAT_YCBCR_REV R200_TXFORMAT_VYUY422
56 #define R200_TXFORMAT_RGB_DXT1 R200_TXFORMAT_DXT1
57 #define R200_TXFORMAT_RGBA_DXT1 R200_TXFORMAT_DXT1
58 #define R200_TXFORMAT_RGBA_DXT3 R200_TXFORMAT_DXT23
59 #define R200_TXFORMAT_RGBA_DXT5 R200_TXFORMAT_DXT45
60
61 #define _COLOR(f) \
62 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, 0 }
63 #define _COLOR_REV(f) \
64 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f, 0 }
65 #define _ALPHA(f) \
66 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
67 #define _ALPHA_REV(f) \
68 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
69 #define _YUV(f) \
70 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, R200_YUV_TO_RGB }
71 #define _INVALID(f) \
72 [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
73 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
74 && (tx_table[f].format != 0xffffffff) )
75
76 static const struct {
77 GLuint format, filter;
78 }
79 tx_table[] =
80 {
81 _ALPHA(RGBA8888),
82 _ALPHA_REV(RGBA8888),
83 _ALPHA(ARGB8888),
84 _ALPHA_REV(ARGB8888),
85 _INVALID(RGB888),
86 _COLOR(RGB565),
87 _COLOR_REV(RGB565),
88 _ALPHA(ARGB4444),
89 _ALPHA_REV(ARGB4444),
90 _ALPHA(ARGB1555),
91 _ALPHA_REV(ARGB1555),
92 _ALPHA(AL88),
93 _ALPHA_REV(AL88),
94 _ALPHA(A8),
95 _COLOR(L8),
96 _ALPHA(I8),
97 _INVALID(CI8),
98 _YUV(YCBCR),
99 _YUV(YCBCR_REV),
100 _INVALID(RGB_FXT1),
101 _INVALID(RGBA_FXT1),
102 _COLOR(RGB_DXT1),
103 _ALPHA(RGBA_DXT1),
104 _ALPHA(RGBA_DXT3),
105 _ALPHA(RGBA_DXT5),
106 };
107
108 #undef _COLOR
109 #undef _ALPHA
110 #undef _INVALID
111
112 /**
113 * This function computes the number of bytes of storage needed for
114 * the given texture object (all mipmap levels, all cube faces).
115 * The \c image[face][level].x/y/width/height parameters for upload/blitting
116 * are computed here. \c pp_txfilter, \c pp_txformat, etc. will be set here
117 * too.
118 *
119 * \param rmesa Context pointer
120 * \param tObj GL texture object whose images are to be posted to
121 * hardware state.
122 */
123 static void r200SetTexImages( r200ContextPtr rmesa,
124 struct gl_texture_object *tObj )
125 {
126 r200TexObjPtr t = (r200TexObjPtr)tObj->DriverData;
127 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
128 GLint curOffset;
129 GLint i;
130 GLint numLevels;
131 GLint log2Width, log2Height, log2Depth;
132
133 /* Set the hardware texture format
134 */
135
136 t->pp_txformat &= ~(R200_TXFORMAT_FORMAT_MASK |
137 R200_TXFORMAT_ALPHA_IN_MAP);
138 t->pp_txfilter &= ~R200_YUV_TO_RGB;
139
140 if ( VALID_FORMAT( baseImage->TexFormat->MesaFormat ) ) {
141 t->pp_txformat |= tx_table[ baseImage->TexFormat->MesaFormat ].format;
142 t->pp_txfilter |= tx_table[ baseImage->TexFormat->MesaFormat ].filter;
143 }
144 else {
145 _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
146 return;
147 }
148
149
150 /* Compute which mipmap levels we really want to send to the hardware.
151 */
152
153 driCalculateTextureFirstLastLevel( (driTextureObject *) t );
154 log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2;
155 log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
156 log2Depth = tObj->Image[0][t->base.firstLevel]->DepthLog2;
157
158 numLevels = t->base.lastLevel - t->base.firstLevel + 1;
159
160 assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
161
162 /* Calculate mipmap offsets and dimensions for blitting (uploading)
163 * The idea is that we lay out the mipmap levels within a block of
164 * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
165 */
166 curOffset = 0;
167
168 for (i = 0; i < numLevels; i++) {
169 const struct gl_texture_image *texImage;
170 GLuint size;
171
172 texImage = tObj->Image[0][i + t->base.firstLevel];
173 if ( !texImage )
174 break;
175
176 /* find image size in bytes */
177 if (texImage->IsCompressed) {
178 /* need to calculate the size AFTER padding even though the texture is
179 submitted without padding.
180 Only handle pot textures currently - don't know if npot is even possible,
181 size calculation would certainly need (trivial) adjustments.
182 Align (and later pad) to 32byte, not sure what that 64byte blit width is
183 good for? */
184 if ((t->pp_txformat & R200_TXFORMAT_FORMAT_MASK) == R200_TXFORMAT_DXT1) {
185 /* RGB_DXT1/RGBA_DXT1, 8 bytes per block */
186 if ((texImage->Width + 3) < 8) /* width one block */
187 size = texImage->CompressedSize * 4;
188 else if ((texImage->Width + 3) < 16)
189 size = texImage->CompressedSize * 2;
190 else size = texImage->CompressedSize;
191 }
192 else /* DXT3/5, 16 bytes per block */
193 if ((texImage->Width + 3) < 8)
194 size = texImage->CompressedSize * 2;
195 else size = texImage->CompressedSize;
196 }
197 else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
198 size = ((texImage->Width * texImage->TexFormat->TexelBytes + 63)
199 & ~63) * texImage->Height;
200 }
201 else {
202 int w = texImage->Width * texImage->TexFormat->TexelBytes;
203 if (w < 32)
204 w = 32;
205 size = w * texImage->Height * texImage->Depth;
206 }
207 assert(size > 0);
208
209
210 /* Align to 32-byte offset. It is faster to do this unconditionally
211 * (no branch penalty).
212 */
213
214 curOffset = (curOffset + 0x1f) & ~0x1f;
215
216 t->image[0][i].x = curOffset % BLIT_WIDTH_BYTES;
217 t->image[0][i].y = curOffset / BLIT_WIDTH_BYTES;
218 t->image[0][i].width = MIN2(size, BLIT_WIDTH_BYTES);
219 t->image[0][i].height = size / t->image[0][i].width;
220
221 #if 0
222 /* for debugging only and only applicable to non-rectangle targets */
223 assert(size % t->image[0][i].width == 0);
224 assert(t->image[0][i].x == 0
225 || (size < BLIT_WIDTH_BYTES && t->image[0][i].height == 1));
226 #endif
227
228 if (0)
229 fprintf(stderr,
230 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
231 i, texImage->Width, texImage->Height,
232 t->image[0][i].x, t->image[0][i].y,
233 t->image[0][i].width, t->image[0][i].height, size, curOffset);
234
235 curOffset += size;
236
237 }
238
239 /* Align the total size of texture memory block.
240 */
241 t->base.totalSize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
242
243 /* Setup remaining cube face blits, if needed */
244 if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
245 /* Round totalSize up to multiple of BLIT_WIDTH_BYTES */
246 const GLuint faceSize = (t->base.totalSize + BLIT_WIDTH_BYTES - 1)
247 & ~(BLIT_WIDTH_BYTES-1);
248 const GLuint lines = faceSize / BLIT_WIDTH_BYTES;
249 GLuint face;
250 /* reuse face 0 x/y/width/height - just adjust y */
251 for (face = 1; face < 6; face++) {
252 for (i = 0; i < numLevels; i++) {
253 t->image[face][i].x = t->image[0][i].x;
254 t->image[face][i].y = t->image[0][i].y + face * lines;
255 t->image[face][i].width = t->image[0][i].width;
256 t->image[face][i].height = t->image[0][i].height;
257 }
258 }
259 t->base.totalSize = 6 * faceSize; /* total texmem needed */
260 }
261
262
263 /* Hardware state:
264 */
265 t->pp_txfilter &= ~R200_MAX_MIP_LEVEL_MASK;
266 t->pp_txfilter |= (numLevels - 1) << R200_MAX_MIP_LEVEL_SHIFT;
267
268 t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK |
269 R200_TXFORMAT_HEIGHT_MASK |
270 R200_TXFORMAT_CUBIC_MAP_ENABLE |
271 R200_TXFORMAT_F5_WIDTH_MASK |
272 R200_TXFORMAT_F5_HEIGHT_MASK);
273 t->pp_txformat |= ((log2Width << R200_TXFORMAT_WIDTH_SHIFT) |
274 (log2Height << R200_TXFORMAT_HEIGHT_SHIFT));
275
276 t->pp_txformat_x &= ~(R200_DEPTH_LOG2_MASK | R200_TEXCOORD_MASK);
277 if (tObj->Target == GL_TEXTURE_3D) {
278 t->pp_txformat_x |= (log2Depth << R200_DEPTH_LOG2_SHIFT);
279 t->pp_txformat_x |= R200_TEXCOORD_VOLUME;
280 }
281 else if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
282 ASSERT(log2Width == log2height);
283 t->pp_txformat |= ((log2Width << R200_TXFORMAT_F5_WIDTH_SHIFT) |
284 (log2Height << R200_TXFORMAT_F5_HEIGHT_SHIFT) |
285 (R200_TXFORMAT_CUBIC_MAP_ENABLE));
286 t->pp_txformat_x |= R200_TEXCOORD_CUBIC_ENV;
287 t->pp_cubic_faces = ((log2Width << R200_FACE_WIDTH_1_SHIFT) |
288 (log2Height << R200_FACE_HEIGHT_1_SHIFT) |
289 (log2Width << R200_FACE_WIDTH_2_SHIFT) |
290 (log2Height << R200_FACE_HEIGHT_2_SHIFT) |
291 (log2Width << R200_FACE_WIDTH_3_SHIFT) |
292 (log2Height << R200_FACE_HEIGHT_3_SHIFT) |
293 (log2Width << R200_FACE_WIDTH_4_SHIFT) |
294 (log2Height << R200_FACE_HEIGHT_4_SHIFT));
295 }
296
297 t->pp_txsize = (((tObj->Image[0][t->base.firstLevel]->Width - 1) << 0) |
298 ((tObj->Image[0][t->base.firstLevel]->Height - 1) << 16));
299
300 /* Only need to round to nearest 32 for textures, but the blitter
301 * requires 64-byte aligned pitches, and we may/may not need the
302 * blitter. NPOT only!
303 */
304 if (baseImage->IsCompressed)
305 t->pp_txpitch = (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63);
306 else
307 t->pp_txpitch = ((tObj->Image[0][t->base.firstLevel]->Width * baseImage->TexFormat->TexelBytes) + 63) & ~(63);
308 t->pp_txpitch -= 32;
309
310 t->dirty_state = TEX_ALL;
311
312 /* FYI: r200UploadTexImages( rmesa, t ) used to be called here */
313 }
314
315
316
317 /* ================================================================
318 * Texture combine functions
319 */
320
321 /* GL_ARB_texture_env_combine support
322 */
323
324 /* The color tables have combine functions for GL_SRC_COLOR,
325 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
326 */
327 static GLuint r200_register_color[][R200_MAX_TEXTURE_UNITS] =
328 {
329 {
330 R200_TXC_ARG_A_R0_COLOR,
331 R200_TXC_ARG_A_R1_COLOR,
332 R200_TXC_ARG_A_R2_COLOR,
333 R200_TXC_ARG_A_R3_COLOR,
334 R200_TXC_ARG_A_R4_COLOR,
335 R200_TXC_ARG_A_R5_COLOR
336 },
337 {
338 R200_TXC_ARG_A_R0_COLOR | R200_TXC_COMP_ARG_A,
339 R200_TXC_ARG_A_R1_COLOR | R200_TXC_COMP_ARG_A,
340 R200_TXC_ARG_A_R2_COLOR | R200_TXC_COMP_ARG_A,
341 R200_TXC_ARG_A_R3_COLOR | R200_TXC_COMP_ARG_A,
342 R200_TXC_ARG_A_R4_COLOR | R200_TXC_COMP_ARG_A,
343 R200_TXC_ARG_A_R5_COLOR | R200_TXC_COMP_ARG_A
344 },
345 {
346 R200_TXC_ARG_A_R0_ALPHA,
347 R200_TXC_ARG_A_R1_ALPHA,
348 R200_TXC_ARG_A_R2_ALPHA,
349 R200_TXC_ARG_A_R3_ALPHA,
350 R200_TXC_ARG_A_R4_ALPHA,
351 R200_TXC_ARG_A_R5_ALPHA
352 },
353 {
354 R200_TXC_ARG_A_R0_ALPHA | R200_TXC_COMP_ARG_A,
355 R200_TXC_ARG_A_R1_ALPHA | R200_TXC_COMP_ARG_A,
356 R200_TXC_ARG_A_R2_ALPHA | R200_TXC_COMP_ARG_A,
357 R200_TXC_ARG_A_R3_ALPHA | R200_TXC_COMP_ARG_A,
358 R200_TXC_ARG_A_R4_ALPHA | R200_TXC_COMP_ARG_A,
359 R200_TXC_ARG_A_R5_ALPHA | R200_TXC_COMP_ARG_A
360 },
361 };
362
363 static GLuint r200_tfactor_color[] =
364 {
365 R200_TXC_ARG_A_TFACTOR_COLOR,
366 R200_TXC_ARG_A_TFACTOR_COLOR | R200_TXC_COMP_ARG_A,
367 R200_TXC_ARG_A_TFACTOR_ALPHA,
368 R200_TXC_ARG_A_TFACTOR_ALPHA | R200_TXC_COMP_ARG_A
369 };
370
371 static GLuint r200_primary_color[] =
372 {
373 R200_TXC_ARG_A_DIFFUSE_COLOR,
374 R200_TXC_ARG_A_DIFFUSE_COLOR | R200_TXC_COMP_ARG_A,
375 R200_TXC_ARG_A_DIFFUSE_ALPHA,
376 R200_TXC_ARG_A_DIFFUSE_ALPHA | R200_TXC_COMP_ARG_A
377 };
378
379 /* GL_ZERO table - indices 0-3
380 * GL_ONE table - indices 1-4
381 */
382 static GLuint r200_zero_color[] =
383 {
384 R200_TXC_ARG_A_ZERO,
385 R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A,
386 R200_TXC_ARG_A_ZERO,
387 R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A,
388 R200_TXC_ARG_A_ZERO
389 };
390
391 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
392 */
393 static GLuint r200_register_alpha[][R200_MAX_TEXTURE_UNITS] =
394 {
395 {
396 R200_TXA_ARG_A_R0_ALPHA,
397 R200_TXA_ARG_A_R1_ALPHA,
398 R200_TXA_ARG_A_R2_ALPHA,
399 R200_TXA_ARG_A_R3_ALPHA,
400 R200_TXA_ARG_A_R4_ALPHA,
401 R200_TXA_ARG_A_R5_ALPHA
402 },
403 {
404 R200_TXA_ARG_A_R0_ALPHA | R200_TXA_COMP_ARG_A,
405 R200_TXA_ARG_A_R1_ALPHA | R200_TXA_COMP_ARG_A,
406 R200_TXA_ARG_A_R2_ALPHA | R200_TXA_COMP_ARG_A,
407 R200_TXA_ARG_A_R3_ALPHA | R200_TXA_COMP_ARG_A,
408 R200_TXA_ARG_A_R4_ALPHA | R200_TXA_COMP_ARG_A,
409 R200_TXA_ARG_A_R5_ALPHA | R200_TXA_COMP_ARG_A
410 },
411 };
412
413 static GLuint r200_tfactor_alpha[] =
414 {
415 R200_TXA_ARG_A_TFACTOR_ALPHA,
416 R200_TXA_ARG_A_TFACTOR_ALPHA | R200_TXA_COMP_ARG_A
417 };
418
419 static GLuint r200_primary_alpha[] =
420 {
421 R200_TXA_ARG_A_DIFFUSE_ALPHA,
422 R200_TXA_ARG_A_DIFFUSE_ALPHA | R200_TXA_COMP_ARG_A
423 };
424
425 /* GL_ZERO table - indices 0-1
426 * GL_ONE table - indices 1-2
427 */
428 static GLuint r200_zero_alpha[] =
429 {
430 R200_TXA_ARG_A_ZERO,
431 R200_TXA_ARG_A_ZERO | R200_TXA_COMP_ARG_A,
432 R200_TXA_ARG_A_ZERO,
433 };
434
435
436 /* Extract the arg from slot A, shift it into the correct argument slot
437 * and set the corresponding complement bit.
438 */
439 #define R200_COLOR_ARG( n, arg ) \
440 do { \
441 color_combine |= \
442 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
443 << R200_TXC_ARG_##arg##_SHIFT); \
444 color_combine |= \
445 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
446 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
447 } while (0)
448
449 #define R200_ALPHA_ARG( n, arg ) \
450 do { \
451 alpha_combine |= \
452 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
453 << R200_TXA_ARG_##arg##_SHIFT); \
454 alpha_combine |= \
455 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
456 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
457 } while (0)
458
459
460 /* ================================================================
461 * Texture unit state management
462 */
463
464 static GLboolean r200UpdateTextureEnv( GLcontext *ctx, int unit )
465 {
466 r200ContextPtr rmesa = R200_CONTEXT(ctx);
467 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
468 GLuint color_combine, alpha_combine;
469 GLuint color_scale = rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND2] &
470 ~(R200_TXC_SCALE_MASK);
471 GLuint alpha_scale = rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND2] &
472 ~(R200_TXA_DOT_ALPHA | R200_TXA_SCALE_MASK);
473
474 /* texUnit->_Current can be NULL if and only if the texture unit is
475 * not actually enabled.
476 */
477 assert( (texUnit->_ReallyEnabled == 0)
478 || (texUnit->_Current != NULL) );
479
480 if ( R200_DEBUG & DEBUG_TEXTURE ) {
481 fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, (void *)ctx, unit );
482 }
483
484 /* Set the texture environment state. Isn't this nice and clean?
485 * The chip will automagically set the texture alpha to 0xff when
486 * the texture format does not include an alpha component. This
487 * reduces the amount of special-casing we have to do, alpha-only
488 * textures being a notable exception.
489 */
490 /* Don't cache these results.
491 */
492 rmesa->state.texture.unit[unit].format = 0;
493 rmesa->state.texture.unit[unit].envMode = 0;
494
495 if ( !texUnit->_ReallyEnabled ) {
496 if ( unit == 0 ) {
497 color_combine = R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO
498 | R200_TXC_ARG_C_DIFFUSE_COLOR | R200_TXC_OP_MADD;
499 alpha_combine = R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO
500 | R200_TXA_ARG_C_DIFFUSE_ALPHA | R200_TXA_OP_MADD;
501 }
502 else {
503 color_combine = R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO
504 | R200_TXC_ARG_C_R0_COLOR | R200_TXC_OP_MADD;
505 alpha_combine = R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO
506 | R200_TXA_ARG_C_R0_ALPHA | R200_TXA_OP_MADD;
507 }
508 }
509 else {
510 GLuint color_arg[3], alpha_arg[3];
511 GLuint i;
512 const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
513 const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
514 GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB;
515 GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA;
516
517
518 /* Step 1:
519 * Extract the color and alpha combine function arguments.
520 */
521 for ( i = 0 ; i < numColorArgs ; i++ ) {
522 const GLint op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR;
523 assert(op >= 0);
524 assert(op <= 3);
525 switch ( texUnit->_CurrentCombine->SourceRGB[i] ) {
526 case GL_TEXTURE:
527 color_arg[i] = r200_register_color[op][unit];
528 break;
529 case GL_CONSTANT:
530 color_arg[i] = r200_tfactor_color[op];
531 break;
532 case GL_PRIMARY_COLOR:
533 color_arg[i] = r200_primary_color[op];
534 break;
535 case GL_PREVIOUS:
536 if (unit == 0)
537 color_arg[i] = r200_primary_color[op];
538 else
539 color_arg[i] = r200_register_color[op][0];
540 break;
541 case GL_ZERO:
542 color_arg[i] = r200_zero_color[op];
543 break;
544 case GL_ONE:
545 color_arg[i] = r200_zero_color[op+1];
546 break;
547 default:
548 return GL_FALSE;
549 }
550 }
551
552 for ( i = 0 ; i < numAlphaArgs ; i++ ) {
553 const GLint op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA;
554 assert(op >= 0);
555 assert(op <= 1);
556 switch ( texUnit->_CurrentCombine->SourceA[i] ) {
557 case GL_TEXTURE:
558 alpha_arg[i] = r200_register_alpha[op][unit];
559 break;
560 case GL_CONSTANT:
561 alpha_arg[i] = r200_tfactor_alpha[op];
562 break;
563 case GL_PRIMARY_COLOR:
564 alpha_arg[i] = r200_primary_alpha[op];
565 break;
566 case GL_PREVIOUS:
567 if (unit == 0)
568 alpha_arg[i] = r200_primary_alpha[op];
569 else
570 alpha_arg[i] = r200_register_alpha[op][0];
571 break;
572 case GL_ZERO:
573 alpha_arg[i] = r200_zero_alpha[op];
574 break;
575 case GL_ONE:
576 alpha_arg[i] = r200_zero_alpha[op+1];
577 break;
578 default:
579 return GL_FALSE;
580 }
581 }
582
583 /* Step 2:
584 * Build up the color and alpha combine functions.
585 */
586 switch ( texUnit->_CurrentCombine->ModeRGB ) {
587 case GL_REPLACE:
588 color_combine = (R200_TXC_ARG_A_ZERO |
589 R200_TXC_ARG_B_ZERO |
590 R200_TXC_OP_MADD);
591 R200_COLOR_ARG( 0, C );
592 break;
593 case GL_MODULATE:
594 color_combine = (R200_TXC_ARG_C_ZERO |
595 R200_TXC_OP_MADD);
596 R200_COLOR_ARG( 0, A );
597 R200_COLOR_ARG( 1, B );
598 break;
599 case GL_ADD:
600 color_combine = (R200_TXC_ARG_B_ZERO |
601 R200_TXC_COMP_ARG_B |
602 R200_TXC_OP_MADD);
603 R200_COLOR_ARG( 0, A );
604 R200_COLOR_ARG( 1, C );
605 break;
606 case GL_ADD_SIGNED:
607 color_combine = (R200_TXC_ARG_B_ZERO |
608 R200_TXC_COMP_ARG_B |
609 R200_TXC_BIAS_ARG_C | /* new */
610 R200_TXC_OP_MADD); /* was ADDSIGNED */
611 R200_COLOR_ARG( 0, A );
612 R200_COLOR_ARG( 1, C );
613 break;
614 case GL_SUBTRACT:
615 color_combine = (R200_TXC_ARG_B_ZERO |
616 R200_TXC_COMP_ARG_B |
617 R200_TXC_NEG_ARG_C |
618 R200_TXC_OP_MADD);
619 R200_COLOR_ARG( 0, A );
620 R200_COLOR_ARG( 1, C );
621 break;
622 case GL_INTERPOLATE:
623 color_combine = (R200_TXC_OP_LERP);
624 R200_COLOR_ARG( 0, B );
625 R200_COLOR_ARG( 1, A );
626 R200_COLOR_ARG( 2, C );
627 break;
628
629 case GL_DOT3_RGB_EXT:
630 case GL_DOT3_RGBA_EXT:
631 /* The EXT version of the DOT3 extension does not support the
632 * scale factor, but the ARB version (and the version in OpenGL
633 * 1.3) does.
634 */
635 RGBshift = 0;
636 /* FALLTHROUGH */
637
638 case GL_DOT3_RGB:
639 case GL_DOT3_RGBA:
640 /* DOT3 works differently on R200 than on R100. On R100, just
641 * setting the DOT3 mode did everything for you. On R200, the
642 * driver has to enable the biasing and scale in the inputs to
643 * put them in the proper [-1,1] range. This is what the 4x and
644 * the -0.5 in the DOT3 spec do. The post-scale is then set
645 * normally.
646 */
647
648 color_combine = (R200_TXC_ARG_C_ZERO |
649 R200_TXC_OP_DOT3 |
650 R200_TXC_BIAS_ARG_A |
651 R200_TXC_BIAS_ARG_B |
652 R200_TXC_SCALE_ARG_A |
653 R200_TXC_SCALE_ARG_B);
654 R200_COLOR_ARG( 0, A );
655 R200_COLOR_ARG( 1, B );
656 break;
657
658 case GL_MODULATE_ADD_ATI:
659 color_combine = (R200_TXC_OP_MADD);
660 R200_COLOR_ARG( 0, A );
661 R200_COLOR_ARG( 1, C );
662 R200_COLOR_ARG( 2, B );
663 break;
664 case GL_MODULATE_SIGNED_ADD_ATI:
665 color_combine = (R200_TXC_BIAS_ARG_C | /* new */
666 R200_TXC_OP_MADD); /* was ADDSIGNED */
667 R200_COLOR_ARG( 0, A );
668 R200_COLOR_ARG( 1, C );
669 R200_COLOR_ARG( 2, B );
670 break;
671 case GL_MODULATE_SUBTRACT_ATI:
672 color_combine = (R200_TXC_NEG_ARG_C |
673 R200_TXC_OP_MADD);
674 R200_COLOR_ARG( 0, A );
675 R200_COLOR_ARG( 1, C );
676 R200_COLOR_ARG( 2, B );
677 break;
678 default:
679 return GL_FALSE;
680 }
681
682 switch ( texUnit->_CurrentCombine->ModeA ) {
683 case GL_REPLACE:
684 alpha_combine = (R200_TXA_ARG_A_ZERO |
685 R200_TXA_ARG_B_ZERO |
686 R200_TXA_OP_MADD);
687 R200_ALPHA_ARG( 0, C );
688 break;
689 case GL_MODULATE:
690 alpha_combine = (R200_TXA_ARG_C_ZERO |
691 R200_TXA_OP_MADD);
692 R200_ALPHA_ARG( 0, A );
693 R200_ALPHA_ARG( 1, B );
694 break;
695 case GL_ADD:
696 alpha_combine = (R200_TXA_ARG_B_ZERO |
697 R200_TXA_COMP_ARG_B |
698 R200_TXA_OP_MADD);
699 R200_ALPHA_ARG( 0, A );
700 R200_ALPHA_ARG( 1, C );
701 break;
702 case GL_ADD_SIGNED:
703 alpha_combine = (R200_TXA_ARG_B_ZERO |
704 R200_TXA_COMP_ARG_B |
705 R200_TXA_BIAS_ARG_C | /* new */
706 R200_TXA_OP_MADD); /* was ADDSIGNED */
707 R200_ALPHA_ARG( 0, A );
708 R200_ALPHA_ARG( 1, C );
709 break;
710 case GL_SUBTRACT:
711 alpha_combine = (R200_TXA_ARG_B_ZERO |
712 R200_TXA_COMP_ARG_B |
713 R200_TXA_NEG_ARG_C |
714 R200_TXA_OP_MADD);
715 R200_ALPHA_ARG( 0, A );
716 R200_ALPHA_ARG( 1, C );
717 break;
718 case GL_INTERPOLATE:
719 alpha_combine = (R200_TXA_OP_LERP);
720 R200_ALPHA_ARG( 0, B );
721 R200_ALPHA_ARG( 1, A );
722 R200_ALPHA_ARG( 2, C );
723 break;
724
725 case GL_MODULATE_ADD_ATI:
726 alpha_combine = (R200_TXA_OP_MADD);
727 R200_ALPHA_ARG( 0, A );
728 R200_ALPHA_ARG( 1, C );
729 R200_ALPHA_ARG( 2, B );
730 break;
731 case GL_MODULATE_SIGNED_ADD_ATI:
732 alpha_combine = (R200_TXA_BIAS_ARG_C | /* new */
733 R200_TXA_OP_MADD); /* was ADDSIGNED */
734 R200_ALPHA_ARG( 0, A );
735 R200_ALPHA_ARG( 1, C );
736 R200_ALPHA_ARG( 2, B );
737 break;
738 case GL_MODULATE_SUBTRACT_ATI:
739 alpha_combine = (R200_TXA_NEG_ARG_C |
740 R200_TXA_OP_MADD);
741 R200_ALPHA_ARG( 0, A );
742 R200_ALPHA_ARG( 1, C );
743 R200_ALPHA_ARG( 2, B );
744 break;
745 default:
746 return GL_FALSE;
747 }
748
749 if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT)
750 || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ) {
751 alpha_scale |= R200_TXA_DOT_ALPHA;
752 Ashift = RGBshift;
753 }
754
755 /* Step 3:
756 * Apply the scale factor.
757 */
758 color_scale |= (RGBshift << R200_TXC_SCALE_SHIFT);
759 alpha_scale |= (Ashift << R200_TXA_SCALE_SHIFT);
760
761 /* All done!
762 */
763 }
764
765 if ( rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND] != color_combine ||
766 rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND] != alpha_combine ||
767 rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND2] != color_scale ||
768 rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND2] != alpha_scale) {
769 R200_STATECHANGE( rmesa, pix[unit] );
770 rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND] = color_combine;
771 rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND] = alpha_combine;
772 rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND2] = color_scale;
773 rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND2] = alpha_scale;
774 }
775
776 return GL_TRUE;
777 }
778
779 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
780 R200_MIN_FILTER_MASK | \
781 R200_MAG_FILTER_MASK | \
782 R200_MAX_ANISO_MASK | \
783 R200_YUV_TO_RGB | \
784 R200_YUV_TEMPERATURE_MASK | \
785 R200_CLAMP_S_MASK | \
786 R200_CLAMP_T_MASK | \
787 R200_BORDER_MODE_D3D )
788
789 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
790 R200_TXFORMAT_HEIGHT_MASK | \
791 R200_TXFORMAT_FORMAT_MASK | \
792 R200_TXFORMAT_F5_WIDTH_MASK | \
793 R200_TXFORMAT_F5_HEIGHT_MASK | \
794 R200_TXFORMAT_ALPHA_IN_MAP | \
795 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
796 R200_TXFORMAT_NON_POWER2)
797
798 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
799 R200_TEXCOORD_MASK | \
800 R200_CLAMP_Q_MASK | \
801 R200_VOLUME_FILTER_MASK)
802
803
804 static void import_tex_obj_state( r200ContextPtr rmesa,
805 int unit,
806 r200TexObjPtr texobj )
807 {
808 GLuint *cmd = R200_DB_STATE( tex[unit] );
809
810 cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
811 cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK;
812 cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
813 cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
814 cmd[TEX_PP_TXFORMAT_X] &= ~TEXOBJ_TXFORMAT_X_MASK;
815 cmd[TEX_PP_TXFORMAT_X] |= texobj->pp_txformat_x & TEXOBJ_TXFORMAT_X_MASK;
816 cmd[TEX_PP_TXSIZE] = texobj->pp_txsize; /* NPOT only! */
817 cmd[TEX_PP_TXPITCH] = texobj->pp_txpitch; /* NPOT only! */
818 cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset;
819 cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
820 R200_DB_STATECHANGE( rmesa, &rmesa->hw.tex[unit] );
821
822 if (texobj->base.tObj->Target == GL_TEXTURE_CUBE_MAP) {
823 GLuint *cube_cmd = R200_DB_STATE( cube[unit] );
824 GLuint bytesPerFace = texobj->base.totalSize / 6;
825 ASSERT(texobj->totalSize % 6 == 0);
826 cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
827 cube_cmd[CUBE_PP_CUBIC_OFFSET_F1] = texobj->pp_txoffset + 1 * bytesPerFace;
828 cube_cmd[CUBE_PP_CUBIC_OFFSET_F2] = texobj->pp_txoffset + 2 * bytesPerFace;
829 cube_cmd[CUBE_PP_CUBIC_OFFSET_F3] = texobj->pp_txoffset + 3 * bytesPerFace;
830 cube_cmd[CUBE_PP_CUBIC_OFFSET_F4] = texobj->pp_txoffset + 4 * bytesPerFace;
831 cube_cmd[CUBE_PP_CUBIC_OFFSET_F5] = texobj->pp_txoffset + 5 * bytesPerFace;
832 R200_DB_STATECHANGE( rmesa, &rmesa->hw.cube[unit] );
833 }
834
835 texobj->dirty_state &= ~(1<<unit);
836 }
837
838
839
840
841 static void set_texgen_matrix( r200ContextPtr rmesa,
842 GLuint unit,
843 const GLfloat *s_plane,
844 const GLfloat *t_plane,
845 const GLfloat *r_plane )
846 {
847 static const GLfloat scale_identity[4] = { 1,1,1,1 };
848
849 if (!TEST_EQ_4V( s_plane, scale_identity) ||
850 !TEST_EQ_4V( t_plane, scale_identity) ||
851 !TEST_EQ_4V( r_plane, scale_identity)) {
852 rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit;
853 rmesa->TexGenMatrix[unit].m[0] = s_plane[0];
854 rmesa->TexGenMatrix[unit].m[4] = s_plane[1];
855 rmesa->TexGenMatrix[unit].m[8] = s_plane[2];
856 rmesa->TexGenMatrix[unit].m[12] = s_plane[3];
857
858 rmesa->TexGenMatrix[unit].m[1] = t_plane[0];
859 rmesa->TexGenMatrix[unit].m[5] = t_plane[1];
860 rmesa->TexGenMatrix[unit].m[9] = t_plane[2];
861 rmesa->TexGenMatrix[unit].m[13] = t_plane[3];
862
863 /* NOTE: r_plane goes in the 4th row, not 3rd! */
864 rmesa->TexGenMatrix[unit].m[3] = r_plane[0];
865 rmesa->TexGenMatrix[unit].m[7] = r_plane[1];
866 rmesa->TexGenMatrix[unit].m[11] = r_plane[2];
867 rmesa->TexGenMatrix[unit].m[15] = r_plane[3];
868
869 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
870 }
871 }
872
873 /* Need this special matrix to get correct reflection map coords */
874 static void
875 set_texgen_reflection_matrix( r200ContextPtr rmesa, GLuint unit )
876 {
877 static const GLfloat m[16] = {
878 -1, 0, 0, 0,
879 0, -1, 0, 0,
880 0, 0, 0, -1,
881 0, 0, -1, 0 };
882 _math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m);
883 _math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) );
884 rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit;
885 }
886
887 /* Need this special matrix to get correct normal map coords */
888 static void
889 set_texgen_normal_map_matrix( r200ContextPtr rmesa, GLuint unit )
890 {
891 static const GLfloat m[16] = {
892 1, 0, 0, 0,
893 0, 1, 0, 0,
894 0, 0, 0, 1,
895 0, 0, 1, 0 };
896 _math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m);
897 _math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) );
898 rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit;
899 }
900
901
902 /* Ignoring the Q texcoord for now.
903 *
904 * Returns GL_FALSE if fallback required.
905 */
906 static GLboolean r200_validate_texgen( GLcontext *ctx, GLuint unit )
907 {
908 r200ContextPtr rmesa = R200_CONTEXT(ctx);
909 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
910 GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit*4;
911 GLuint tmp = rmesa->TexGenEnabled;
912
913 rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
914 rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
915 rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
916 rmesa->TexGenInputs &= ~(R200_TEXGEN_INPUT_MASK<<inputshift);
917 rmesa->TexGenNeedNormals[unit] = 0;
918
919 if (0)
920 fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit);
921
922 if ((texUnit->TexGenEnabled & (S_BIT|T_BIT|R_BIT)) == 0) {
923 /* Disabled, no fallback:
924 */
925 rmesa->TexGenInputs |=
926 (R200_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
927 return GL_TRUE;
928 }
929 else if (texUnit->TexGenEnabled & Q_BIT) {
930 /* Very easy to do this, in fact would remove a fallback case
931 * elsewhere, but I haven't done it yet... Fallback:
932 */
933 /*fprintf(stderr, "fallback Q_BIT\n");*/
934 return GL_FALSE;
935 }
936 else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) &&
937 texUnit->GenModeS == texUnit->GenModeT) {
938 /* OK */
939 rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit;
940 /* continue */
941 }
942 else if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT) &&
943 texUnit->GenModeS == texUnit->GenModeT &&
944 texUnit->GenModeT == texUnit->GenModeR) {
945 /* OK */
946 rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit;
947 /* continue */
948 }
949 else {
950 /* Mixed modes, fallback:
951 */
952 /* fprintf(stderr, "fallback mixed texgen\n"); */
953 return GL_FALSE;
954 }
955
956 rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit;
957
958 switch (texUnit->GenModeS) {
959 case GL_OBJECT_LINEAR:
960 rmesa->TexGenInputs |= R200_TEXGEN_INPUT_OBJ << inputshift;
961 set_texgen_matrix( rmesa, unit,
962 texUnit->ObjectPlaneS,
963 texUnit->ObjectPlaneT,
964 texUnit->ObjectPlaneR);
965 break;
966
967 case GL_EYE_LINEAR:
968 rmesa->TexGenInputs |= R200_TEXGEN_INPUT_EYE << inputshift;
969 set_texgen_matrix( rmesa, unit,
970 texUnit->EyePlaneS,
971 texUnit->EyePlaneT,
972 texUnit->EyePlaneR);
973 break;
974
975 case GL_REFLECTION_MAP_NV:
976 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
977 rmesa->TexGenInputs |= R200_TEXGEN_INPUT_EYE_REFLECT<<inputshift;
978 set_texgen_reflection_matrix(rmesa, unit);
979 break;
980
981 case GL_NORMAL_MAP_NV:
982 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
983 rmesa->TexGenInputs |= R200_TEXGEN_INPUT_EYE_NORMAL<<inputshift;
984 set_texgen_normal_map_matrix(rmesa, unit);
985 break;
986
987 case GL_SPHERE_MAP:
988 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
989 rmesa->TexGenInputs |= R200_TEXGEN_INPUT_SPHERE<<inputshift;
990 break;
991
992 default:
993 /* Unsupported mode, fallback:
994 */
995 /* fprintf(stderr, "fallback unsupported texgen\n"); */
996 return GL_FALSE;
997 }
998
999 rmesa->TexGenCompSel |= R200_OUTPUT_TEX_0 << unit;
1000
1001 if (tmp != rmesa->TexGenEnabled) {
1002 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1003 }
1004
1005 return GL_TRUE;
1006 }
1007
1008
1009 static void disable_tex( GLcontext *ctx, int unit )
1010 {
1011 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1012
1013 if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE<<unit)) {
1014 /* Texture unit disabled */
1015 if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
1016 /* The old texture is no longer bound to this texture unit.
1017 * Mark it as such.
1018 */
1019
1020 rmesa->state.texture.unit[unit].texobj->base.bound &= ~(1UL << unit);
1021 rmesa->state.texture.unit[unit].texobj = NULL;
1022 }
1023
1024 R200_STATECHANGE( rmesa, ctx );
1025 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~((R200_TEX_0_ENABLE |
1026 R200_TEX_BLEND_0_ENABLE) << unit);
1027 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_BLEND_0_ENABLE;
1028
1029 R200_STATECHANGE( rmesa, vtx );
1030 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
1031
1032 if (rmesa->TclFallback & (R200_TCL_FALLBACK_TEXGEN_0<<unit)) {
1033 TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
1034 }
1035
1036 /* Actually want to keep all units less than max active texture
1037 * enabled, right? Fix this for >2 texunits.
1038 */
1039 /* FIXME: What should happen here if r200UpdateTextureEnv fails? */
1040 if (unit == 0)
1041 r200UpdateTextureEnv( ctx, unit );
1042
1043
1044 {
1045 GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit*4;
1046 GLuint tmp = rmesa->TexGenEnabled;
1047
1048 rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
1049 rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
1050 rmesa->TexGenEnabled &= ~(R200_TEXGEN_INPUT_MASK<<inputshift);
1051 rmesa->TexGenNeedNormals[unit] = 0;
1052 rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
1053 rmesa->TexGenInputs &= ~(R200_TEXGEN_INPUT_MASK<<inputshift);
1054
1055 if (tmp != rmesa->TexGenEnabled) {
1056 rmesa->recheck_texgen[unit] = GL_TRUE;
1057 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1058 }
1059 }
1060 }
1061 }
1062
1063 static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
1064 {
1065 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1066 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1067 struct gl_texture_object *tObj = texUnit->_Current;
1068 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1069
1070 /* Need to load the 2d images associated with this unit.
1071 */
1072 if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
1073 t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
1074 t->base.dirty_images[0] = ~0;
1075 }
1076
1077 ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
1078
1079 if ( t->base.dirty_images[0] ) {
1080 R200_FIREVERTICES( rmesa );
1081 r200SetTexImages( rmesa, tObj );
1082 r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
1083 if ( !t->base.memBlock )
1084 return GL_FALSE;
1085 }
1086
1087 return GL_TRUE;
1088 }
1089
1090 #if ENABLE_HW_3D_TEXTURE
1091 static GLboolean enable_tex_3d( GLcontext *ctx, int unit )
1092 {
1093 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1094 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1095 struct gl_texture_object *tObj = texUnit->_Current;
1096 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1097
1098 /* Need to load the 3d images associated with this unit.
1099 */
1100 if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
1101 t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
1102 t->base.dirty_images[0] = ~0;
1103 }
1104
1105 ASSERT(tObj->Target == GL_TEXTURE_3D);
1106
1107 /* R100 & R200 do not support mipmaps for 3D textures.
1108 */
1109 if ( (tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR) ) {
1110 return GL_FALSE;
1111 }
1112
1113 if ( t->base.dirty_images[0] ) {
1114 R200_FIREVERTICES( rmesa );
1115 r200SetTexImages( rmesa, tObj );
1116 r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
1117 if ( !t->base.memBlock )
1118 return GL_FALSE;
1119 }
1120
1121 return GL_TRUE;
1122 }
1123 #endif
1124
1125 static GLboolean enable_tex_cube( GLcontext *ctx, int unit )
1126 {
1127 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1128 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1129 struct gl_texture_object *tObj = texUnit->_Current;
1130 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1131 GLuint face;
1132
1133 /* Need to load the 2d images associated with this unit.
1134 */
1135 if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
1136 t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
1137 for (face = 0; face < 6; face++)
1138 t->base.dirty_images[face] = ~0;
1139 }
1140
1141 ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP);
1142
1143 if ( t->base.dirty_images[0] || t->base.dirty_images[1] ||
1144 t->base.dirty_images[2] || t->base.dirty_images[3] ||
1145 t->base.dirty_images[4] || t->base.dirty_images[5] ) {
1146 /* flush */
1147 R200_FIREVERTICES( rmesa );
1148 /* layout memory space, once for all faces */
1149 r200SetTexImages( rmesa, tObj );
1150 }
1151
1152 /* upload (per face) */
1153 for (face = 0; face < 6; face++) {
1154 if (t->base.dirty_images[face]) {
1155 r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, face );
1156 }
1157 }
1158
1159 if ( !t->base.memBlock ) {
1160 /* texmem alloc failed, use s/w fallback */
1161 return GL_FALSE;
1162 }
1163
1164 return GL_TRUE;
1165 }
1166
1167 static GLboolean enable_tex_rect( GLcontext *ctx, int unit )
1168 {
1169 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1170 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1171 struct gl_texture_object *tObj = texUnit->_Current;
1172 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1173
1174 if (!(t->pp_txformat & R200_TXFORMAT_NON_POWER2)) {
1175 t->pp_txformat |= R200_TXFORMAT_NON_POWER2;
1176 t->base.dirty_images[0] = ~0;
1177 }
1178
1179 ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
1180
1181 if ( t->base.dirty_images[0] ) {
1182 R200_FIREVERTICES( rmesa );
1183 r200SetTexImages( rmesa, tObj );
1184 r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
1185 if ( !t->base.memBlock && !rmesa->prefer_gart_client_texturing )
1186 return GL_FALSE;
1187 }
1188
1189 return GL_TRUE;
1190 }
1191
1192
1193 static GLboolean update_tex_common( GLcontext *ctx, int unit )
1194 {
1195 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1196 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1197 struct gl_texture_object *tObj = texUnit->_Current;
1198 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1199 GLenum format;
1200
1201 /* Fallback if there's a texture border */
1202 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 )
1203 return GL_FALSE;
1204
1205 /* Update state if this is a different texture object to last
1206 * time.
1207 */
1208 if ( rmesa->state.texture.unit[unit].texobj != t ) {
1209 if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
1210 /* The old texture is no longer bound to this texture unit.
1211 * Mark it as such.
1212 */
1213
1214 rmesa->state.texture.unit[unit].texobj->base.bound &=
1215 ~(1UL << unit);
1216 }
1217
1218 rmesa->state.texture.unit[unit].texobj = t;
1219 t->base.bound |= (1UL << unit);
1220 t->dirty_state |= 1<<unit;
1221 driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
1222 }
1223
1224
1225 /* Newly enabled?
1226 */
1227 if ( 1|| !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE<<unit))) {
1228 R200_STATECHANGE( rmesa, ctx );
1229 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_0_ENABLE |
1230 R200_TEX_BLEND_0_ENABLE) << unit;
1231
1232 R200_STATECHANGE( rmesa, vtx );
1233 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] |= 4 << (unit * 3);
1234
1235 rmesa->recheck_texgen[unit] = GL_TRUE;
1236 }
1237
1238 if (t->dirty_state & (1<<unit)) {
1239 import_tex_obj_state( rmesa, unit, t );
1240 }
1241
1242 if (rmesa->recheck_texgen[unit]) {
1243 GLboolean fallback = !r200_validate_texgen( ctx, unit );
1244 TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
1245 rmesa->recheck_texgen[unit] = 0;
1246 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1247 }
1248
1249 format = tObj->Image[0][tObj->BaseLevel]->Format;
1250 if ( rmesa->state.texture.unit[unit].format != format ||
1251 rmesa->state.texture.unit[unit].envMode != texUnit->EnvMode ) {
1252 rmesa->state.texture.unit[unit].format = format;
1253 rmesa->state.texture.unit[unit].envMode = texUnit->EnvMode;
1254 if ( ! r200UpdateTextureEnv( ctx, unit ) ) {
1255 return GL_FALSE;
1256 }
1257 }
1258
1259 FALLBACK( rmesa, R200_FALLBACK_BORDER_MODE, t->border_fallback );
1260 return !t->border_fallback;
1261 }
1262
1263
1264
1265 static GLboolean r200UpdateTextureUnit( GLcontext *ctx, int unit )
1266 {
1267 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1268
1269 if ( texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT) ) {
1270 return (enable_tex_rect( ctx, unit ) &&
1271 update_tex_common( ctx, unit ));
1272 }
1273 else if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
1274 return (enable_tex_2d( ctx, unit ) &&
1275 update_tex_common( ctx, unit ));
1276 }
1277 #if ENABLE_HW_3D_TEXTURE
1278 else if ( texUnit->_ReallyEnabled & (TEXTURE_3D_BIT) ) {
1279 return (enable_tex_3d( ctx, unit ) &&
1280 update_tex_common( ctx, unit ));
1281 }
1282 #endif
1283 else if ( texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT) ) {
1284 return (enable_tex_cube( ctx, unit ) &&
1285 update_tex_common( ctx, unit ));
1286 }
1287 else if ( texUnit->_ReallyEnabled ) {
1288 return GL_FALSE;
1289 }
1290 else {
1291 disable_tex( ctx, unit );
1292 return GL_TRUE;
1293 }
1294 }
1295
1296
1297 void r200UpdateTextureState( GLcontext *ctx )
1298 {
1299 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1300 GLboolean ok;
1301 GLuint dbg;
1302
1303 ok = (r200UpdateTextureUnit( ctx, 0 ) &&
1304 r200UpdateTextureUnit( ctx, 1 ) &&
1305 r200UpdateTextureUnit( ctx, 2 ) &&
1306 r200UpdateTextureUnit( ctx, 3 ) &&
1307 r200UpdateTextureUnit( ctx, 4 ) &&
1308 r200UpdateTextureUnit( ctx, 5 ));
1309
1310 FALLBACK( rmesa, R200_FALLBACK_TEXTURE, !ok );
1311
1312 if (rmesa->TclFallback)
1313 r200ChooseVertexState( ctx );
1314
1315
1316 if (rmesa->r200Screen->chipset & R200_CHIPSET_REAL_R200) {
1317
1318 /*
1319 * T0 hang workaround -------------
1320 * not needed for r200 derivatives?
1321 */
1322 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_ENABLE_MASK) == R200_TEX_0_ENABLE &&
1323 (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) {
1324
1325 R200_STATECHANGE(rmesa, ctx);
1326 R200_STATECHANGE(rmesa, tex[1]);
1327 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_1_ENABLE;
1328 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1329 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1330 }
1331 else {
1332 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE) &&
1333 (rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1334 R200_STATECHANGE(rmesa, tex[1]);
1335 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1336 }
1337 }
1338
1339 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1340 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1341 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1342 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1343 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1344 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1345 R200_MIN_FILTER_LINEAR)) {
1346 R200_STATECHANGE(rmesa, ctx);
1347 R200_STATECHANGE(rmesa, tex[i+1]);
1348 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1349 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1350 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1351 }
1352 else {
1353 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1354 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1355 R200_STATECHANGE(rmesa, tex[i+1]);
1356 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1357 }
1358 }
1359 } */
1360
1361 /*
1362 * Texture cache LRU hang workaround -------------
1363 * not needed for r200 derivatives?
1364 */
1365 dbg = 0x0;
1366
1367 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) &&
1368 ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1369 0x04) == 0)) ||
1370 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1371 ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1372 0x04) == 0)) ||
1373 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1374 ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1375 0x04) == 0)))
1376 {
1377 dbg |= 0x02;
1378 }
1379
1380 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) &&
1381 ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1382 0x04) == 0)) ||
1383 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1384 ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1385 0x04) == 0)) ||
1386 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1387 ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1388 0x04) == 0)))
1389 {
1390 dbg |= 0x04;
1391 }
1392
1393 if (dbg != rmesa->hw.tam.cmd[TAM_DEBUG3]) {
1394 R200_STATECHANGE( rmesa, tam );
1395 rmesa->hw.tam.cmd[TAM_DEBUG3] = dbg;
1396 if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg);
1397 }
1398 }
1399 }