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