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