remove CVS/XFree86 keywords
[mesa.git] / src / mesa / drivers / dri / r200 / r200_texstate.c
1 /*
2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
3
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
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 * Keith Whitwell <keith@tungstengraphics.com>
33 */
34
35 #include "glheader.h"
36 #include "imports.h"
37 #include "context.h"
38 #include "macros.h"
39 #include "texformat.h"
40 #include "enums.h"
41
42 #include "r200_context.h"
43 #include "r200_state.h"
44 #include "r200_ioctl.h"
45 #include "r200_swtcl.h"
46 #include "r200_tex.h"
47 #include "r200_tcl.h"
48
49
50 #define R200_TXFORMAT_A8 R200_TXFORMAT_I8
51 #define R200_TXFORMAT_L8 R200_TXFORMAT_I8
52 #define R200_TXFORMAT_AL88 R200_TXFORMAT_AI88
53 #define R200_TXFORMAT_YCBCR R200_TXFORMAT_YVYU422
54 #define R200_TXFORMAT_YCBCR_REV R200_TXFORMAT_VYUY422
55 #define R200_TXFORMAT_RGB_DXT1 R200_TXFORMAT_DXT1
56 #define R200_TXFORMAT_RGBA_DXT1 R200_TXFORMAT_DXT1
57 #define R200_TXFORMAT_RGBA_DXT3 R200_TXFORMAT_DXT23
58 #define R200_TXFORMAT_RGBA_DXT5 R200_TXFORMAT_DXT45
59
60 #define _COLOR(f) \
61 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, 0 }
62 #define _COLOR_REV(f) \
63 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f, 0 }
64 #define _ALPHA(f) \
65 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
66 #define _ALPHA_REV(f) \
67 [ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
68 #define _YUV(f) \
69 [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, R200_YUV_TO_RGB }
70 #define _INVALID(f) \
71 [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
72 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
73 && (tx_table_le[f].format != 0xffffffff) )
74
75 static const struct {
76 GLuint format, filter;
77 }
78 tx_table_be[] =
79 {
80 [ MESA_FORMAT_RGBA8888 ] = { R200_TXFORMAT_ABGR8888 | R200_TXFORMAT_ALPHA_IN_MAP, 0 },
81 _ALPHA_REV(RGBA8888),
82 _ALPHA(ARGB8888),
83 _ALPHA_REV(ARGB8888),
84 _INVALID(RGB888),
85 _COLOR(RGB565),
86 _COLOR_REV(RGB565),
87 _ALPHA(ARGB4444),
88 _ALPHA_REV(ARGB4444),
89 _ALPHA(ARGB1555),
90 _ALPHA_REV(ARGB1555),
91 _ALPHA(AL88),
92 _ALPHA_REV(AL88),
93 _ALPHA(A8),
94 _COLOR(L8),
95 _ALPHA(I8),
96 _INVALID(CI8),
97 _YUV(YCBCR),
98 _YUV(YCBCR_REV),
99 _INVALID(RGB_FXT1),
100 _INVALID(RGBA_FXT1),
101 _COLOR(RGB_DXT1),
102 _ALPHA(RGBA_DXT1),
103 _ALPHA(RGBA_DXT3),
104 _ALPHA(RGBA_DXT5),
105 };
106
107 static const struct {
108 GLuint format, filter;
109 }
110 tx_table_le[] =
111 {
112 _ALPHA(RGBA8888),
113 [ MESA_FORMAT_RGBA8888_REV ] = { R200_TXFORMAT_ABGR8888 | R200_TXFORMAT_ALPHA_IN_MAP, 0 },
114 _ALPHA(ARGB8888),
115 _ALPHA_REV(ARGB8888),
116 _INVALID(RGB888),
117 _COLOR(RGB565),
118 _COLOR_REV(RGB565),
119 _ALPHA(ARGB4444),
120 _ALPHA_REV(ARGB4444),
121 _ALPHA(ARGB1555),
122 _ALPHA_REV(ARGB1555),
123 _ALPHA(AL88),
124 _ALPHA_REV(AL88),
125 _ALPHA(A8),
126 _COLOR(L8),
127 _ALPHA(I8),
128 _INVALID(CI8),
129 _YUV(YCBCR),
130 _YUV(YCBCR_REV),
131 _INVALID(RGB_FXT1),
132 _INVALID(RGBA_FXT1),
133 _COLOR(RGB_DXT1),
134 _ALPHA(RGBA_DXT1),
135 _ALPHA(RGBA_DXT3),
136 _ALPHA(RGBA_DXT5),
137 };
138
139 #undef _COLOR
140 #undef _ALPHA
141 #undef _INVALID
142
143 /**
144 * This function computes the number of bytes of storage needed for
145 * the given texture object (all mipmap levels, all cube faces).
146 * The \c image[face][level].x/y/width/height parameters for upload/blitting
147 * are computed here. \c pp_txfilter, \c pp_txformat, etc. will be set here
148 * too.
149 *
150 * \param rmesa Context pointer
151 * \param tObj GL texture object whose images are to be posted to
152 * hardware state.
153 */
154 static void r200SetTexImages( r200ContextPtr rmesa,
155 struct gl_texture_object *tObj )
156 {
157 r200TexObjPtr t = (r200TexObjPtr)tObj->DriverData;
158 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
159 GLint curOffset, blitWidth;
160 GLint i, texelBytes;
161 GLint numLevels;
162 GLint log2Width, log2Height, log2Depth;
163 const GLuint ui = 1;
164 const GLubyte littleEndian = *((const GLubyte *) &ui);
165
166 /* Set the hardware texture format
167 */
168
169 t->pp_txformat &= ~(R200_TXFORMAT_FORMAT_MASK |
170 R200_TXFORMAT_ALPHA_IN_MAP);
171 t->pp_txfilter &= ~R200_YUV_TO_RGB;
172
173 if ( VALID_FORMAT( baseImage->TexFormat->MesaFormat ) ) {
174 if (littleEndian) {
175 t->pp_txformat |= tx_table_le[ baseImage->TexFormat->MesaFormat ].format;
176 t->pp_txfilter |= tx_table_le[ baseImage->TexFormat->MesaFormat ].filter;
177 }
178 else {
179 t->pp_txformat |= tx_table_be[ baseImage->TexFormat->MesaFormat ].format;
180 t->pp_txfilter |= tx_table_be[ baseImage->TexFormat->MesaFormat ].filter;
181 }
182 }
183 else {
184 _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
185 return;
186 }
187
188 texelBytes = baseImage->TexFormat->TexelBytes;
189
190 /* Compute which mipmap levels we really want to send to the hardware.
191 */
192
193 driCalculateTextureFirstLastLevel( (driTextureObject *) t );
194 log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2;
195 log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
196 log2Depth = tObj->Image[0][t->base.firstLevel]->DepthLog2;
197
198 numLevels = t->base.lastLevel - t->base.firstLevel + 1;
199
200 assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
201
202 /* Calculate mipmap offsets and dimensions for blitting (uploading)
203 * The idea is that we lay out the mipmap levels within a block of
204 * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
205 */
206 curOffset = 0;
207 blitWidth = BLIT_WIDTH_BYTES;
208 t->tile_bits = 0;
209
210 /* figure out if this texture is suitable for tiling. */
211 if (texelBytes) {
212 if (rmesa->texmicrotile && (tObj->Target != GL_TEXTURE_RECTANGLE_NV) &&
213 /* texrect might be able to use micro tiling too in theory? */
214 (baseImage->Height > 1)) {
215 /* allow 32 (bytes) x 1 mip (which will use two times the space
216 the non-tiled version would use) max if base texture is large enough */
217 if ((numLevels == 1) ||
218 (((baseImage->Width * texelBytes / baseImage->Height) <= 32) &&
219 (baseImage->Width * texelBytes > 64)) ||
220 ((baseImage->Width * texelBytes / baseImage->Height) <= 16)) {
221 t->tile_bits |= R200_TXO_MICRO_TILE;
222 }
223 }
224 if (tObj->Target != GL_TEXTURE_RECTANGLE_NV) {
225 /* we can set macro tiling even for small textures, they will be untiled anyway */
226 t->tile_bits |= R200_TXO_MACRO_TILE;
227 }
228 }
229
230 for (i = 0; i < numLevels; i++) {
231 const struct gl_texture_image *texImage;
232 GLuint size;
233
234 texImage = tObj->Image[0][i + t->base.firstLevel];
235 if ( !texImage )
236 break;
237
238 /* find image size in bytes */
239 if (texImage->IsCompressed) {
240 /* need to calculate the size AFTER padding even though the texture is
241 submitted without padding.
242 Only handle pot textures currently - don't know if npot is even possible,
243 size calculation would certainly need (trivial) adjustments.
244 Align (and later pad) to 32byte, not sure what that 64byte blit width is
245 good for? */
246 if ((t->pp_txformat & R200_TXFORMAT_FORMAT_MASK) == R200_TXFORMAT_DXT1) {
247 /* RGB_DXT1/RGBA_DXT1, 8 bytes per block */
248 if ((texImage->Width + 3) < 8) /* width one block */
249 size = texImage->CompressedSize * 4;
250 else if ((texImage->Width + 3) < 16)
251 size = texImage->CompressedSize * 2;
252 else size = texImage->CompressedSize;
253 }
254 else /* DXT3/5, 16 bytes per block */
255 if ((texImage->Width + 3) < 8)
256 size = texImage->CompressedSize * 2;
257 else size = texImage->CompressedSize;
258 }
259 else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
260 size = ((texImage->Width * texelBytes + 63) & ~63) * texImage->Height;
261 }
262 else if (t->tile_bits & R200_TXO_MICRO_TILE) {
263 /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
264 though the actual offset may be different (if texture is less than
265 32 bytes width) to the untiled case */
266 int w = (texImage->Width * texelBytes * 2 + 31) & ~31;
267 size = (w * ((texImage->Height + 1) / 2)) * texImage->Depth;
268 blitWidth = MAX2(texImage->Width, 64 / texelBytes);
269 }
270 else {
271 int w = (texImage->Width * texelBytes + 31) & ~31;
272 size = w * texImage->Height * texImage->Depth;
273 blitWidth = MAX2(texImage->Width, 64 / texelBytes);
274 }
275 assert(size > 0);
276
277 /* Align to 32-byte offset. It is faster to do this unconditionally
278 * (no branch penalty).
279 */
280
281 curOffset = (curOffset + 0x1f) & ~0x1f;
282
283 if (texelBytes) {
284 t->image[0][i].x = curOffset; /* fix x and y coords up later together with offset */
285 t->image[0][i].y = 0;
286 t->image[0][i].width = MIN2(size / texelBytes, blitWidth);
287 t->image[0][i].height = (size / texelBytes) / t->image[0][i].width;
288 }
289 else {
290 t->image[0][i].x = curOffset % BLIT_WIDTH_BYTES;
291 t->image[0][i].y = curOffset / BLIT_WIDTH_BYTES;
292 t->image[0][i].width = MIN2(size, BLIT_WIDTH_BYTES);
293 t->image[0][i].height = size / t->image[0][i].width;
294 }
295
296 #if 0
297 /* for debugging only and only applicable to non-rectangle targets */
298 assert(size % t->image[0][i].width == 0);
299 assert(t->image[0][i].x == 0
300 || (size < BLIT_WIDTH_BYTES && t->image[0][i].height == 1));
301 #endif
302
303 if (0)
304 fprintf(stderr,
305 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
306 i, texImage->Width, texImage->Height,
307 t->image[0][i].x, t->image[0][i].y,
308 t->image[0][i].width, t->image[0][i].height, size, curOffset);
309
310 curOffset += size;
311
312 }
313
314 /* Align the total size of texture memory block.
315 */
316 t->base.totalSize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
317
318 /* Setup remaining cube face blits, if needed */
319 if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
320 const GLuint faceSize = t->base.totalSize;
321 GLuint face;
322 /* reuse face 0 x/y/width/height - just update the offset when uploading */
323 for (face = 1; face < 6; face++) {
324 for (i = 0; i < numLevels; i++) {
325 t->image[face][i].x = t->image[0][i].x;
326 t->image[face][i].y = t->image[0][i].y;
327 t->image[face][i].width = t->image[0][i].width;
328 t->image[face][i].height = t->image[0][i].height;
329 }
330 }
331 t->base.totalSize = 6 * faceSize; /* total texmem needed */
332 }
333
334
335 /* Hardware state:
336 */
337 t->pp_txfilter &= ~R200_MAX_MIP_LEVEL_MASK;
338 t->pp_txfilter |= (numLevels - 1) << R200_MAX_MIP_LEVEL_SHIFT;
339
340 t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK |
341 R200_TXFORMAT_HEIGHT_MASK |
342 R200_TXFORMAT_CUBIC_MAP_ENABLE |
343 R200_TXFORMAT_F5_WIDTH_MASK |
344 R200_TXFORMAT_F5_HEIGHT_MASK);
345 t->pp_txformat |= ((log2Width << R200_TXFORMAT_WIDTH_SHIFT) |
346 (log2Height << R200_TXFORMAT_HEIGHT_SHIFT));
347
348 t->pp_txformat_x &= ~(R200_DEPTH_LOG2_MASK | R200_TEXCOORD_MASK);
349 if (tObj->Target == GL_TEXTURE_3D) {
350 t->pp_txformat_x |= (log2Depth << R200_DEPTH_LOG2_SHIFT);
351 t->pp_txformat_x |= R200_TEXCOORD_VOLUME;
352 }
353 else if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
354 ASSERT(log2Width == log2Height);
355 t->pp_txformat |= ((log2Width << R200_TXFORMAT_F5_WIDTH_SHIFT) |
356 (log2Height << R200_TXFORMAT_F5_HEIGHT_SHIFT) |
357 /* don't think we need this bit, if it exists at all - fglrx does not set it */
358 (R200_TXFORMAT_CUBIC_MAP_ENABLE));
359 t->pp_txformat_x |= R200_TEXCOORD_CUBIC_ENV;
360 t->pp_cubic_faces = ((log2Width << R200_FACE_WIDTH_1_SHIFT) |
361 (log2Height << R200_FACE_HEIGHT_1_SHIFT) |
362 (log2Width << R200_FACE_WIDTH_2_SHIFT) |
363 (log2Height << R200_FACE_HEIGHT_2_SHIFT) |
364 (log2Width << R200_FACE_WIDTH_3_SHIFT) |
365 (log2Height << R200_FACE_HEIGHT_3_SHIFT) |
366 (log2Width << R200_FACE_WIDTH_4_SHIFT) |
367 (log2Height << R200_FACE_HEIGHT_4_SHIFT));
368 }
369 else {
370 /* If we don't in fact send enough texture coordinates, q will be 1,
371 * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
372 */
373 t->pp_txformat_x |= R200_TEXCOORD_PROJ;
374 }
375
376 t->pp_txsize = (((tObj->Image[0][t->base.firstLevel]->Width - 1) << 0) |
377 ((tObj->Image[0][t->base.firstLevel]->Height - 1) << 16));
378
379 /* Only need to round to nearest 32 for textures, but the blitter
380 * requires 64-byte aligned pitches, and we may/may not need the
381 * blitter. NPOT only!
382 */
383 if (baseImage->IsCompressed)
384 t->pp_txpitch = (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63);
385 else
386 t->pp_txpitch = ((tObj->Image[0][t->base.firstLevel]->Width * texelBytes) + 63) & ~(63);
387 t->pp_txpitch -= 32;
388
389 t->dirty_state = TEX_ALL;
390
391 /* FYI: r200UploadTexImages( rmesa, t ) used to be called here */
392 }
393
394
395
396 /* ================================================================
397 * Texture combine functions
398 */
399
400 /* GL_ARB_texture_env_combine support
401 */
402
403 /* The color tables have combine functions for GL_SRC_COLOR,
404 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
405 */
406 static GLuint r200_register_color[][R200_MAX_TEXTURE_UNITS] =
407 {
408 {
409 R200_TXC_ARG_A_R0_COLOR,
410 R200_TXC_ARG_A_R1_COLOR,
411 R200_TXC_ARG_A_R2_COLOR,
412 R200_TXC_ARG_A_R3_COLOR,
413 R200_TXC_ARG_A_R4_COLOR,
414 R200_TXC_ARG_A_R5_COLOR
415 },
416 {
417 R200_TXC_ARG_A_R0_COLOR | R200_TXC_COMP_ARG_A,
418 R200_TXC_ARG_A_R1_COLOR | R200_TXC_COMP_ARG_A,
419 R200_TXC_ARG_A_R2_COLOR | R200_TXC_COMP_ARG_A,
420 R200_TXC_ARG_A_R3_COLOR | R200_TXC_COMP_ARG_A,
421 R200_TXC_ARG_A_R4_COLOR | R200_TXC_COMP_ARG_A,
422 R200_TXC_ARG_A_R5_COLOR | R200_TXC_COMP_ARG_A
423 },
424 {
425 R200_TXC_ARG_A_R0_ALPHA,
426 R200_TXC_ARG_A_R1_ALPHA,
427 R200_TXC_ARG_A_R2_ALPHA,
428 R200_TXC_ARG_A_R3_ALPHA,
429 R200_TXC_ARG_A_R4_ALPHA,
430 R200_TXC_ARG_A_R5_ALPHA
431 },
432 {
433 R200_TXC_ARG_A_R0_ALPHA | R200_TXC_COMP_ARG_A,
434 R200_TXC_ARG_A_R1_ALPHA | R200_TXC_COMP_ARG_A,
435 R200_TXC_ARG_A_R2_ALPHA | R200_TXC_COMP_ARG_A,
436 R200_TXC_ARG_A_R3_ALPHA | R200_TXC_COMP_ARG_A,
437 R200_TXC_ARG_A_R4_ALPHA | R200_TXC_COMP_ARG_A,
438 R200_TXC_ARG_A_R5_ALPHA | R200_TXC_COMP_ARG_A
439 },
440 };
441
442 static GLuint r200_tfactor_color[] =
443 {
444 R200_TXC_ARG_A_TFACTOR_COLOR,
445 R200_TXC_ARG_A_TFACTOR_COLOR | R200_TXC_COMP_ARG_A,
446 R200_TXC_ARG_A_TFACTOR_ALPHA,
447 R200_TXC_ARG_A_TFACTOR_ALPHA | R200_TXC_COMP_ARG_A
448 };
449
450 static GLuint r200_tfactor1_color[] =
451 {
452 R200_TXC_ARG_A_TFACTOR1_COLOR,
453 R200_TXC_ARG_A_TFACTOR1_COLOR | R200_TXC_COMP_ARG_A,
454 R200_TXC_ARG_A_TFACTOR1_ALPHA,
455 R200_TXC_ARG_A_TFACTOR1_ALPHA | R200_TXC_COMP_ARG_A
456 };
457
458 static GLuint r200_primary_color[] =
459 {
460 R200_TXC_ARG_A_DIFFUSE_COLOR,
461 R200_TXC_ARG_A_DIFFUSE_COLOR | R200_TXC_COMP_ARG_A,
462 R200_TXC_ARG_A_DIFFUSE_ALPHA,
463 R200_TXC_ARG_A_DIFFUSE_ALPHA | R200_TXC_COMP_ARG_A
464 };
465
466 /* GL_ZERO table - indices 0-3
467 * GL_ONE table - indices 1-4
468 */
469 static GLuint r200_zero_color[] =
470 {
471 R200_TXC_ARG_A_ZERO,
472 R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A,
473 R200_TXC_ARG_A_ZERO,
474 R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A,
475 R200_TXC_ARG_A_ZERO
476 };
477
478 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
479 */
480 static GLuint r200_register_alpha[][R200_MAX_TEXTURE_UNITS] =
481 {
482 {
483 R200_TXA_ARG_A_R0_ALPHA,
484 R200_TXA_ARG_A_R1_ALPHA,
485 R200_TXA_ARG_A_R2_ALPHA,
486 R200_TXA_ARG_A_R3_ALPHA,
487 R200_TXA_ARG_A_R4_ALPHA,
488 R200_TXA_ARG_A_R5_ALPHA
489 },
490 {
491 R200_TXA_ARG_A_R0_ALPHA | R200_TXA_COMP_ARG_A,
492 R200_TXA_ARG_A_R1_ALPHA | R200_TXA_COMP_ARG_A,
493 R200_TXA_ARG_A_R2_ALPHA | R200_TXA_COMP_ARG_A,
494 R200_TXA_ARG_A_R3_ALPHA | R200_TXA_COMP_ARG_A,
495 R200_TXA_ARG_A_R4_ALPHA | R200_TXA_COMP_ARG_A,
496 R200_TXA_ARG_A_R5_ALPHA | R200_TXA_COMP_ARG_A
497 },
498 };
499
500 static GLuint r200_tfactor_alpha[] =
501 {
502 R200_TXA_ARG_A_TFACTOR_ALPHA,
503 R200_TXA_ARG_A_TFACTOR_ALPHA | R200_TXA_COMP_ARG_A
504 };
505
506 static GLuint r200_tfactor1_alpha[] =
507 {
508 R200_TXA_ARG_A_TFACTOR1_ALPHA,
509 R200_TXA_ARG_A_TFACTOR1_ALPHA | R200_TXA_COMP_ARG_A
510 };
511
512 static GLuint r200_primary_alpha[] =
513 {
514 R200_TXA_ARG_A_DIFFUSE_ALPHA,
515 R200_TXA_ARG_A_DIFFUSE_ALPHA | R200_TXA_COMP_ARG_A
516 };
517
518 /* GL_ZERO table - indices 0-1
519 * GL_ONE table - indices 1-2
520 */
521 static GLuint r200_zero_alpha[] =
522 {
523 R200_TXA_ARG_A_ZERO,
524 R200_TXA_ARG_A_ZERO | R200_TXA_COMP_ARG_A,
525 R200_TXA_ARG_A_ZERO,
526 };
527
528
529 /* Extract the arg from slot A, shift it into the correct argument slot
530 * and set the corresponding complement bit.
531 */
532 #define R200_COLOR_ARG( n, arg ) \
533 do { \
534 color_combine |= \
535 ((color_arg[n] & R200_TXC_ARG_A_MASK) \
536 << R200_TXC_ARG_##arg##_SHIFT); \
537 color_combine |= \
538 ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \
539 << R200_TXC_COMP_ARG_##arg##_SHIFT); \
540 } while (0)
541
542 #define R200_ALPHA_ARG( n, arg ) \
543 do { \
544 alpha_combine |= \
545 ((alpha_arg[n] & R200_TXA_ARG_A_MASK) \
546 << R200_TXA_ARG_##arg##_SHIFT); \
547 alpha_combine |= \
548 ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \
549 << R200_TXA_COMP_ARG_##arg##_SHIFT); \
550 } while (0)
551
552
553 /* ================================================================
554 * Texture unit state management
555 */
556
557 static GLboolean r200UpdateTextureEnv( GLcontext *ctx, int unit, int slot, GLuint replaceargs )
558 {
559 r200ContextPtr rmesa = R200_CONTEXT(ctx);
560 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
561 GLuint color_combine, alpha_combine;
562 GLuint color_scale = rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] &
563 ~(R200_TXC_SCALE_MASK | R200_TXC_OUTPUT_REG_MASK | R200_TXC_TFACTOR_SEL_MASK |
564 R200_TXC_TFACTOR1_SEL_MASK);
565 GLuint alpha_scale = rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] &
566 ~(R200_TXA_DOT_ALPHA | R200_TXA_SCALE_MASK | R200_TXA_OUTPUT_REG_MASK |
567 R200_TXA_TFACTOR_SEL_MASK | R200_TXA_TFACTOR1_SEL_MASK);
568
569 /* texUnit->_Current can be NULL if and only if the texture unit is
570 * not actually enabled.
571 */
572 assert( (texUnit->_ReallyEnabled == 0)
573 || (texUnit->_Current != NULL) );
574
575 if ( R200_DEBUG & DEBUG_TEXTURE ) {
576 fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, (void *)ctx, unit );
577 }
578
579 /* Set the texture environment state. Isn't this nice and clean?
580 * The chip will automagically set the texture alpha to 0xff when
581 * the texture format does not include an alpha component. This
582 * reduces the amount of special-casing we have to do, alpha-only
583 * textures being a notable exception.
584 */
585
586 color_scale |= ((rmesa->state.texture.unit[unit].outputreg + 1) << R200_TXC_OUTPUT_REG_SHIFT) |
587 (unit << R200_TXC_TFACTOR_SEL_SHIFT) |
588 (replaceargs << R200_TXC_TFACTOR1_SEL_SHIFT);
589 alpha_scale |= ((rmesa->state.texture.unit[unit].outputreg + 1) << R200_TXA_OUTPUT_REG_SHIFT) |
590 (unit << R200_TXA_TFACTOR_SEL_SHIFT) |
591 (replaceargs << R200_TXA_TFACTOR1_SEL_SHIFT);
592
593 if ( !texUnit->_ReallyEnabled ) {
594 assert( unit == 0);
595 color_combine = R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO
596 | R200_TXC_ARG_C_DIFFUSE_COLOR | R200_TXC_OP_MADD;
597 alpha_combine = R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO
598 | R200_TXA_ARG_C_DIFFUSE_ALPHA | R200_TXA_OP_MADD;
599 }
600 else {
601 GLuint color_arg[3], alpha_arg[3];
602 GLuint i;
603 const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
604 const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
605 GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB;
606 GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA;
607
608
609 const GLint replaceoprgb =
610 ctx->Texture.Unit[replaceargs]._CurrentCombine->OperandRGB[0] - GL_SRC_COLOR;
611 const GLint replaceopa =
612 ctx->Texture.Unit[replaceargs]._CurrentCombine->OperandA[0] - GL_SRC_ALPHA;
613
614 /* Step 1:
615 * Extract the color and alpha combine function arguments.
616 */
617 for ( i = 0 ; i < numColorArgs ; i++ ) {
618 GLint op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR;
619 const GLint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i];
620 assert(op >= 0);
621 assert(op <= 3);
622 switch ( srcRGBi ) {
623 case GL_TEXTURE:
624 color_arg[i] = r200_register_color[op][unit];
625 break;
626 case GL_CONSTANT:
627 color_arg[i] = r200_tfactor_color[op];
628 break;
629 case GL_PRIMARY_COLOR:
630 color_arg[i] = r200_primary_color[op];
631 break;
632 case GL_PREVIOUS:
633 if (replaceargs != unit) {
634 const GLint srcRGBreplace =
635 ctx->Texture.Unit[replaceargs]._CurrentCombine->SourceRGB[0];
636 if (op >= 2) {
637 op = op ^ replaceopa;
638 }
639 else {
640 op = op ^ replaceoprgb;
641 }
642 switch (srcRGBreplace) {
643 case GL_TEXTURE:
644 color_arg[i] = r200_register_color[op][replaceargs];
645 break;
646 case GL_CONSTANT:
647 color_arg[i] = r200_tfactor1_color[op];
648 break;
649 case GL_PRIMARY_COLOR:
650 color_arg[i] = r200_primary_color[op];
651 break;
652 case GL_PREVIOUS:
653 if (slot == 0)
654 color_arg[i] = r200_primary_color[op];
655 else
656 color_arg[i] = r200_register_color[op]
657 [rmesa->state.texture.unit[replaceargs - 1].outputreg];
658 break;
659 case GL_ZERO:
660 color_arg[i] = r200_zero_color[op];
661 break;
662 case GL_ONE:
663 color_arg[i] = r200_zero_color[op+1];
664 break;
665 case GL_TEXTURE0:
666 case GL_TEXTURE1:
667 case GL_TEXTURE2:
668 case GL_TEXTURE3:
669 case GL_TEXTURE4:
670 case GL_TEXTURE5:
671 color_arg[i] = r200_register_color[op][srcRGBreplace - GL_TEXTURE0];
672 break;
673 default:
674 return GL_FALSE;
675 }
676 }
677 else {
678 if (slot == 0)
679 color_arg[i] = r200_primary_color[op];
680 else
681 color_arg[i] = r200_register_color[op]
682 [rmesa->state.texture.unit[unit - 1].outputreg];
683 }
684 break;
685 case GL_ZERO:
686 color_arg[i] = r200_zero_color[op];
687 break;
688 case GL_ONE:
689 color_arg[i] = r200_zero_color[op+1];
690 break;
691 case GL_TEXTURE0:
692 case GL_TEXTURE1:
693 case GL_TEXTURE2:
694 case GL_TEXTURE3:
695 case GL_TEXTURE4:
696 case GL_TEXTURE5:
697 color_arg[i] = r200_register_color[op][srcRGBi - GL_TEXTURE0];
698 break;
699 default:
700 return GL_FALSE;
701 }
702 }
703
704 for ( i = 0 ; i < numAlphaArgs ; i++ ) {
705 GLint op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA;
706 const GLint srcAi = texUnit->_CurrentCombine->SourceA[i];
707 assert(op >= 0);
708 assert(op <= 1);
709 switch ( srcAi ) {
710 case GL_TEXTURE:
711 alpha_arg[i] = r200_register_alpha[op][unit];
712 break;
713 case GL_CONSTANT:
714 alpha_arg[i] = r200_tfactor_alpha[op];
715 break;
716 case GL_PRIMARY_COLOR:
717 alpha_arg[i] = r200_primary_alpha[op];
718 break;
719 case GL_PREVIOUS:
720 if (replaceargs != unit) {
721 const GLint srcAreplace =
722 ctx->Texture.Unit[replaceargs]._CurrentCombine->SourceA[0];
723 op = op ^ replaceopa;
724 switch (srcAreplace) {
725 case GL_TEXTURE:
726 alpha_arg[i] = r200_register_alpha[op][replaceargs];
727 break;
728 case GL_CONSTANT:
729 alpha_arg[i] = r200_tfactor1_alpha[op];
730 break;
731 case GL_PRIMARY_COLOR:
732 alpha_arg[i] = r200_primary_alpha[op];
733 break;
734 case GL_PREVIOUS:
735 if (slot == 0)
736 alpha_arg[i] = r200_primary_alpha[op];
737 else
738 alpha_arg[i] = r200_register_alpha[op]
739 [rmesa->state.texture.unit[replaceargs - 1].outputreg];
740 break;
741 case GL_ZERO:
742 alpha_arg[i] = r200_zero_alpha[op];
743 break;
744 case GL_ONE:
745 alpha_arg[i] = r200_zero_alpha[op+1];
746 break;
747 case GL_TEXTURE0:
748 case GL_TEXTURE1:
749 case GL_TEXTURE2:
750 case GL_TEXTURE3:
751 case GL_TEXTURE4:
752 case GL_TEXTURE5:
753 alpha_arg[i] = r200_register_alpha[op][srcAreplace - GL_TEXTURE0];
754 break;
755 default:
756 return GL_FALSE;
757 }
758 }
759 else {
760 if (slot == 0)
761 alpha_arg[i] = r200_primary_alpha[op];
762 else
763 alpha_arg[i] = r200_register_alpha[op]
764 [rmesa->state.texture.unit[unit - 1].outputreg];
765 }
766 break;
767 case GL_ZERO:
768 alpha_arg[i] = r200_zero_alpha[op];
769 break;
770 case GL_ONE:
771 alpha_arg[i] = r200_zero_alpha[op+1];
772 break;
773 case GL_TEXTURE0:
774 case GL_TEXTURE1:
775 case GL_TEXTURE2:
776 case GL_TEXTURE3:
777 case GL_TEXTURE4:
778 case GL_TEXTURE5:
779 alpha_arg[i] = r200_register_alpha[op][srcAi - GL_TEXTURE0];
780 break;
781 default:
782 return GL_FALSE;
783 }
784 }
785
786 /* Step 2:
787 * Build up the color and alpha combine functions.
788 */
789 switch ( texUnit->_CurrentCombine->ModeRGB ) {
790 case GL_REPLACE:
791 color_combine = (R200_TXC_ARG_A_ZERO |
792 R200_TXC_ARG_B_ZERO |
793 R200_TXC_OP_MADD);
794 R200_COLOR_ARG( 0, C );
795 break;
796 case GL_MODULATE:
797 color_combine = (R200_TXC_ARG_C_ZERO |
798 R200_TXC_OP_MADD);
799 R200_COLOR_ARG( 0, A );
800 R200_COLOR_ARG( 1, B );
801 break;
802 case GL_ADD:
803 color_combine = (R200_TXC_ARG_B_ZERO |
804 R200_TXC_COMP_ARG_B |
805 R200_TXC_OP_MADD);
806 R200_COLOR_ARG( 0, A );
807 R200_COLOR_ARG( 1, C );
808 break;
809 case GL_ADD_SIGNED:
810 color_combine = (R200_TXC_ARG_B_ZERO |
811 R200_TXC_COMP_ARG_B |
812 R200_TXC_BIAS_ARG_C | /* new */
813 R200_TXC_OP_MADD); /* was ADDSIGNED */
814 R200_COLOR_ARG( 0, A );
815 R200_COLOR_ARG( 1, C );
816 break;
817 case GL_SUBTRACT:
818 color_combine = (R200_TXC_ARG_B_ZERO |
819 R200_TXC_COMP_ARG_B |
820 R200_TXC_NEG_ARG_C |
821 R200_TXC_OP_MADD);
822 R200_COLOR_ARG( 0, A );
823 R200_COLOR_ARG( 1, C );
824 break;
825 case GL_INTERPOLATE:
826 color_combine = (R200_TXC_OP_LERP);
827 R200_COLOR_ARG( 0, B );
828 R200_COLOR_ARG( 1, A );
829 R200_COLOR_ARG( 2, C );
830 break;
831
832 case GL_DOT3_RGB_EXT:
833 case GL_DOT3_RGBA_EXT:
834 /* The EXT version of the DOT3 extension does not support the
835 * scale factor, but the ARB version (and the version in OpenGL
836 * 1.3) does.
837 */
838 RGBshift = 0;
839 /* FALLTHROUGH */
840
841 case GL_DOT3_RGB:
842 case GL_DOT3_RGBA:
843 /* DOT3 works differently on R200 than on R100. On R100, just
844 * setting the DOT3 mode did everything for you. On R200, the
845 * driver has to enable the biasing and scale in the inputs to
846 * put them in the proper [-1,1] range. This is what the 4x and
847 * the -0.5 in the DOT3 spec do. The post-scale is then set
848 * normally.
849 */
850
851 color_combine = (R200_TXC_ARG_C_ZERO |
852 R200_TXC_OP_DOT3 |
853 R200_TXC_BIAS_ARG_A |
854 R200_TXC_BIAS_ARG_B |
855 R200_TXC_SCALE_ARG_A |
856 R200_TXC_SCALE_ARG_B);
857 R200_COLOR_ARG( 0, A );
858 R200_COLOR_ARG( 1, B );
859 break;
860
861 case GL_MODULATE_ADD_ATI:
862 color_combine = (R200_TXC_OP_MADD);
863 R200_COLOR_ARG( 0, A );
864 R200_COLOR_ARG( 1, C );
865 R200_COLOR_ARG( 2, B );
866 break;
867 case GL_MODULATE_SIGNED_ADD_ATI:
868 color_combine = (R200_TXC_BIAS_ARG_C | /* new */
869 R200_TXC_OP_MADD); /* was ADDSIGNED */
870 R200_COLOR_ARG( 0, A );
871 R200_COLOR_ARG( 1, C );
872 R200_COLOR_ARG( 2, B );
873 break;
874 case GL_MODULATE_SUBTRACT_ATI:
875 color_combine = (R200_TXC_NEG_ARG_C |
876 R200_TXC_OP_MADD);
877 R200_COLOR_ARG( 0, A );
878 R200_COLOR_ARG( 1, C );
879 R200_COLOR_ARG( 2, B );
880 break;
881 default:
882 return GL_FALSE;
883 }
884
885 switch ( texUnit->_CurrentCombine->ModeA ) {
886 case GL_REPLACE:
887 alpha_combine = (R200_TXA_ARG_A_ZERO |
888 R200_TXA_ARG_B_ZERO |
889 R200_TXA_OP_MADD);
890 R200_ALPHA_ARG( 0, C );
891 break;
892 case GL_MODULATE:
893 alpha_combine = (R200_TXA_ARG_C_ZERO |
894 R200_TXA_OP_MADD);
895 R200_ALPHA_ARG( 0, A );
896 R200_ALPHA_ARG( 1, B );
897 break;
898 case GL_ADD:
899 alpha_combine = (R200_TXA_ARG_B_ZERO |
900 R200_TXA_COMP_ARG_B |
901 R200_TXA_OP_MADD);
902 R200_ALPHA_ARG( 0, A );
903 R200_ALPHA_ARG( 1, C );
904 break;
905 case GL_ADD_SIGNED:
906 alpha_combine = (R200_TXA_ARG_B_ZERO |
907 R200_TXA_COMP_ARG_B |
908 R200_TXA_BIAS_ARG_C | /* new */
909 R200_TXA_OP_MADD); /* was ADDSIGNED */
910 R200_ALPHA_ARG( 0, A );
911 R200_ALPHA_ARG( 1, C );
912 break;
913 case GL_SUBTRACT:
914 alpha_combine = (R200_TXA_ARG_B_ZERO |
915 R200_TXA_COMP_ARG_B |
916 R200_TXA_NEG_ARG_C |
917 R200_TXA_OP_MADD);
918 R200_ALPHA_ARG( 0, A );
919 R200_ALPHA_ARG( 1, C );
920 break;
921 case GL_INTERPOLATE:
922 alpha_combine = (R200_TXA_OP_LERP);
923 R200_ALPHA_ARG( 0, B );
924 R200_ALPHA_ARG( 1, A );
925 R200_ALPHA_ARG( 2, C );
926 break;
927
928 case GL_MODULATE_ADD_ATI:
929 alpha_combine = (R200_TXA_OP_MADD);
930 R200_ALPHA_ARG( 0, A );
931 R200_ALPHA_ARG( 1, C );
932 R200_ALPHA_ARG( 2, B );
933 break;
934 case GL_MODULATE_SIGNED_ADD_ATI:
935 alpha_combine = (R200_TXA_BIAS_ARG_C | /* new */
936 R200_TXA_OP_MADD); /* was ADDSIGNED */
937 R200_ALPHA_ARG( 0, A );
938 R200_ALPHA_ARG( 1, C );
939 R200_ALPHA_ARG( 2, B );
940 break;
941 case GL_MODULATE_SUBTRACT_ATI:
942 alpha_combine = (R200_TXA_NEG_ARG_C |
943 R200_TXA_OP_MADD);
944 R200_ALPHA_ARG( 0, A );
945 R200_ALPHA_ARG( 1, C );
946 R200_ALPHA_ARG( 2, B );
947 break;
948 default:
949 return GL_FALSE;
950 }
951
952 if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT)
953 || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ) {
954 alpha_scale |= R200_TXA_DOT_ALPHA;
955 Ashift = RGBshift;
956 }
957
958 /* Step 3:
959 * Apply the scale factor.
960 */
961 color_scale |= (RGBshift << R200_TXC_SCALE_SHIFT);
962 alpha_scale |= (Ashift << R200_TXA_SCALE_SHIFT);
963
964 /* All done!
965 */
966 }
967
968 if ( rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND] != color_combine ||
969 rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND] != alpha_combine ||
970 rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] != color_scale ||
971 rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] != alpha_scale) {
972 R200_STATECHANGE( rmesa, pix[slot] );
973 rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND] = color_combine;
974 rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND] = alpha_combine;
975 rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] = color_scale;
976 rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] = alpha_scale;
977 }
978
979 return GL_TRUE;
980 }
981
982 #define REF_COLOR 1
983 #define REF_ALPHA 2
984
985 static GLboolean r200UpdateAllTexEnv( GLcontext *ctx )
986 {
987 r200ContextPtr rmesa = R200_CONTEXT(ctx);
988 GLint i, j, currslot;
989 GLint maxunitused = -1;
990 GLboolean texregfree[6] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
991 GLubyte stageref[7] = {0, 0, 0, 0, 0, 0, 0};
992 GLint nextunit[R200_MAX_TEXTURE_UNITS] = {0, 0, 0, 0, 0, 0};
993 GLint currentnext = -1;
994 GLboolean ok;
995
996 /* find highest used unit */
997 for ( j = 0; j < R200_MAX_TEXTURE_UNITS; j++) {
998 if (ctx->Texture.Unit[j]._ReallyEnabled) {
999 maxunitused = j;
1000 }
1001 }
1002 stageref[maxunitused + 1] = REF_COLOR | REF_ALPHA;
1003
1004 for ( j = maxunitused; j >= 0; j-- ) {
1005 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[j];
1006
1007 rmesa->state.texture.unit[j].outputreg = -1;
1008
1009 if (stageref[j + 1]) {
1010
1011 /* use the lowest available reg. That gets us automatically reg0 for the last stage.
1012 need this even for disabled units, as it may get referenced due to the replace
1013 optimization */
1014 for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS; i++ ) {
1015 if (texregfree[i]) {
1016 rmesa->state.texture.unit[j].outputreg = i;
1017 break;
1018 }
1019 }
1020 if (rmesa->state.texture.unit[j].outputreg == -1) {
1021 /* no more free regs we can use. Need a fallback :-( */
1022 return GL_FALSE;
1023 }
1024
1025 nextunit[j] = currentnext;
1026
1027 if (!texUnit->_ReallyEnabled) {
1028 /* the not enabled stages are referenced "indirectly",
1029 must not cut off the lower stages */
1030 stageref[j] = REF_COLOR | REF_ALPHA;
1031 continue;
1032 }
1033 currentnext = j;
1034
1035 const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
1036 const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
1037 const GLboolean isdot3rgba = (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ||
1038 (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT);
1039
1040
1041 /* check if we need the color part, special case for dot3_rgba
1042 as if only the alpha part is referenced later on it still is using the color part */
1043 if ((stageref[j + 1] & REF_COLOR) || isdot3rgba) {
1044 for ( i = 0 ; i < numColorArgs ; i++ ) {
1045 const GLuint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i];
1046 const GLuint op = texUnit->_CurrentCombine->OperandRGB[i];
1047 switch ( srcRGBi ) {
1048 case GL_PREVIOUS:
1049 /* op 0/1 are referencing color, op 2/3 alpha */
1050 stageref[j] |= (op >> 1) + 1;
1051 break;
1052 case GL_TEXTURE:
1053 texregfree[j] = GL_FALSE;
1054 break;
1055 case GL_TEXTURE0:
1056 case GL_TEXTURE1:
1057 case GL_TEXTURE2:
1058 case GL_TEXTURE3:
1059 case GL_TEXTURE4:
1060 case GL_TEXTURE5:
1061 texregfree[srcRGBi - GL_TEXTURE0] = GL_FALSE;
1062 break;
1063 default: /* don't care about other sources here */
1064 break;
1065 }
1066 }
1067 }
1068
1069 /* alpha args are ignored for dot3_rgba */
1070 if ((stageref[j + 1] & REF_ALPHA) && !isdot3rgba) {
1071
1072 for ( i = 0 ; i < numAlphaArgs ; i++ ) {
1073 const GLuint srcAi = texUnit->_CurrentCombine->SourceA[i];
1074 switch ( srcAi ) {
1075 case GL_PREVIOUS:
1076 stageref[j] |= REF_ALPHA;
1077 break;
1078 case GL_TEXTURE:
1079 texregfree[j] = GL_FALSE;
1080 break;
1081 case GL_TEXTURE0:
1082 case GL_TEXTURE1:
1083 case GL_TEXTURE2:
1084 case GL_TEXTURE3:
1085 case GL_TEXTURE4:
1086 case GL_TEXTURE5:
1087 texregfree[srcAi - GL_TEXTURE0] = GL_FALSE;
1088 break;
1089 default: /* don't care about other sources here */
1090 break;
1091 }
1092 }
1093 }
1094 }
1095 }
1096
1097 /* don't enable texture sampling for units if the result is not used */
1098 for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) {
1099 if (ctx->Texture.Unit[i]._ReallyEnabled && !texregfree[i])
1100 rmesa->state.texture.unit[i].unitneeded = ctx->Texture.Unit[i]._ReallyEnabled;
1101 else rmesa->state.texture.unit[i].unitneeded = 0;
1102 }
1103
1104 ok = GL_TRUE;
1105 currslot = 0;
1106 rmesa->state.envneeded = 1;
1107
1108 i = 0;
1109 while ((i <= maxunitused) && (i >= 0)) {
1110 /* only output instruction if the results are referenced */
1111 if (ctx->Texture.Unit[i]._ReallyEnabled && stageref[i+1]) {
1112 GLuint replaceunit = i;
1113 /* try to optimize GL_REPLACE away (only one level deep though) */
1114 if ( (ctx->Texture.Unit[i]._CurrentCombine->ModeRGB == GL_REPLACE) &&
1115 (ctx->Texture.Unit[i]._CurrentCombine->ModeA == GL_REPLACE) &&
1116 (ctx->Texture.Unit[i]._CurrentCombine->ScaleShiftRGB == 0) &&
1117 (ctx->Texture.Unit[i]._CurrentCombine->ScaleShiftA == 0) &&
1118 (nextunit[i] > 0) ) {
1119 /* yippie! can optimize it away! */
1120 replaceunit = i;
1121 i = nextunit[i];
1122 }
1123
1124 /* need env instruction slot */
1125 rmesa->state.envneeded |= 1 << currslot;
1126 ok = r200UpdateTextureEnv( ctx, i, currslot, replaceunit );
1127 if (!ok) return GL_FALSE;
1128 currslot++;
1129 }
1130 i = i + 1;
1131 }
1132
1133 if (currslot == 0) {
1134 /* need one stage at least */
1135 rmesa->state.texture.unit[0].outputreg = 0;
1136 ok = r200UpdateTextureEnv( ctx, 0, 0, 0 );
1137 }
1138
1139 R200_STATECHANGE( rmesa, ctx );
1140 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_BLEND_ENABLE_MASK | R200_MULTI_PASS_ENABLE);
1141 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= rmesa->state.envneeded << R200_TEX_BLEND_0_ENABLE_SHIFT;
1142
1143 return ok;
1144 }
1145
1146 #undef REF_COLOR
1147 #undef REF_ALPHA
1148
1149
1150 #define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \
1151 R200_MIN_FILTER_MASK | \
1152 R200_MAG_FILTER_MASK | \
1153 R200_MAX_ANISO_MASK | \
1154 R200_YUV_TO_RGB | \
1155 R200_YUV_TEMPERATURE_MASK | \
1156 R200_CLAMP_S_MASK | \
1157 R200_CLAMP_T_MASK | \
1158 R200_BORDER_MODE_D3D )
1159
1160 #define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \
1161 R200_TXFORMAT_HEIGHT_MASK | \
1162 R200_TXFORMAT_FORMAT_MASK | \
1163 R200_TXFORMAT_F5_WIDTH_MASK | \
1164 R200_TXFORMAT_F5_HEIGHT_MASK | \
1165 R200_TXFORMAT_ALPHA_IN_MAP | \
1166 R200_TXFORMAT_CUBIC_MAP_ENABLE | \
1167 R200_TXFORMAT_NON_POWER2)
1168
1169 #define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \
1170 R200_TEXCOORD_MASK | \
1171 R200_CLAMP_Q_MASK | \
1172 R200_VOLUME_FILTER_MASK)
1173
1174
1175 static void import_tex_obj_state( r200ContextPtr rmesa,
1176 int unit,
1177 r200TexObjPtr texobj )
1178 {
1179 /* do not use RADEON_DB_STATE to avoid stale texture caches */
1180 int *cmd = &rmesa->hw.tex[unit].cmd[TEX_CMD_0];
1181
1182 R200_STATECHANGE( rmesa, tex[unit] );
1183
1184 cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
1185 cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK;
1186 cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1187 cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
1188 cmd[TEX_PP_TXFORMAT_X] &= ~TEXOBJ_TXFORMAT_X_MASK;
1189 cmd[TEX_PP_TXFORMAT_X] |= texobj->pp_txformat_x & TEXOBJ_TXFORMAT_X_MASK;
1190 cmd[TEX_PP_TXSIZE] = texobj->pp_txsize; /* NPOT only! */
1191 cmd[TEX_PP_TXPITCH] = texobj->pp_txpitch; /* NPOT only! */
1192 cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
1193 if (rmesa->r200Screen->drmSupportsFragShader) {
1194 cmd[TEX_PP_TXOFFSET_NEWDRM] = texobj->pp_txoffset;
1195 }
1196 else {
1197 cmd[TEX_PP_TXOFFSET_OLDDRM] = texobj->pp_txoffset;
1198 }
1199
1200 if (texobj->base.tObj->Target == GL_TEXTURE_CUBE_MAP) {
1201 int *cube_cmd = &rmesa->hw.cube[unit].cmd[CUBE_CMD_0];
1202 GLuint bytesPerFace = texobj->base.totalSize / 6;
1203 ASSERT(texobj->base.totalSize % 6 == 0);
1204
1205 R200_STATECHANGE( rmesa, cube[unit] );
1206 cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
1207 if (rmesa->r200Screen->drmSupportsFragShader) {
1208 /* that value is submitted twice. could change cube atom
1209 to not include that command when new drm is used */
1210 cmd[TEX_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
1211 }
1212 cube_cmd[CUBE_PP_CUBIC_OFFSET_F1] = texobj->pp_txoffset + 1 * bytesPerFace;
1213 cube_cmd[CUBE_PP_CUBIC_OFFSET_F2] = texobj->pp_txoffset + 2 * bytesPerFace;
1214 cube_cmd[CUBE_PP_CUBIC_OFFSET_F3] = texobj->pp_txoffset + 3 * bytesPerFace;
1215 cube_cmd[CUBE_PP_CUBIC_OFFSET_F4] = texobj->pp_txoffset + 4 * bytesPerFace;
1216 cube_cmd[CUBE_PP_CUBIC_OFFSET_F5] = texobj->pp_txoffset + 5 * bytesPerFace;
1217 }
1218
1219 texobj->dirty_state &= ~(1<<unit);
1220 }
1221
1222
1223 static void set_texgen_matrix( r200ContextPtr rmesa,
1224 GLuint unit,
1225 const GLfloat *s_plane,
1226 const GLfloat *t_plane,
1227 const GLfloat *r_plane,
1228 const GLfloat *q_plane )
1229 {
1230 GLfloat m[16];
1231
1232 m[0] = s_plane[0];
1233 m[4] = s_plane[1];
1234 m[8] = s_plane[2];
1235 m[12] = s_plane[3];
1236
1237 m[1] = t_plane[0];
1238 m[5] = t_plane[1];
1239 m[9] = t_plane[2];
1240 m[13] = t_plane[3];
1241
1242 m[2] = r_plane[0];
1243 m[6] = r_plane[1];
1244 m[10] = r_plane[2];
1245 m[14] = r_plane[3];
1246
1247 m[3] = q_plane[0];
1248 m[7] = q_plane[1];
1249 m[11] = q_plane[2];
1250 m[15] = q_plane[3];
1251
1252 _math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m);
1253 _math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) );
1254 rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit;
1255 }
1256
1257
1258 static GLuint r200_need_dis_texgen(const GLbitfield texGenEnabled,
1259 const GLfloat *planeS,
1260 const GLfloat *planeT,
1261 const GLfloat *planeR,
1262 const GLfloat *planeQ)
1263 {
1264 GLuint needtgenable = 0;
1265
1266 if (!(texGenEnabled & S_BIT)) {
1267 if (((texGenEnabled & T_BIT) && planeT[0] != 0.0) ||
1268 ((texGenEnabled & R_BIT) && planeR[0] != 0.0) ||
1269 ((texGenEnabled & Q_BIT) && planeQ[0] != 0.0)) {
1270 needtgenable |= S_BIT;
1271 }
1272 }
1273 if (!(texGenEnabled & T_BIT)) {
1274 if (((texGenEnabled & S_BIT) && planeS[1] != 0.0) ||
1275 ((texGenEnabled & R_BIT) && planeR[1] != 0.0) ||
1276 ((texGenEnabled & Q_BIT) && planeQ[1] != 0.0)) {
1277 needtgenable |= T_BIT;
1278 }
1279 }
1280 if (!(texGenEnabled & R_BIT)) {
1281 if (((texGenEnabled & S_BIT) && planeS[2] != 0.0) ||
1282 ((texGenEnabled & T_BIT) && planeT[2] != 0.0) ||
1283 ((texGenEnabled & Q_BIT) && planeQ[2] != 0.0)) {
1284 needtgenable |= R_BIT;
1285 }
1286 }
1287 if (!(texGenEnabled & Q_BIT)) {
1288 if (((texGenEnabled & S_BIT) && planeS[3] != 0.0) ||
1289 ((texGenEnabled & T_BIT) && planeT[3] != 0.0) ||
1290 ((texGenEnabled & R_BIT) && planeR[3] != 0.0)) {
1291 needtgenable |= Q_BIT;
1292 }
1293 }
1294
1295 return needtgenable;
1296 }
1297
1298
1299 /*
1300 * Returns GL_FALSE if fallback required.
1301 */
1302 static GLboolean r200_validate_texgen( GLcontext *ctx, GLuint unit )
1303 {
1304 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1305 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1306 GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit*4;
1307 GLuint tgi, tgcm;
1308 GLuint mode = 0;
1309 GLboolean mixed_fallback = GL_FALSE;
1310 static const GLfloat I[16] = {
1311 1, 0, 0, 0,
1312 0, 1, 0, 0,
1313 0, 0, 1, 0,
1314 0, 0, 0, 1 };
1315 static const GLfloat reflect[16] = {
1316 -1, 0, 0, 0,
1317 0, -1, 0, 0,
1318 0, 0, -1, 0,
1319 0, 0, 0, 1 };
1320
1321 rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
1322 rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
1323 rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
1324 rmesa->TexGenNeedNormals[unit] = GL_FALSE;
1325 tgi = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] & ~(R200_TEXGEN_INPUT_MASK <<
1326 inputshift);
1327 tgcm = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] & ~(R200_TEXGEN_COMP_MASK <<
1328 (unit * 4));
1329
1330 if (0)
1331 fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit);
1332
1333 if (texUnit->TexGenEnabled & S_BIT) {
1334 mode = texUnit->GenModeS;
1335 } else {
1336 tgcm |= R200_TEXGEN_COMP_S << (unit * 4);
1337 }
1338
1339 if (texUnit->TexGenEnabled & T_BIT) {
1340 if (texUnit->GenModeT != mode)
1341 mixed_fallback = GL_TRUE;
1342 } else {
1343 tgcm |= R200_TEXGEN_COMP_T << (unit * 4);
1344 }
1345
1346 if (texUnit->TexGenEnabled & R_BIT) {
1347 if (texUnit->GenModeR != mode)
1348 mixed_fallback = GL_TRUE;
1349 } else {
1350 tgcm |= R200_TEXGEN_COMP_R << (unit * 4);
1351 }
1352
1353 if (texUnit->TexGenEnabled & Q_BIT) {
1354 if (texUnit->GenModeQ != mode)
1355 mixed_fallback = GL_TRUE;
1356 } else {
1357 tgcm |= R200_TEXGEN_COMP_Q << (unit * 4);
1358 }
1359
1360 if (mixed_fallback) {
1361 if (R200_DEBUG & DEBUG_FALLBACKS)
1362 fprintf(stderr, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
1363 texUnit->TexGenEnabled, texUnit->GenModeS, texUnit->GenModeT,
1364 texUnit->GenModeR, texUnit->GenModeQ);
1365 return GL_FALSE;
1366 }
1367
1368 /* we CANNOT do mixed mode if the texgen mode requires a plane where the input
1369 is not enabled for texgen, since the planes are concatenated into texmat,
1370 and thus the input will come from texcoord rather than tex gen equation!
1371 Either fallback or just hope that those texcoords aren't really needed...
1372 Assuming the former will cause lots of unnecessary fallbacks, the latter will
1373 generate bogus results sometimes - it's pretty much impossible to really know
1374 when a fallback is needed, depends on texmat and what sort of texture is bound
1375 etc, - for now fallback if we're missing either S or T bits, there's a high
1376 probability we need the texcoords in that case.
1377 That's a lot of work for some obscure texgen mixed mode fixup - why oh why
1378 doesn't the chip just directly accept the plane parameters :-(. */
1379 switch (mode) {
1380 case GL_OBJECT_LINEAR: {
1381 GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled,
1382 texUnit->ObjectPlaneS, texUnit->ObjectPlaneT,
1383 texUnit->ObjectPlaneR, texUnit->ObjectPlaneQ );
1384 if (needtgenable & (S_BIT | T_BIT)) {
1385 if (R200_DEBUG & DEBUG_FALLBACKS)
1386 fprintf(stderr, "fallback mixed texgen / obj plane, 0x%x\n",
1387 texUnit->TexGenEnabled);
1388 return GL_FALSE;
1389 }
1390 if (needtgenable & (R_BIT)) {
1391 tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4));
1392 }
1393 if (needtgenable & (Q_BIT)) {
1394 tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4));
1395 }
1396
1397 tgi |= R200_TEXGEN_INPUT_OBJ << inputshift;
1398 set_texgen_matrix( rmesa, unit,
1399 (texUnit->TexGenEnabled & S_BIT) ? texUnit->ObjectPlaneS : I,
1400 (texUnit->TexGenEnabled & T_BIT) ? texUnit->ObjectPlaneT : I + 4,
1401 (texUnit->TexGenEnabled & R_BIT) ? texUnit->ObjectPlaneR : I + 8,
1402 (texUnit->TexGenEnabled & Q_BIT) ? texUnit->ObjectPlaneQ : I + 12);
1403 }
1404 break;
1405
1406 case GL_EYE_LINEAR: {
1407 GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled,
1408 texUnit->EyePlaneS, texUnit->EyePlaneT,
1409 texUnit->EyePlaneR, texUnit->EyePlaneQ );
1410 if (needtgenable & (S_BIT | T_BIT)) {
1411 if (R200_DEBUG & DEBUG_FALLBACKS)
1412 fprintf(stderr, "fallback mixed texgen / eye plane, 0x%x\n",
1413 texUnit->TexGenEnabled);
1414 return GL_FALSE;
1415 }
1416 if (needtgenable & (R_BIT)) {
1417 tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4));
1418 }
1419 if (needtgenable & (Q_BIT)) {
1420 tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4));
1421 }
1422 tgi |= R200_TEXGEN_INPUT_EYE << inputshift;
1423 set_texgen_matrix( rmesa, unit,
1424 (texUnit->TexGenEnabled & S_BIT) ? texUnit->EyePlaneS : I,
1425 (texUnit->TexGenEnabled & T_BIT) ? texUnit->EyePlaneT : I + 4,
1426 (texUnit->TexGenEnabled & R_BIT) ? texUnit->EyePlaneR : I + 8,
1427 (texUnit->TexGenEnabled & Q_BIT) ? texUnit->EyePlaneQ : I + 12);
1428 }
1429 break;
1430
1431 case GL_REFLECTION_MAP_NV:
1432 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1433 tgi |= R200_TEXGEN_INPUT_EYE_REFLECT << inputshift;
1434 /* pretty weird, must only negate when lighting is enabled? */
1435 if (ctx->Light.Enabled)
1436 set_texgen_matrix( rmesa, unit,
1437 (texUnit->TexGenEnabled & S_BIT) ? reflect : I,
1438 (texUnit->TexGenEnabled & T_BIT) ? reflect + 4 : I + 4,
1439 (texUnit->TexGenEnabled & R_BIT) ? reflect + 8 : I + 8,
1440 I + 12);
1441 break;
1442
1443 case GL_NORMAL_MAP_NV:
1444 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1445 tgi |= R200_TEXGEN_INPUT_EYE_NORMAL<<inputshift;
1446 break;
1447
1448 case GL_SPHERE_MAP:
1449 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1450 tgi |= R200_TEXGEN_INPUT_SPHERE<<inputshift;
1451 break;
1452
1453 case 0:
1454 /* All texgen units were disabled, so just pass coords through. */
1455 tgi |= unit << inputshift;
1456 break;
1457
1458 default:
1459 /* Unsupported mode, fallback:
1460 */
1461 if (R200_DEBUG & DEBUG_FALLBACKS)
1462 fprintf(stderr, "fallback unsupported texgen, %d\n",
1463 texUnit->GenModeS);
1464 return GL_FALSE;
1465 }
1466
1467 rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit;
1468 rmesa->TexGenCompSel |= R200_OUTPUT_TEX_0 << unit;
1469
1470 if (tgi != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] ||
1471 tgcm != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2])
1472 {
1473 R200_STATECHANGE(rmesa, tcg);
1474 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] = tgi;
1475 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] = tgcm;
1476 }
1477
1478 return GL_TRUE;
1479 }
1480
1481
1482 static void disable_tex( GLcontext *ctx, int unit )
1483 {
1484 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1485
1486 if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE<<unit)) {
1487 /* Texture unit disabled */
1488 if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
1489 /* The old texture is no longer bound to this texture unit.
1490 * Mark it as such.
1491 */
1492
1493 rmesa->state.texture.unit[unit].texobj->base.bound &= ~(1UL << unit);
1494 rmesa->state.texture.unit[unit].texobj = NULL;
1495 }
1496
1497 R200_STATECHANGE( rmesa, ctx );
1498 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_0_ENABLE << unit);
1499
1500 R200_STATECHANGE( rmesa, vtx );
1501 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
1502
1503 if (rmesa->TclFallback & (R200_TCL_FALLBACK_TEXGEN_0<<unit)) {
1504 TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
1505 }
1506
1507 /* Actually want to keep all units less than max active texture
1508 * enabled, right? Fix this for >2 texunits.
1509 */
1510
1511 {
1512 GLuint tmp = rmesa->TexGenEnabled;
1513
1514 rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
1515 rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
1516 rmesa->TexGenNeedNormals[unit] = GL_FALSE;
1517 rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
1518
1519 if (tmp != rmesa->TexGenEnabled) {
1520 rmesa->recheck_texgen[unit] = GL_TRUE;
1521 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1522 }
1523 }
1524 }
1525 }
1526
1527 void set_re_cntl_d3d( GLcontext *ctx, int unit, GLboolean use_d3d )
1528 {
1529 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1530
1531 GLuint re_cntl;
1532
1533 re_cntl = rmesa->hw.set.cmd[SET_RE_CNTL] & ~(R200_VTX_STQ0_D3D << (2 * unit));
1534 if (use_d3d)
1535 re_cntl |= R200_VTX_STQ0_D3D << (2 * unit);
1536
1537 if ( re_cntl != rmesa->hw.set.cmd[SET_RE_CNTL] ) {
1538 R200_STATECHANGE( rmesa, set );
1539 rmesa->hw.set.cmd[SET_RE_CNTL] = re_cntl;
1540 }
1541 }
1542
1543 static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
1544 {
1545 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1546 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1547 struct gl_texture_object *tObj = texUnit->_Current;
1548 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1549
1550 /* Need to load the 2d images associated with this unit.
1551 */
1552 if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
1553 t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
1554 t->base.dirty_images[0] = ~0;
1555 }
1556
1557 ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
1558
1559 if ( t->base.dirty_images[0] ) {
1560 R200_FIREVERTICES( rmesa );
1561 r200SetTexImages( rmesa, tObj );
1562 r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
1563 if ( !t->base.memBlock )
1564 return GL_FALSE;
1565 }
1566
1567 set_re_cntl_d3d( ctx, unit, GL_FALSE );
1568
1569 return GL_TRUE;
1570 }
1571
1572 #if ENABLE_HW_3D_TEXTURE
1573 static GLboolean enable_tex_3d( GLcontext *ctx, int unit )
1574 {
1575 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1576 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1577 struct gl_texture_object *tObj = texUnit->_Current;
1578 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1579
1580 /* Need to load the 3d images associated with this unit.
1581 */
1582 if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
1583 t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
1584 t->base.dirty_images[0] = ~0;
1585 }
1586
1587 ASSERT(tObj->Target == GL_TEXTURE_3D);
1588
1589 /* R100 & R200 do not support mipmaps for 3D textures.
1590 */
1591 if ( (tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR) ) {
1592 return GL_FALSE;
1593 }
1594
1595 if ( t->base.dirty_images[0] ) {
1596 R200_FIREVERTICES( rmesa );
1597 r200SetTexImages( rmesa, tObj );
1598 r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
1599 if ( !t->base.memBlock )
1600 return GL_FALSE;
1601 }
1602
1603 set_re_cntl_d3d( ctx, unit, GL_TRUE );
1604
1605 return GL_TRUE;
1606 }
1607 #endif
1608
1609 static GLboolean enable_tex_cube( GLcontext *ctx, int unit )
1610 {
1611 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1612 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1613 struct gl_texture_object *tObj = texUnit->_Current;
1614 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1615 GLuint face;
1616
1617 /* Need to load the 2d images associated with this unit.
1618 */
1619 if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
1620 t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
1621 for (face = 0; face < 6; face++)
1622 t->base.dirty_images[face] = ~0;
1623 }
1624
1625 ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP);
1626
1627 if ( t->base.dirty_images[0] || t->base.dirty_images[1] ||
1628 t->base.dirty_images[2] || t->base.dirty_images[3] ||
1629 t->base.dirty_images[4] || t->base.dirty_images[5] ) {
1630 /* flush */
1631 R200_FIREVERTICES( rmesa );
1632 /* layout memory space, once for all faces */
1633 r200SetTexImages( rmesa, tObj );
1634 }
1635
1636 /* upload (per face) */
1637 for (face = 0; face < 6; face++) {
1638 if (t->base.dirty_images[face]) {
1639 r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, face );
1640 }
1641 }
1642
1643 if ( !t->base.memBlock ) {
1644 /* texmem alloc failed, use s/w fallback */
1645 return GL_FALSE;
1646 }
1647
1648 set_re_cntl_d3d( ctx, unit, GL_TRUE );
1649
1650 return GL_TRUE;
1651 }
1652
1653 static GLboolean enable_tex_rect( GLcontext *ctx, int unit )
1654 {
1655 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1656 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1657 struct gl_texture_object *tObj = texUnit->_Current;
1658 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1659
1660 if (!(t->pp_txformat & R200_TXFORMAT_NON_POWER2)) {
1661 t->pp_txformat |= R200_TXFORMAT_NON_POWER2;
1662 t->base.dirty_images[0] = ~0;
1663 }
1664
1665 ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
1666
1667 if ( t->base.dirty_images[0] ) {
1668 R200_FIREVERTICES( rmesa );
1669 r200SetTexImages( rmesa, tObj );
1670 r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
1671 if ( !t->base.memBlock && !rmesa->prefer_gart_client_texturing )
1672 return GL_FALSE;
1673 }
1674
1675 set_re_cntl_d3d( ctx, unit, GL_FALSE );
1676
1677 return GL_TRUE;
1678 }
1679
1680
1681 static GLboolean update_tex_common( GLcontext *ctx, int unit )
1682 {
1683 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1684 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1685 struct gl_texture_object *tObj = texUnit->_Current;
1686 r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1687
1688 /* Fallback if there's a texture border */
1689 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 )
1690 return GL_FALSE;
1691
1692 /* Update state if this is a different texture object to last
1693 * time.
1694 */
1695 if ( rmesa->state.texture.unit[unit].texobj != t ) {
1696 if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
1697 /* The old texture is no longer bound to this texture unit.
1698 * Mark it as such.
1699 */
1700
1701 rmesa->state.texture.unit[unit].texobj->base.bound &=
1702 ~(1UL << unit);
1703 }
1704
1705 rmesa->state.texture.unit[unit].texobj = t;
1706 t->base.bound |= (1UL << unit);
1707 t->dirty_state |= 1<<unit;
1708 driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
1709 }
1710
1711
1712 /* Newly enabled?
1713 */
1714 if ( 1|| !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE<<unit))) {
1715 R200_STATECHANGE( rmesa, ctx );
1716 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << unit;
1717
1718 R200_STATECHANGE( rmesa, vtx );
1719 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
1720 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] |= 4 << (unit * 3);
1721
1722 rmesa->recheck_texgen[unit] = GL_TRUE;
1723 }
1724
1725 if (t->dirty_state & (1<<unit)) {
1726 import_tex_obj_state( rmesa, unit, t );
1727 }
1728
1729 if (rmesa->recheck_texgen[unit]) {
1730 GLboolean fallback = !r200_validate_texgen( ctx, unit );
1731 TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
1732 rmesa->recheck_texgen[unit] = 0;
1733 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1734 }
1735
1736 FALLBACK( rmesa, R200_FALLBACK_BORDER_MODE, t->border_fallback );
1737 return !t->border_fallback;
1738 }
1739
1740
1741
1742 static GLboolean r200UpdateTextureUnit( GLcontext *ctx, int unit )
1743 {
1744 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1745 GLuint unitneeded = rmesa->state.texture.unit[unit].unitneeded;
1746
1747 if ( unitneeded & (TEXTURE_RECT_BIT) ) {
1748 return (enable_tex_rect( ctx, unit ) &&
1749 update_tex_common( ctx, unit ));
1750 }
1751 else if ( unitneeded & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
1752 return (enable_tex_2d( ctx, unit ) &&
1753 update_tex_common( ctx, unit ));
1754 }
1755 #if ENABLE_HW_3D_TEXTURE
1756 else if ( unitneeded & (TEXTURE_3D_BIT) ) {
1757 return (enable_tex_3d( ctx, unit ) &&
1758 update_tex_common( ctx, unit ));
1759 }
1760 #endif
1761 else if ( unitneeded & (TEXTURE_CUBE_BIT) ) {
1762 return (enable_tex_cube( ctx, unit ) &&
1763 update_tex_common( ctx, unit ));
1764 }
1765 else if ( unitneeded ) {
1766 return GL_FALSE;
1767 }
1768 else {
1769 disable_tex( ctx, unit );
1770 return GL_TRUE;
1771 }
1772 }
1773
1774
1775 void r200UpdateTextureState( GLcontext *ctx )
1776 {
1777 r200ContextPtr rmesa = R200_CONTEXT(ctx);
1778 GLboolean ok;
1779 GLuint dbg;
1780
1781 if (ctx->ATIFragmentShader._Enabled) {
1782 GLuint i;
1783 for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) {
1784 rmesa->state.texture.unit[i].unitneeded = ctx->Texture.Unit[i]._ReallyEnabled;
1785 }
1786 ok = GL_TRUE;
1787 }
1788 else {
1789 ok = r200UpdateAllTexEnv( ctx );
1790 }
1791 if (ok) {
1792 ok = (r200UpdateTextureUnit( ctx, 0 ) &&
1793 r200UpdateTextureUnit( ctx, 1 ) &&
1794 r200UpdateTextureUnit( ctx, 2 ) &&
1795 r200UpdateTextureUnit( ctx, 3 ) &&
1796 r200UpdateTextureUnit( ctx, 4 ) &&
1797 r200UpdateTextureUnit( ctx, 5 ));
1798 }
1799
1800 if (ok && ctx->ATIFragmentShader._Enabled) {
1801 r200UpdateFragmentShader(ctx);
1802 }
1803
1804 FALLBACK( rmesa, R200_FALLBACK_TEXTURE, !ok );
1805
1806 if (rmesa->TclFallback)
1807 r200ChooseVertexState( ctx );
1808
1809
1810 if (rmesa->r200Screen->chip_family == CHIP_FAMILY_R200) {
1811
1812 /*
1813 * T0 hang workaround -------------
1814 * not needed for r200 derivatives
1815 */
1816 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_ENABLE_MASK) == R200_TEX_0_ENABLE &&
1817 (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) {
1818
1819 R200_STATECHANGE(rmesa, ctx);
1820 R200_STATECHANGE(rmesa, tex[1]);
1821 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_1_ENABLE;
1822 if (!(rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_1_ENABLE))
1823 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1824 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] |= R200_TXFORMAT_LOOKUP_DISABLE;
1825 }
1826 else if (!ctx->ATIFragmentShader._Enabled) {
1827 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE) &&
1828 (rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] & R200_TXFORMAT_LOOKUP_DISABLE)) {
1829 R200_STATECHANGE(rmesa, tex[1]);
1830 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~R200_TXFORMAT_LOOKUP_DISABLE;
1831 }
1832 }
1833 /* do the same workaround for the first pass of a fragment shader.
1834 * completely unknown if necessary / sufficient.
1835 */
1836 if ((rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_ENABLE_MASK) == R200_PPX_TEX_0_ENABLE &&
1837 (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) {
1838
1839 R200_STATECHANGE(rmesa, cst);
1840 R200_STATECHANGE(rmesa, tex[1]);
1841 rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_1_ENABLE;
1842 if (!(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE))
1843 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1844 rmesa->hw.tex[1].cmd[TEX_PP_TXMULTI_CTL] |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE;
1845 }
1846
1847 /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1848 looks like that's not the case, if 8500/9100 owners don't complain remove this...
1849 for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1850 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1851 R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1852 ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1853 R200_MIN_FILTER_LINEAR)) {
1854 R200_STATECHANGE(rmesa, ctx);
1855 R200_STATECHANGE(rmesa, tex[i+1]);
1856 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1857 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1858 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1859 }
1860 else {
1861 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1862 (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1863 R200_STATECHANGE(rmesa, tex[i+1]);
1864 rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1865 }
1866 }
1867 } */
1868
1869 /*
1870 * Texture cache LRU hang workaround -------------
1871 * not needed for r200 derivatives
1872 * hopefully this covers first pass of a shader as well
1873 */
1874
1875 /* While the cases below attempt to only enable the workaround in the
1876 * specific cases necessary, they were insufficient. See bugzilla #1519,
1877 * #729, #814. Tests with quake3 showed no impact on performance.
1878 */
1879 dbg = 0x6;
1880
1881 /*
1882 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) &&
1883 ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1884 0x04) == 0)) ||
1885 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1886 ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1887 0x04) == 0)) ||
1888 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1889 ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1890 0x04) == 0)))
1891 {
1892 dbg |= 0x02;
1893 }
1894
1895 if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) &&
1896 ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1897 0x04) == 0)) ||
1898 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1899 ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1900 0x04) == 0)) ||
1901 ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1902 ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1903 0x04) == 0)))
1904 {
1905 dbg |= 0x04;
1906 }*/
1907
1908 if (dbg != rmesa->hw.tam.cmd[TAM_DEBUG3]) {
1909 R200_STATECHANGE( rmesa, tam );
1910 rmesa->hw.tam.cmd[TAM_DEBUG3] = dbg;
1911 if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg);
1912 }
1913 }
1914 }