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