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