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