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