Fixed off by one errors in clipping.
[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 else {
297 /* If we don't in fact send enough texture coordinates, q will be 1,
298 * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
299 */
300 t->pp_txformat_x |= R200_TEXCOORD_PROJ;
301 }
302
303 t->pp_txsize = (((tObj->Image[0][t->base.firstLevel]->Width - 1) << 0) |
304 ((tObj->Image[0][t->base.firstLevel]->Height - 1) << 16));
305
306 /* Only need to round to nearest 32 for textures, but the blitter
307 * requires 64-byte aligned pitches, and we may/may not need the
308 * blitter. NPOT only!
309 */
310 if (baseImage->IsCompressed)
311 t->pp_txpitch = (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63);
312 else
313 t->pp_txpitch = ((tObj->Image[0][t->base.firstLevel]->Width * baseImage->TexFormat->TexelBytes) + 63) & ~(63);
314 t->pp_txpitch -= 32;
315
316 t->dirty_state = TEX_ALL;
317
318 /* FYI: r200UploadTexImages( rmesa, t ) used to be called here */
319 }
320
321
322
323 /* ================================================================
324 * Texture combine functions
325 */
326
327 /* GL_ARB_texture_env_combine support
328 */
329
330 /* The color tables have combine functions for GL_SRC_COLOR,
331 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
332 */
333 static GLuint r200_register_color[][R200_MAX_TEXTURE_UNITS] =
334 {
335 {
336 R200_TXC_ARG_A_R0_COLOR,
337 R200_TXC_ARG_A_R1_COLOR,
338 R200_TXC_ARG_A_R2_COLOR,
339 R200_TXC_ARG_A_R3_COLOR,
340 R200_TXC_ARG_A_R4_COLOR,
341 R200_TXC_ARG_A_R5_COLOR
342 },
343 {
344 R200_TXC_ARG_A_R0_COLOR | R200_TXC_COMP_ARG_A,
345 R200_TXC_ARG_A_R1_COLOR | R200_TXC_COMP_ARG_A,
346 R200_TXC_ARG_A_R2_COLOR | R200_TXC_COMP_ARG_A,
347 R200_TXC_ARG_A_R3_COLOR | R200_TXC_COMP_ARG_A,
348 R200_TXC_ARG_A_R4_COLOR | R200_TXC_COMP_ARG_A,
349 R200_TXC_ARG_A_R5_COLOR | R200_TXC_COMP_ARG_A
350 },
351 {
352 R200_TXC_ARG_A_R0_ALPHA,
353 R200_TXC_ARG_A_R1_ALPHA,
354 R200_TXC_ARG_A_R2_ALPHA,
355 R200_TXC_ARG_A_R3_ALPHA,
356 R200_TXC_ARG_A_R4_ALPHA,
357 R200_TXC_ARG_A_R5_ALPHA
358 },
359 {
360 R200_TXC_ARG_A_R0_ALPHA | R200_TXC_COMP_ARG_A,
361 R200_TXC_ARG_A_R1_ALPHA | R200_TXC_COMP_ARG_A,
362 R200_TXC_ARG_A_R2_ALPHA | R200_TXC_COMP_ARG_A,
363 R200_TXC_ARG_A_R3_ALPHA | R200_TXC_COMP_ARG_A,
364 R200_TXC_ARG_A_R4_ALPHA | R200_TXC_COMP_ARG_A,
365 R200_TXC_ARG_A_R5_ALPHA | R200_TXC_COMP_ARG_A
366 },
367 };
368
369 static GLuint r200_tfactor_color[] =
370 {
371 R200_TXC_ARG_A_TFACTOR_COLOR,
372 R200_TXC_ARG_A_TFACTOR_COLOR | R200_TXC_COMP_ARG_A,
373 R200_TXC_ARG_A_TFACTOR_ALPHA,
374 R200_TXC_ARG_A_TFACTOR_ALPHA | R200_TXC_COMP_ARG_A
375 };
376
377 static GLuint r200_primary_color[] =
378 {
379 R200_TXC_ARG_A_DIFFUSE_COLOR,
380 R200_TXC_ARG_A_DIFFUSE_COLOR | R200_TXC_COMP_ARG_A,
381 R200_TXC_ARG_A_DIFFUSE_ALPHA,
382 R200_TXC_ARG_A_DIFFUSE_ALPHA | R200_TXC_COMP_ARG_A
383 };
384
385 /* GL_ZERO table - indices 0-3
386 * GL_ONE table - indices 1-4
387 */
388 static GLuint r200_zero_color[] =
389 {
390 R200_TXC_ARG_A_ZERO,
391 R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A,
392 R200_TXC_ARG_A_ZERO,
393 R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A,
394 R200_TXC_ARG_A_ZERO
395 };
396
397 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
398 */
399 static GLuint r200_register_alpha[][R200_MAX_TEXTURE_UNITS] =
400 {
401 {
402 R200_TXA_ARG_A_R0_ALPHA,
403 R200_TXA_ARG_A_R1_ALPHA,
404 R200_TXA_ARG_A_R2_ALPHA,
405 R200_TXA_ARG_A_R3_ALPHA,
406 R200_TXA_ARG_A_R4_ALPHA,
407 R200_TXA_ARG_A_R5_ALPHA
408 },
409 {
410 R200_TXA_ARG_A_R0_ALPHA | R200_TXA_COMP_ARG_A,
411 R200_TXA_ARG_A_R1_ALPHA | R200_TXA_COMP_ARG_A,
412 R200_TXA_ARG_A_R2_ALPHA | R200_TXA_COMP_ARG_A,
413 R200_TXA_ARG_A_R3_ALPHA | R200_TXA_COMP_ARG_A,
414 R200_TXA_ARG_A_R4_ALPHA | R200_TXA_COMP_ARG_A,
415 R200_TXA_ARG_A_R5_ALPHA | R200_TXA_COMP_ARG_A
416 },
417 };
418
419 static GLuint r200_tfactor_alpha[] =
420 {
421 R200_TXA_ARG_A_TFACTOR_ALPHA,
422 R200_TXA_ARG_A_TFACTOR_ALPHA | R200_TXA_COMP_ARG_A
423 };
424
425 static GLuint r200_primary_alpha[] =
426 {
427 R200_TXA_ARG_A_DIFFUSE_ALPHA,
428 R200_TXA_ARG_A_DIFFUSE_ALPHA | R200_TXA_COMP_ARG_A
429 };
430
431 /* GL_ZERO table - indices 0-1
432 * GL_ONE table - indices 1-2
433 */
434 static GLuint r200_zero_alpha[] =
435 {
436 R200_TXA_ARG_A_ZERO,
437 R200_TXA_ARG_A_ZERO | R200_TXA_COMP_ARG_A,
438 R200_TXA_ARG_A_ZERO,
439 };
440
441
442 /* Extract the arg from slot A, shift it into the correct argument slot
443 * and set the corresponding complement bit.
444 */
445 #define R200_COLOR_ARG( n, arg ) \
446 do { \
447 color_combine |= \
448 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
449 << R200_TXC_ARG_##arg##_SHIFT); \
450 color_combine |= \
451 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
452 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
453 } while (0)
454
455 #define R200_ALPHA_ARG( n, arg ) \
456 do { \
457 alpha_combine |= \
458 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
459 << R200_TXA_ARG_##arg##_SHIFT); \
460 alpha_combine |= \
461 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
462 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
463 } while (0)
464
465
466 /* ================================================================
467 * Texture unit state management
468 */
469
470 static GLboolean r200UpdateTextureEnv( GLcontext *ctx, int unit )
471 {
472 r200ContextPtr rmesa = R200_CONTEXT(ctx);
473 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
474 GLuint color_combine, alpha_combine;
475 GLuint color_scale = rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND2] &
476 ~(R200_TXC_SCALE_MASK);
477 GLuint alpha_scale = rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND2] &
478 ~(R200_TXA_DOT_ALPHA | R200_TXA_SCALE_MASK);
479
480 /* texUnit->_Current can be NULL if and only if the texture unit is
481 * not actually enabled.
482 */
483 assert( (texUnit->_ReallyEnabled == 0)
484 || (texUnit->_Current != NULL) );
485
486 if ( R200_DEBUG & DEBUG_TEXTURE ) {
487 fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, (void *)ctx, unit );
488 }
489
490 /* Set the texture environment state. Isn't this nice and clean?
491 * The chip will automagically set the texture alpha to 0xff when
492 * the texture format does not include an alpha component. This
493 * reduces the amount of special-casing we have to do, alpha-only
494 * textures being a notable exception.
495 */
496 /* Don't cache these results.
497 */
498 rmesa->state.texture.unit[unit].format = 0;
499 rmesa->state.texture.unit[unit].envMode = 0;
500
501 if ( !texUnit->_ReallyEnabled ) {
502 if ( unit == 0 ) {
503 color_combine = R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO
504 | R200_TXC_ARG_C_DIFFUSE_COLOR | R200_TXC_OP_MADD;
505 alpha_combine = R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO
506 | R200_TXA_ARG_C_DIFFUSE_ALPHA | R200_TXA_OP_MADD;
507 }
508 else {
509 color_combine = R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO
510 | R200_TXC_ARG_C_R0_COLOR | R200_TXC_OP_MADD;
511 alpha_combine = R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO
512 | R200_TXA_ARG_C_R0_ALPHA | R200_TXA_OP_MADD;
513 }
514 }
515 else {
516 GLuint color_arg[3], alpha_arg[3];
517 GLuint i;
518 const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
519 const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
520 GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB;
521 GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA;
522
523
524 /* Step 1:
525 * Extract the color and alpha combine function arguments.
526 */
527 for ( i = 0 ; i < numColorArgs ; i++ ) {
528 const GLint op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR;
529 assert(op >= 0);
530 assert(op <= 3);
531 switch ( texUnit->_CurrentCombine->SourceRGB[i] ) {
532 case GL_TEXTURE:
533 color_arg[i] = r200_register_color[op][unit];
534 break;
535 case GL_CONSTANT:
536 color_arg[i] = r200_tfactor_color[op];
537 break;
538 case GL_PRIMARY_COLOR:
539 color_arg[i] = r200_primary_color[op];
540 break;
541 case GL_PREVIOUS:
542 if (unit == 0)
543 color_arg[i] = r200_primary_color[op];
544 else
545 color_arg[i] = r200_register_color[op][0];
546 break;
547 case GL_ZERO:
548 color_arg[i] = r200_zero_color[op];
549 break;
550 case GL_ONE:
551 color_arg[i] = r200_zero_color[op+1];
552 break;
553 default:
554 return GL_FALSE;
555 }
556 }
557
558 for ( i = 0 ; i < numAlphaArgs ; i++ ) {
559 const GLint op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA;
560 assert(op >= 0);
561 assert(op <= 1);
562 switch ( texUnit->_CurrentCombine->SourceA[i] ) {
563 case GL_TEXTURE:
564 alpha_arg[i] = r200_register_alpha[op][unit];
565 break;
566 case GL_CONSTANT:
567 alpha_arg[i] = r200_tfactor_alpha[op];
568 break;
569 case GL_PRIMARY_COLOR:
570 alpha_arg[i] = r200_primary_alpha[op];
571 break;
572 case GL_PREVIOUS:
573 if (unit == 0)
574 alpha_arg[i] = r200_primary_alpha[op];
575 else
576 alpha_arg[i] = r200_register_alpha[op][0];
577 break;
578 case GL_ZERO:
579 alpha_arg[i] = r200_zero_alpha[op];
580 break;
581 case GL_ONE:
582 alpha_arg[i] = r200_zero_alpha[op+1];
583 break;
584 default:
585 return GL_FALSE;
586 }
587 }
588
589 /* Step 2:
590 * Build up the color and alpha combine functions.
591 */
592 switch ( texUnit->_CurrentCombine->ModeRGB ) {
593 case GL_REPLACE:
594 color_combine = (R200_TXC_ARG_A_ZERO |
595 R200_TXC_ARG_B_ZERO |
596 R200_TXC_OP_MADD);
597 R200_COLOR_ARG( 0, C );
598 break;
599 case GL_MODULATE:
600 color_combine = (R200_TXC_ARG_C_ZERO |
601 R200_TXC_OP_MADD);
602 R200_COLOR_ARG( 0, A );
603 R200_COLOR_ARG( 1, B );
604 break;
605 case GL_ADD:
606 color_combine = (R200_TXC_ARG_B_ZERO |
607 R200_TXC_COMP_ARG_B |
608 R200_TXC_OP_MADD);
609 R200_COLOR_ARG( 0, A );
610 R200_COLOR_ARG( 1, C );
611 break;
612 case GL_ADD_SIGNED:
613 color_combine = (R200_TXC_ARG_B_ZERO |
614 R200_TXC_COMP_ARG_B |
615 R200_TXC_BIAS_ARG_C | /* new */
616 R200_TXC_OP_MADD); /* was ADDSIGNED */
617 R200_COLOR_ARG( 0, A );
618 R200_COLOR_ARG( 1, C );
619 break;
620 case GL_SUBTRACT:
621 color_combine = (R200_TXC_ARG_B_ZERO |
622 R200_TXC_COMP_ARG_B |
623 R200_TXC_NEG_ARG_C |
624 R200_TXC_OP_MADD);
625 R200_COLOR_ARG( 0, A );
626 R200_COLOR_ARG( 1, C );
627 break;
628 case GL_INTERPOLATE:
629 color_combine = (R200_TXC_OP_LERP);
630 R200_COLOR_ARG( 0, B );
631 R200_COLOR_ARG( 1, A );
632 R200_COLOR_ARG( 2, C );
633 break;
634
635 case GL_DOT3_RGB_EXT:
636 case GL_DOT3_RGBA_EXT:
637 /* The EXT version of the DOT3 extension does not support the
638 * scale factor, but the ARB version (and the version in OpenGL
639 * 1.3) does.
640 */
641 RGBshift = 0;
642 /* FALLTHROUGH */
643
644 case GL_DOT3_RGB:
645 case GL_DOT3_RGBA:
646 /* DOT3 works differently on R200 than on R100. On R100, just
647 * setting the DOT3 mode did everything for you. On R200, the
648 * driver has to enable the biasing and scale in the inputs to
649 * put them in the proper [-1,1] range. This is what the 4x and
650 * the -0.5 in the DOT3 spec do. The post-scale is then set
651 * normally.
652 */
653
654 color_combine = (R200_TXC_ARG_C_ZERO |
655 R200_TXC_OP_DOT3 |
656 R200_TXC_BIAS_ARG_A |
657 R200_TXC_BIAS_ARG_B |
658 R200_TXC_SCALE_ARG_A |
659 R200_TXC_SCALE_ARG_B);
660 R200_COLOR_ARG( 0, A );
661 R200_COLOR_ARG( 1, B );
662 break;
663
664 case GL_MODULATE_ADD_ATI:
665 color_combine = (R200_TXC_OP_MADD);
666 R200_COLOR_ARG( 0, A );
667 R200_COLOR_ARG( 1, C );
668 R200_COLOR_ARG( 2, B );
669 break;
670 case GL_MODULATE_SIGNED_ADD_ATI:
671 color_combine = (R200_TXC_BIAS_ARG_C | /* new */
672 R200_TXC_OP_MADD); /* was ADDSIGNED */
673 R200_COLOR_ARG( 0, A );
674 R200_COLOR_ARG( 1, C );
675 R200_COLOR_ARG( 2, B );
676 break;
677 case GL_MODULATE_SUBTRACT_ATI:
678 color_combine = (R200_TXC_NEG_ARG_C |
679 R200_TXC_OP_MADD);
680 R200_COLOR_ARG( 0, A );
681 R200_COLOR_ARG( 1, C );
682 R200_COLOR_ARG( 2, B );
683 break;
684 default:
685 return GL_FALSE;
686 }
687
688 switch ( texUnit->_CurrentCombine->ModeA ) {
689 case GL_REPLACE:
690 alpha_combine = (R200_TXA_ARG_A_ZERO |
691 R200_TXA_ARG_B_ZERO |
692 R200_TXA_OP_MADD);
693 R200_ALPHA_ARG( 0, C );
694 break;
695 case GL_MODULATE:
696 alpha_combine = (R200_TXA_ARG_C_ZERO |
697 R200_TXA_OP_MADD);
698 R200_ALPHA_ARG( 0, A );
699 R200_ALPHA_ARG( 1, B );
700 break;
701 case GL_ADD:
702 alpha_combine = (R200_TXA_ARG_B_ZERO |
703 R200_TXA_COMP_ARG_B |
704 R200_TXA_OP_MADD);
705 R200_ALPHA_ARG( 0, A );
706 R200_ALPHA_ARG( 1, C );
707 break;
708 case GL_ADD_SIGNED:
709 alpha_combine = (R200_TXA_ARG_B_ZERO |
710 R200_TXA_COMP_ARG_B |
711 R200_TXA_BIAS_ARG_C | /* new */
712 R200_TXA_OP_MADD); /* was ADDSIGNED */
713 R200_ALPHA_ARG( 0, A );
714 R200_ALPHA_ARG( 1, C );
715 break;
716 case GL_SUBTRACT:
717 alpha_combine = (R200_TXA_ARG_B_ZERO |
718 R200_TXA_COMP_ARG_B |
719 R200_TXA_NEG_ARG_C |
720 R200_TXA_OP_MADD);
721 R200_ALPHA_ARG( 0, A );
722 R200_ALPHA_ARG( 1, C );
723 break;
724 case GL_INTERPOLATE:
725 alpha_combine = (R200_TXA_OP_LERP);
726 R200_ALPHA_ARG( 0, B );
727 R200_ALPHA_ARG( 1, A );
728 R200_ALPHA_ARG( 2, C );
729 break;
730
731 case GL_MODULATE_ADD_ATI:
732 alpha_combine = (R200_TXA_OP_MADD);
733 R200_ALPHA_ARG( 0, A );
734 R200_ALPHA_ARG( 1, C );
735 R200_ALPHA_ARG( 2, B );
736 break;
737 case GL_MODULATE_SIGNED_ADD_ATI:
738 alpha_combine = (R200_TXA_BIAS_ARG_C | /* new */
739 R200_TXA_OP_MADD); /* was ADDSIGNED */
740 R200_ALPHA_ARG( 0, A );
741 R200_ALPHA_ARG( 1, C );
742 R200_ALPHA_ARG( 2, B );
743 break;
744 case GL_MODULATE_SUBTRACT_ATI:
745 alpha_combine = (R200_TXA_NEG_ARG_C |
746 R200_TXA_OP_MADD);
747 R200_ALPHA_ARG( 0, A );
748 R200_ALPHA_ARG( 1, C );
749 R200_ALPHA_ARG( 2, B );
750 break;
751 default:
752 return GL_FALSE;
753 }
754
755 if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT)
756 || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ) {
757 alpha_scale |= R200_TXA_DOT_ALPHA;
758 Ashift = RGBshift;
759 }
760
761 /* Step 3:
762 * Apply the scale factor.
763 */
764 color_scale |= (RGBshift << R200_TXC_SCALE_SHIFT);
765 alpha_scale |= (Ashift << R200_TXA_SCALE_SHIFT);
766
767 /* All done!
768 */
769 }
770
771 if ( rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND] != color_combine ||
772 rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND] != alpha_combine ||
773 rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND2] != color_scale ||
774 rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND2] != alpha_scale) {
775 R200_STATECHANGE( rmesa, pix[unit] );
776 rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND] = color_combine;
777 rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND] = alpha_combine;
778 rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND2] = color_scale;
779 rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND2] = alpha_scale;
780 }
781
782 return GL_TRUE;
783 }
784
785 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
786 R200_MIN_FILTER_MASK | \
787 R200_MAG_FILTER_MASK | \
788 R200_MAX_ANISO_MASK | \
789 R200_YUV_TO_RGB | \
790 R200_YUV_TEMPERATURE_MASK | \
791 R200_CLAMP_S_MASK | \
792 R200_CLAMP_T_MASK | \
793 R200_BORDER_MODE_D3D )
794
795 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
796 R200_TXFORMAT_HEIGHT_MASK | \
797 R200_TXFORMAT_FORMAT_MASK | \
798 R200_TXFORMAT_F5_WIDTH_MASK | \
799 R200_TXFORMAT_F5_HEIGHT_MASK | \
800 R200_TXFORMAT_ALPHA_IN_MAP | \
801 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
802 R200_TXFORMAT_NON_POWER2)
803
804 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
805 R200_TEXCOORD_MASK | \
806 R200_CLAMP_Q_MASK | \
807 R200_VOLUME_FILTER_MASK)
808
809
810 static void import_tex_obj_state( r200ContextPtr rmesa,
811 int unit,
812 r200TexObjPtr texobj )
813 {
814 GLuint *cmd = R200_DB_STATE( tex[unit] );
815
816 cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
817 cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK;
818 cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
819 cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
820 cmd[TEX_PP_TXFORMAT_X] &= ~TEXOBJ_TXFORMAT_X_MASK;
821 cmd[TEX_PP_TXFORMAT_X] |= texobj->pp_txformat_x & TEXOBJ_TXFORMAT_X_MASK;
822 cmd[TEX_PP_TXSIZE] = texobj->pp_txsize; /* NPOT only! */
823 cmd[TEX_PP_TXPITCH] = texobj->pp_txpitch; /* NPOT only! */
824 cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset;
825 cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
826 R200_DB_STATECHANGE( rmesa, &rmesa->hw.tex[unit] );
827
828 if (texobj->base.tObj->Target == GL_TEXTURE_CUBE_MAP) {
829 GLuint *cube_cmd = R200_DB_STATE( cube[unit] );
830 GLuint bytesPerFace = texobj->base.totalSize / 6;
831 ASSERT(texobj->totalSize % 6 == 0);
832 cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
833 cube_cmd[CUBE_PP_CUBIC_OFFSET_F1] = texobj->pp_txoffset + 1 * bytesPerFace;
834 cube_cmd[CUBE_PP_CUBIC_OFFSET_F2] = texobj->pp_txoffset + 2 * bytesPerFace;
835 cube_cmd[CUBE_PP_CUBIC_OFFSET_F3] = texobj->pp_txoffset + 3 * bytesPerFace;
836 cube_cmd[CUBE_PP_CUBIC_OFFSET_F4] = texobj->pp_txoffset + 4 * bytesPerFace;
837 cube_cmd[CUBE_PP_CUBIC_OFFSET_F5] = texobj->pp_txoffset + 5 * bytesPerFace;
838 R200_DB_STATECHANGE( rmesa, &rmesa->hw.cube[unit] );
839 }
840
841 texobj->dirty_state &= ~(1<<unit);
842 }
843
844
845 static void set_texgen_matrix( r200ContextPtr rmesa,
846 GLuint unit,
847 const GLfloat *s_plane,
848 const GLfloat *t_plane,
849 const GLfloat *r_plane,
850 const GLfloat *q_plane )
851 {
852 GLfloat m[16];
853
854 m[0] = s_plane[0];
855 m[4] = s_plane[1];
856 m[8] = s_plane[2];
857 m[12] = s_plane[3];
858
859 m[1] = t_plane[0];
860 m[5] = t_plane[1];
861 m[9] = t_plane[2];
862 m[13] = t_plane[3];
863
864 m[2] = r_plane[0];
865 m[6] = r_plane[1];
866 m[10] = r_plane[2];
867 m[14] = r_plane[3];
868
869 m[3] = q_plane[0];
870 m[7] = q_plane[1];
871 m[11] = q_plane[2];
872 m[15] = q_plane[3];
873
874 _math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m);
875 _math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) );
876 rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit;
877 }
878
879
880 /*
881 * Returns GL_FALSE if fallback required.
882 */
883 static GLboolean r200_validate_texgen( GLcontext *ctx, GLuint unit )
884 {
885 r200ContextPtr rmesa = R200_CONTEXT(ctx);
886 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
887 GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit*4;
888 GLuint tgi, tgcm;
889 GLuint mode = 0;
890 GLboolean mixed_fallback = GL_FALSE;
891 static const GLfloat I[16] = {
892 1, 0, 0, 0,
893 0, 1, 0, 0,
894 0, 0, 1, 0,
895 0, 0, 0, 1 };
896 static const GLfloat reflect[16] = {
897 -1, 0, 0, 0,
898 0, -1, 0, 0,
899 0, 0, -1, 0,
900 0, 0, 0, 1 };
901
902 rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
903 rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
904 rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
905 rmesa->TexGenNeedNormals[unit] = GL_FALSE;
906 tgi = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] & ~(R200_TEXGEN_INPUT_MASK <<
907 inputshift);
908 tgcm = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] & ~(R200_TEXGEN_COMP_MASK <<
909 (unit * 4));
910
911 if (0)
912 fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit);
913
914 if (texUnit->TexGenEnabled & S_BIT) {
915 mode = texUnit->GenModeS;
916 } else {
917 tgcm |= R200_TEXGEN_COMP_S << (unit * 4);
918 }
919
920 if (texUnit->TexGenEnabled & T_BIT) {
921 if (texUnit->GenModeT != mode)
922 mixed_fallback = GL_TRUE;
923 } else {
924 tgcm |= R200_TEXGEN_COMP_T << (unit * 4);
925 }
926
927 if (texUnit->TexGenEnabled & R_BIT) {
928 if (texUnit->GenModeR != mode)
929 mixed_fallback = GL_TRUE;
930 } else {
931 tgcm |= R200_TEXGEN_COMP_R << (unit * 4);
932 }
933
934 if (texUnit->TexGenEnabled & Q_BIT) {
935 if (texUnit->GenModeQ != mode)
936 mixed_fallback = GL_TRUE;
937 } else {
938 tgcm |= R200_TEXGEN_COMP_Q << (unit * 4);
939 }
940
941 if (mixed_fallback) {
942 if (R200_DEBUG & DEBUG_FALLBACKS)
943 fprintf(stderr, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
944 texUnit->TexGenEnabled, texUnit->GenModeS, texUnit->GenModeT,
945 texUnit->GenModeR, texUnit->GenModeQ);
946 return GL_FALSE;
947 }
948
949 switch (mode) {
950 case GL_OBJECT_LINEAR:
951 tgi |= R200_TEXGEN_INPUT_OBJ << inputshift;
952 set_texgen_matrix( rmesa, unit,
953 (texUnit->TexGenEnabled & S_BIT) ? texUnit->ObjectPlaneS : I,
954 (texUnit->TexGenEnabled & T_BIT) ? texUnit->ObjectPlaneT : I + 4,
955 (texUnit->TexGenEnabled & R_BIT) ? texUnit->ObjectPlaneR : I + 8,
956 (texUnit->TexGenEnabled & Q_BIT) ? texUnit->ObjectPlaneQ : I + 12);
957 break;
958
959 case GL_EYE_LINEAR:
960 tgi |= R200_TEXGEN_INPUT_EYE << inputshift;
961 set_texgen_matrix( rmesa, unit,
962 (texUnit->TexGenEnabled & S_BIT) ? texUnit->EyePlaneS : I,
963 (texUnit->TexGenEnabled & T_BIT) ? texUnit->EyePlaneT : I + 4,
964 (texUnit->TexGenEnabled & R_BIT) ? texUnit->EyePlaneR : I + 8,
965 (texUnit->TexGenEnabled & Q_BIT) ? texUnit->EyePlaneQ : I + 12);
966 break;
967
968 case GL_REFLECTION_MAP_NV:
969 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
970 tgi |= R200_TEXGEN_INPUT_EYE_REFLECT<<inputshift;
971 set_texgen_matrix( rmesa, unit,
972 (texUnit->TexGenEnabled & S_BIT) ? reflect : I,
973 (texUnit->TexGenEnabled & T_BIT) ? reflect + 4 : I + 4,
974 (texUnit->TexGenEnabled & R_BIT) ? reflect + 8 : I + 8,
975 I + 12);
976 break;
977
978 case GL_NORMAL_MAP_NV:
979 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
980 tgi |= R200_TEXGEN_INPUT_EYE_NORMAL<<inputshift;
981 break;
982
983 case GL_SPHERE_MAP:
984 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
985 tgi |= R200_TEXGEN_INPUT_SPHERE<<inputshift;
986 /* GL_SPHERE_MAP doesn't appear to work. */
987 return GL_FALSE;
988
989 case 0:
990 /* All texgen units were disabled, so just pass coords through. */
991 tgi |= unit << inputshift;
992 break;
993
994 default:
995 /* Unsupported mode, fallback:
996 */
997 if (R200_DEBUG & DEBUG_FALLBACKS)
998 fprintf(stderr, "fallback unsupported texgen, %d\n",
999 texUnit->GenModeS);
1000 return GL_FALSE;
1001 }
1002
1003 rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit;
1004 rmesa->TexGenCompSel |= R200_OUTPUT_TEX_0 << unit;
1005
1006 if (tgi != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] ||
1007 tgcm != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2])
1008 {
1009 R200_STATECHANGE(rmesa, tcg);
1010 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] = tgi;
1011 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] = tgcm;
1012 }
1013
1014 return GL_TRUE;
1015 }
1016
1017
1018 static void disable_tex( GLcontext *ctx, int unit )
1019 {
1020 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1021
1022 if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE<<unit)) {
1023 /* Texture unit disabled */
1024 if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
1025 /* The old texture is no longer bound to this texture unit.
1026 * Mark it as such.
1027 */
1028
1029 rmesa->state.texture.unit[unit].texobj->base.bound &= ~(1UL << unit);
1030 rmesa->state.texture.unit[unit].texobj = NULL;
1031 }
1032
1033 R200_STATECHANGE( rmesa, ctx );
1034 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~((R200_TEX_0_ENABLE |
1035 R200_TEX_BLEND_0_ENABLE) << unit);
1036 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_BLEND_0_ENABLE;
1037
1038 R200_STATECHANGE( rmesa, vtx );
1039 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
1040
1041 if (rmesa->TclFallback & (R200_TCL_FALLBACK_TEXGEN_0<<unit)) {
1042 TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
1043 }
1044
1045 /* Actually want to keep all units less than max active texture
1046 * enabled, right? Fix this for >2 texunits.
1047 */
1048 /* FIXME: What should happen here if r200UpdateTextureEnv fails? */
1049 if (unit == 0)
1050 r200UpdateTextureEnv( ctx, unit );
1051
1052
1053 {
1054 GLuint tmp = rmesa->TexGenEnabled;
1055
1056 rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
1057 rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
1058 rmesa->TexGenNeedNormals[unit] = GL_FALSE;
1059 rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
1060
1061 if (tmp != rmesa->TexGenEnabled) {
1062 rmesa->recheck_texgen[unit] = GL_TRUE;
1063 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1064 }
1065 }
1066 }
1067 }
1068
1069 static void set_re_cntl_d3d( GLcontext *ctx, int unit, GLboolean use_d3d )
1070 {
1071 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1072
1073 GLuint re_cntl;
1074
1075 re_cntl = rmesa->hw.set.cmd[SET_RE_CNTL] & ~(R200_VTX_STQ0_D3D << (2 * unit));
1076 if (use_d3d)
1077 re_cntl |= R200_VTX_STQ0_D3D << (2 * unit);
1078
1079 if ( re_cntl != rmesa->hw.set.cmd[SET_RE_CNTL] ) {
1080 R200_STATECHANGE( rmesa, set );
1081 rmesa->hw.set.cmd[SET_RE_CNTL] = re_cntl;
1082 }
1083 }
1084
1085 static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
1086 {
1087 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1088 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1089 struct gl_texture_object *tObj = texUnit->_Current;
1090 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1091
1092 /* Need to load the 2d images associated with this unit.
1093 */
1094 if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
1095 t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
1096 t->base.dirty_images[0] = ~0;
1097 }
1098
1099 ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
1100
1101 if ( t->base.dirty_images[0] ) {
1102 R200_FIREVERTICES( rmesa );
1103 r200SetTexImages( rmesa, tObj );
1104 r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
1105 if ( !t->base.memBlock )
1106 return GL_FALSE;
1107 }
1108
1109 set_re_cntl_d3d( ctx, unit, GL_FALSE );
1110
1111 return GL_TRUE;
1112 }
1113
1114 #if ENABLE_HW_3D_TEXTURE
1115 static GLboolean enable_tex_3d( GLcontext *ctx, int unit )
1116 {
1117 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1118 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1119 struct gl_texture_object *tObj = texUnit->_Current;
1120 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1121
1122 /* Need to load the 3d images associated with this unit.
1123 */
1124 if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
1125 t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
1126 t->base.dirty_images[0] = ~0;
1127 }
1128
1129 ASSERT(tObj->Target == GL_TEXTURE_3D);
1130
1131 /* R100 & R200 do not support mipmaps for 3D textures.
1132 */
1133 if ( (tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR) ) {
1134 return GL_FALSE;
1135 }
1136
1137 if ( t->base.dirty_images[0] ) {
1138 R200_FIREVERTICES( rmesa );
1139 r200SetTexImages( rmesa, tObj );
1140 r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
1141 if ( !t->base.memBlock )
1142 return GL_FALSE;
1143 }
1144
1145 set_re_cntl_d3d( ctx, unit, GL_TRUE );
1146
1147 return GL_TRUE;
1148 }
1149 #endif
1150
1151 static GLboolean enable_tex_cube( GLcontext *ctx, int unit )
1152 {
1153 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1154 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1155 struct gl_texture_object *tObj = texUnit->_Current;
1156 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1157 GLuint face;
1158
1159 /* Need to load the 2d images associated with this unit.
1160 */
1161 if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
1162 t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
1163 for (face = 0; face < 6; face++)
1164 t->base.dirty_images[face] = ~0;
1165 }
1166
1167 ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP);
1168
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] ) {
1172 /* flush */
1173 R200_FIREVERTICES( rmesa );
1174 /* layout memory space, once for all faces */
1175 r200SetTexImages( rmesa, tObj );
1176 }
1177
1178 /* upload (per face) */
1179 for (face = 0; face < 6; face++) {
1180 if (t->base.dirty_images[face]) {
1181 r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, face );
1182 }
1183 }
1184
1185 if ( !t->base.memBlock ) {
1186 /* texmem alloc failed, use s/w fallback */
1187 return GL_FALSE;
1188 }
1189
1190 set_re_cntl_d3d( ctx, unit, GL_TRUE );
1191
1192 return GL_TRUE;
1193 }
1194
1195 static GLboolean enable_tex_rect( GLcontext *ctx, int unit )
1196 {
1197 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1198 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1199 struct gl_texture_object *tObj = texUnit->_Current;
1200 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1201
1202 if (!(t->pp_txformat & R200_TXFORMAT_NON_POWER2)) {
1203 t->pp_txformat |= R200_TXFORMAT_NON_POWER2;
1204 t->base.dirty_images[0] = ~0;
1205 }
1206
1207 ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
1208
1209 if ( t->base.dirty_images[0] ) {
1210 R200_FIREVERTICES( rmesa );
1211 r200SetTexImages( rmesa, tObj );
1212 r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
1213 if ( !t->base.memBlock && !rmesa->prefer_gart_client_texturing )
1214 return GL_FALSE;
1215 }
1216
1217 set_re_cntl_d3d( ctx, unit, GL_FALSE );
1218
1219 return GL_TRUE;
1220 }
1221
1222
1223 static GLboolean update_tex_common( GLcontext *ctx, int unit )
1224 {
1225 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1226 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1227 struct gl_texture_object *tObj = texUnit->_Current;
1228 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1229 GLenum format;
1230
1231 /* Fallback if there's a texture border */
1232 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 )
1233 return GL_FALSE;
1234
1235 /* Update state if this is a different texture object to last
1236 * time.
1237 */
1238 if ( rmesa->state.texture.unit[unit].texobj != t ) {
1239 if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
1240 /* The old texture is no longer bound to this texture unit.
1241 * Mark it as such.
1242 */
1243
1244 rmesa->state.texture.unit[unit].texobj->base.bound &=
1245 ~(1UL << unit);
1246 }
1247
1248 rmesa->state.texture.unit[unit].texobj = t;
1249 t->base.bound |= (1UL << unit);
1250 t->dirty_state |= 1<<unit;
1251 driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
1252 }
1253
1254
1255 /* Newly enabled?
1256 */
1257 if ( 1|| !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE<<unit))) {
1258 R200_STATECHANGE( rmesa, ctx );
1259 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_0_ENABLE |
1260 R200_TEX_BLEND_0_ENABLE) << unit;
1261
1262 R200_STATECHANGE( rmesa, vtx );
1263 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
1264 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] |= 4 << (unit * 3);
1265
1266 rmesa->recheck_texgen[unit] = GL_TRUE;
1267 }
1268
1269 if (t->dirty_state & (1<<unit)) {
1270 import_tex_obj_state( rmesa, unit, t );
1271 }
1272
1273 if (rmesa->recheck_texgen[unit]) {
1274 GLboolean fallback = !r200_validate_texgen( ctx, unit );
1275 TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
1276 rmesa->recheck_texgen[unit] = 0;
1277 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1278 }
1279
1280 format = tObj->Image[0][tObj->BaseLevel]->Format;
1281 if ( rmesa->state.texture.unit[unit].format != format ||
1282 rmesa->state.texture.unit[unit].envMode != texUnit->EnvMode ) {
1283 rmesa->state.texture.unit[unit].format = format;
1284 rmesa->state.texture.unit[unit].envMode = texUnit->EnvMode;
1285 if ( ! r200UpdateTextureEnv( ctx, unit ) ) {
1286 return GL_FALSE;
1287 }
1288 }
1289
1290 FALLBACK( rmesa, R200_FALLBACK_BORDER_MODE, t->border_fallback );
1291 return !t->border_fallback;
1292 }
1293
1294
1295
1296 static GLboolean r200UpdateTextureUnit( GLcontext *ctx, int unit )
1297 {
1298 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1299
1300 if ( texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT) ) {
1301 return (enable_tex_rect( ctx, unit ) &&
1302 update_tex_common( ctx, unit ));
1303 }
1304 else if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
1305 return (enable_tex_2d( ctx, unit ) &&
1306 update_tex_common( ctx, unit ));
1307 }
1308 #if ENABLE_HW_3D_TEXTURE
1309 else if ( texUnit->_ReallyEnabled & (TEXTURE_3D_BIT) ) {
1310 return (enable_tex_3d( ctx, unit ) &&
1311 update_tex_common( ctx, unit ));
1312 }
1313 #endif
1314 else if ( texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT) ) {
1315 return (enable_tex_cube( ctx, unit ) &&
1316 update_tex_common( ctx, unit ));
1317 }
1318 else if ( texUnit->_ReallyEnabled ) {
1319 return GL_FALSE;
1320 }
1321 else {
1322 disable_tex( ctx, unit );
1323 return GL_TRUE;
1324 }
1325 }
1326
1327
1328 void r200UpdateTextureState( GLcontext *ctx )
1329 {
1330 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1331 GLboolean ok;
1332 GLuint dbg;
1333
1334 ok = (r200UpdateTextureUnit( ctx, 0 ) &&
1335 r200UpdateTextureUnit( ctx, 1 ) &&
1336 r200UpdateTextureUnit( ctx, 2 ) &&
1337 r200UpdateTextureUnit( ctx, 3 ) &&
1338 r200UpdateTextureUnit( ctx, 4 ) &&
1339 r200UpdateTextureUnit( ctx, 5 ));
1340
1341 FALLBACK( rmesa, R200_FALLBACK_TEXTURE, !ok );
1342
1343 if (rmesa->TclFallback)
1344 r200ChooseVertexState( ctx );
1345
1346
1347 if (rmesa->r200Screen->chipset & R200_CHIPSET_REAL_R200) {
1348
1349 /*
1350 * T0 hang workaround -------------
1351 * not needed for r200 derivatives?
1352 */
1353 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_ENABLE_MASK) == R200_TEX_0_ENABLE &&
1354 (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) {
1355
1356 R200_STATECHANGE(rmesa, ctx);
1357 R200_STATECHANGE(rmesa, tex[1]);
1358 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_1_ENABLE;
1359 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1360 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1361 }
1362 else {
1363 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE) &&
1364 (rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1365 R200_STATECHANGE(rmesa, tex[1]);
1366 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1367 }
1368 }
1369
1370 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1371 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1372 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1373 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1374 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1375 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1376 R200_MIN_FILTER_LINEAR)) {
1377 R200_STATECHANGE(rmesa, ctx);
1378 R200_STATECHANGE(rmesa, tex[i+1]);
1379 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1380 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1381 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1382 }
1383 else {
1384 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1385 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1386 R200_STATECHANGE(rmesa, tex[i+1]);
1387 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1388 }
1389 }
1390 } */
1391
1392 /*
1393 * Texture cache LRU hang workaround -------------
1394 * not needed for r200 derivatives?
1395 */
1396
1397 /* While the cases below attempt to only enable the workaround in the
1398 * specific cases necessary, they were insufficient. See bugzilla #1519,
1399 * #729, #814. Tests with quake3 showed no impact on performance.
1400 */
1401 dbg = 0x6;
1402
1403 /*
1404 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) &&
1405 ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1406 0x04) == 0)) ||
1407 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1408 ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1409 0x04) == 0)) ||
1410 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1411 ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1412 0x04) == 0)))
1413 {
1414 dbg |= 0x02;
1415 }
1416
1417 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) &&
1418 ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1419 0x04) == 0)) ||
1420 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1421 ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1422 0x04) == 0)) ||
1423 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1424 ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1425 0x04) == 0)))
1426 {
1427 dbg |= 0x04;
1428 }*/
1429
1430 if (dbg != rmesa->hw.tam.cmd[TAM_DEBUG3]) {
1431 R200_STATECHANGE( rmesa, tam );
1432 rmesa->hw.tam.cmd[TAM_DEBUG3] = dbg;
1433 if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg);
1434 }
1435 }
1436 }