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