add support for GL_ARB_texture_env_crossbar
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_texstate.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c,v 1.6 2002/12/16 16:18:59 dawes Exp $ */
2 /**************************************************************************
3
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5 VA Linux Systems Inc., Fremont, California.
6
7 All Rights Reserved.
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 * Kevin E. Martin <martin@valinux.com>
34 * Gareth Hughes <gareth@valinux.com>
35 */
36
37 #include "glheader.h"
38 #include "imports.h"
39 #include "colormac.h"
40 #include "context.h"
41 #include "macros.h"
42 #include "texformat.h"
43 #include "enums.h"
44
45 #include "radeon_context.h"
46 #include "radeon_state.h"
47 #include "radeon_ioctl.h"
48 #include "radeon_swtcl.h"
49 #include "radeon_tex.h"
50 #include "radeon_tcl.h"
51
52
53 #define RADEON_TXFORMAT_AL88 RADEON_TXFORMAT_AI88
54 #define RADEON_TXFORMAT_YCBCR RADEON_TXFORMAT_YVYU422
55 #define RADEON_TXFORMAT_YCBCR_REV RADEON_TXFORMAT_VYUY422
56
57 #define _COLOR(f) \
58 [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, 0 }
59 #define _ALPHA(f) \
60 [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f | RADEON_TXFORMAT_ALPHA_IN_MAP, 0 }
61 #define _YUV(f) \
62 [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, RADEON_YUV_TO_RGB }
63 #define _INVALID(f) \
64 [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
65 #define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_YCBCR_REV) \
66 && (tx_table[f].format != 0xffffffff) )
67
68 static const struct {
69 GLuint format, filter;
70 }
71 tx_table[] =
72 {
73 _ALPHA(RGBA8888),
74 _ALPHA(ARGB8888),
75 _INVALID(RGB888),
76 _COLOR(RGB565),
77 _ALPHA(ARGB4444),
78 _ALPHA(ARGB1555),
79 _ALPHA(AL88),
80 _INVALID(A8),
81 _INVALID(L8),
82 _COLOR(I8),
83 _INVALID(CI8),
84 _YUV(YCBCR),
85 _YUV(YCBCR_REV),
86 };
87
88 #undef _COLOR
89 #undef _ALPHA
90 #undef _INVALID
91
92 /**
93 * This function computes the number of bytes of storage needed for
94 * the given texture object (all mipmap levels, all cube faces).
95 * The \c image[face][level].x/y/width/height parameters for upload/blitting
96 * are computed here. \c pp_txfilter, \c pp_txformat, etc. will be set here
97 * too.
98 *
99 * \param rmesa Context pointer
100 * \param tObj GL texture object whose images are to be posted to
101 * hardware state.
102 */
103 static void radeonSetTexImages( radeonContextPtr rmesa,
104 struct gl_texture_object *tObj )
105 {
106 radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData;
107 const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
108 GLint curOffset;
109 GLint i;
110 GLint numLevels;
111 GLint log2Width, log2Height, log2Depth;
112
113 /* Set the hardware texture format
114 */
115
116 t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK |
117 RADEON_TXFORMAT_ALPHA_IN_MAP);
118 t->pp_txfilter &= ~RADEON_YUV_TO_RGB;
119
120 if ( VALID_FORMAT( baseImage->TexFormat->MesaFormat ) ) {
121 t->pp_txformat |= tx_table[ baseImage->TexFormat->MesaFormat ].format;
122 t->pp_txfilter |= tx_table[ baseImage->TexFormat->MesaFormat ].filter;
123 }
124 else {
125 _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
126 return;
127 }
128
129
130 /* Compute which mipmap levels we really want to send to the hardware.
131 */
132
133 driCalculateTextureFirstLastLevel( (driTextureObject *) t );
134 log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2;
135 log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
136 log2Depth = tObj->Image[0][t->base.firstLevel]->DepthLog2;
137
138 numLevels = t->base.lastLevel - t->base.firstLevel + 1;
139
140 assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
141
142 /* Calculate mipmap offsets and dimensions for blitting (uploading)
143 * The idea is that we lay out the mipmap levels within a block of
144 * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
145 */
146 curOffset = 0;
147
148 for (i = 0; i < numLevels; i++) {
149 const struct gl_texture_image *texImage;
150 GLuint size;
151
152 texImage = tObj->Image[0][i + t->base.firstLevel];
153 if ( !texImage )
154 break;
155
156 /* find image size in bytes */
157 if (texImage->IsCompressed) {
158 size = texImage->CompressedSize;
159 }
160 else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
161 size = ((texImage->Width * texImage->TexFormat->TexelBytes + 63)
162 & ~63) * texImage->Height;
163 }
164 else {
165 int w = texImage->Width * texImage->TexFormat->TexelBytes;
166 if (w < 32)
167 w = 32;
168 size = w * texImage->Height * texImage->Depth;
169 }
170 assert(size > 0);
171
172
173 /* Align to 32-byte offset. It is faster to do this unconditionally
174 * (no branch penalty).
175 */
176
177 curOffset = (curOffset + 0x1f) & ~0x1f;
178
179 t->image[0][i].x = curOffset % BLIT_WIDTH_BYTES;
180 t->image[0][i].y = curOffset / BLIT_WIDTH_BYTES;
181 t->image[0][i].width = MIN2(size, BLIT_WIDTH_BYTES);
182 t->image[0][i].height = size / t->image[0][i].width;
183
184 #if 0
185 /* for debugging only and only applicable to non-rectangle targets */
186 assert(size % t->image[0][i].width == 0);
187 assert(t->image[0][i].x == 0
188 || (size < BLIT_WIDTH_BYTES && t->image[0][i].height == 1));
189 #endif
190
191 if (0)
192 fprintf(stderr,
193 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
194 i, texImage->Width, texImage->Height,
195 t->image[0][i].x, t->image[0][i].y,
196 t->image[0][i].width, t->image[0][i].height, size, curOffset);
197
198 curOffset += size;
199
200 }
201
202 /* Align the total size of texture memory block.
203 */
204 t->base.totalSize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
205
206 /* Hardware state:
207 */
208 t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK;
209 t->pp_txfilter |= (numLevels - 1) << RADEON_MAX_MIP_LEVEL_SHIFT;
210
211 t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK |
212 RADEON_TXFORMAT_HEIGHT_MASK |
213 RADEON_TXFORMAT_CUBIC_MAP_ENABLE);
214 t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) |
215 (log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT));
216
217 t->pp_txsize = (((tObj->Image[0][t->base.firstLevel]->Width - 1) << 0) |
218 ((tObj->Image[0][t->base.firstLevel]->Height - 1) << 16));
219
220 /* Only need to round to nearest 32 for textures, but the blitter
221 * requires 64-byte aligned pitches, and we may/may not need the
222 * blitter. NPOT only!
223 */
224 if (baseImage->IsCompressed)
225 t->pp_txpitch = (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63);
226 else
227 t->pp_txpitch = ((tObj->Image[0][t->base.firstLevel]->Width * baseImage->TexFormat->TexelBytes) + 63) & ~(63);
228 t->pp_txpitch -= 32;
229
230 t->dirty_state = TEX_ALL;
231
232 /* FYI: radeonUploadTexImages( rmesa, t ); used to be called here */
233 }
234
235
236
237 /* ================================================================
238 * Texture combine functions
239 */
240
241 /* GL_ARB_texture_env_combine support
242 */
243
244 /* The color tables have combine functions for GL_SRC_COLOR,
245 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
246 */
247 static GLuint radeon_texture_color[][RADEON_MAX_TEXTURE_UNITS] =
248 {
249 {
250 RADEON_COLOR_ARG_A_T0_COLOR,
251 RADEON_COLOR_ARG_A_T1_COLOR,
252 RADEON_COLOR_ARG_A_T2_COLOR
253 },
254 {
255 RADEON_COLOR_ARG_A_T0_COLOR | RADEON_COMP_ARG_A,
256 RADEON_COLOR_ARG_A_T1_COLOR | RADEON_COMP_ARG_A,
257 RADEON_COLOR_ARG_A_T2_COLOR | RADEON_COMP_ARG_A
258 },
259 {
260 RADEON_COLOR_ARG_A_T0_ALPHA,
261 RADEON_COLOR_ARG_A_T1_ALPHA,
262 RADEON_COLOR_ARG_A_T2_ALPHA
263 },
264 {
265 RADEON_COLOR_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A,
266 RADEON_COLOR_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A,
267 RADEON_COLOR_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A
268 },
269 };
270
271 static GLuint radeon_tfactor_color[] =
272 {
273 RADEON_COLOR_ARG_A_TFACTOR_COLOR,
274 RADEON_COLOR_ARG_A_TFACTOR_COLOR | RADEON_COMP_ARG_A,
275 RADEON_COLOR_ARG_A_TFACTOR_ALPHA,
276 RADEON_COLOR_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A
277 };
278
279 static GLuint radeon_primary_color[] =
280 {
281 RADEON_COLOR_ARG_A_DIFFUSE_COLOR,
282 RADEON_COLOR_ARG_A_DIFFUSE_COLOR | RADEON_COMP_ARG_A,
283 RADEON_COLOR_ARG_A_DIFFUSE_ALPHA,
284 RADEON_COLOR_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A
285 };
286
287 static GLuint radeon_previous_color[] =
288 {
289 RADEON_COLOR_ARG_A_CURRENT_COLOR,
290 RADEON_COLOR_ARG_A_CURRENT_COLOR | RADEON_COMP_ARG_A,
291 RADEON_COLOR_ARG_A_CURRENT_ALPHA,
292 RADEON_COLOR_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A
293 };
294
295 /* GL_ZERO table - indices 0-3
296 * GL_ONE table - indices 1-4
297 */
298 static GLuint radeon_zero_color[] =
299 {
300 RADEON_COLOR_ARG_A_ZERO,
301 RADEON_COLOR_ARG_A_ZERO | RADEON_COMP_ARG_A,
302 RADEON_COLOR_ARG_A_ZERO,
303 RADEON_COLOR_ARG_A_ZERO | RADEON_COMP_ARG_A,
304 RADEON_COLOR_ARG_A_ZERO
305 };
306
307
308 /* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
309 */
310 static GLuint radeon_texture_alpha[][RADEON_MAX_TEXTURE_UNITS] =
311 {
312 {
313 RADEON_ALPHA_ARG_A_T0_ALPHA,
314 RADEON_ALPHA_ARG_A_T1_ALPHA,
315 RADEON_ALPHA_ARG_A_T2_ALPHA
316 },
317 {
318 RADEON_ALPHA_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A,
319 RADEON_ALPHA_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A,
320 RADEON_ALPHA_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A
321 },
322 };
323
324 static GLuint radeon_tfactor_alpha[] =
325 {
326 RADEON_ALPHA_ARG_A_TFACTOR_ALPHA,
327 RADEON_ALPHA_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A
328 };
329
330 static GLuint radeon_primary_alpha[] =
331 {
332 RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA,
333 RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A
334 };
335
336 static GLuint radeon_previous_alpha[] =
337 {
338 RADEON_ALPHA_ARG_A_CURRENT_ALPHA,
339 RADEON_ALPHA_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A
340 };
341
342 /* GL_ZERO table - indices 0-1
343 * GL_ONE table - indices 1-2
344 */
345 static GLuint radeon_zero_alpha[] =
346 {
347 RADEON_ALPHA_ARG_A_ZERO,
348 RADEON_ALPHA_ARG_A_ZERO | RADEON_COMP_ARG_A,
349 RADEON_ALPHA_ARG_A_ZERO
350 };
351
352
353 /* Extract the arg from slot A, shift it into the correct argument slot
354 * and set the corresponding complement bit.
355 */
356 #define RADEON_COLOR_ARG( n, arg ) \
357 do { \
358 color_combine |= \
359 ((color_arg[n] & RADEON_COLOR_ARG_MASK) \
360 << RADEON_COLOR_ARG_##arg##_SHIFT); \
361 color_combine |= \
362 ((color_arg[n] >> RADEON_COMP_ARG_SHIFT) \
363 << RADEON_COMP_ARG_##arg##_SHIFT); \
364 } while (0)
365
366 #define RADEON_ALPHA_ARG( n, arg ) \
367 do { \
368 alpha_combine |= \
369 ((alpha_arg[n] & RADEON_ALPHA_ARG_MASK) \
370 << RADEON_ALPHA_ARG_##arg##_SHIFT); \
371 alpha_combine |= \
372 ((alpha_arg[n] >> RADEON_COMP_ARG_SHIFT) \
373 << RADEON_COMP_ARG_##arg##_SHIFT); \
374 } while (0)
375
376
377 /* ================================================================
378 * Texture unit state management
379 */
380
381 static GLboolean radeonUpdateTextureEnv( GLcontext *ctx, int unit )
382 {
383 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
384 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
385 GLuint color_combine, alpha_combine;
386 const GLuint color_combine0 = RADEON_COLOR_ARG_A_ZERO | RADEON_COLOR_ARG_B_ZERO
387 | RADEON_COLOR_ARG_C_CURRENT_COLOR | RADEON_BLEND_CTL_ADD
388 | RADEON_SCALE_1X | RADEON_CLAMP_TX;
389 const GLuint alpha_combine0 = RADEON_ALPHA_ARG_A_ZERO | RADEON_ALPHA_ARG_B_ZERO
390 | RADEON_ALPHA_ARG_C_CURRENT_ALPHA | RADEON_BLEND_CTL_ADD
391 | RADEON_SCALE_1X | RADEON_CLAMP_TX;
392
393
394 /* texUnit->_Current can be NULL if and only if the texture unit is
395 * not actually enabled.
396 */
397 assert( (texUnit->_ReallyEnabled == 0)
398 || (texUnit->_Current != NULL) );
399
400 if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
401 fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, (void *)ctx, unit );
402 }
403
404 /* Set the texture environment state. Isn't this nice and clean?
405 * The chip will automagically set the texture alpha to 0xff when
406 * the texture format does not include an alpha component. This
407 * reduces the amount of special-casing we have to do, alpha-only
408 * textures being a notable exception.
409 */
410 /* Don't cache these results.
411 */
412 rmesa->state.texture.unit[unit].format = 0;
413 rmesa->state.texture.unit[unit].envMode = 0;
414
415 if ( !texUnit->_ReallyEnabled ) {
416 color_combine = color_combine0;
417 alpha_combine = alpha_combine0;
418 }
419 else {
420 GLuint color_arg[3], alpha_arg[3];
421 GLuint i;
422 const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
423 const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
424 GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB;
425 GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA;
426
427
428 /* Step 1:
429 * Extract the color and alpha combine function arguments.
430 */
431 for ( i = 0 ; i < numColorArgs ; i++ ) {
432 const GLuint op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR;
433 const GLuint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i];
434 assert(op >= 0);
435 assert(op <= 3);
436 switch ( srcRGBi ) {
437 case GL_TEXTURE:
438 color_arg[i] = radeon_texture_color[op][unit];
439 break;
440 case GL_CONSTANT:
441 color_arg[i] = radeon_tfactor_color[op];
442 break;
443 case GL_PRIMARY_COLOR:
444 color_arg[i] = radeon_primary_color[op];
445 break;
446 case GL_PREVIOUS:
447 color_arg[i] = radeon_previous_color[op];
448 break;
449 case GL_ZERO:
450 color_arg[i] = radeon_zero_color[op];
451 break;
452 case GL_ONE:
453 color_arg[i] = radeon_zero_color[op+1];
454 break;
455 case GL_TEXTURE0:
456 case GL_TEXTURE1:
457 case GL_TEXTURE2:
458 if (ctx->Texture.Unit[srcRGBi - GL_TEXTURE0]._ReallyEnabled)
459 color_arg[i] = radeon_texture_color[op][srcRGBi - GL_TEXTURE0];
460 else {
461 color_combine = color_combine0;
462 alpha_combine = alpha_combine0;
463 goto write_txblend;
464 }
465 break;
466 default:
467 return GL_FALSE;
468 }
469 }
470
471 for ( i = 0 ; i < numAlphaArgs ; i++ ) {
472 const GLuint op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA;
473 const GLuint srcAi = texUnit->_CurrentCombine->SourceA[i];
474 assert(op >= 0);
475 assert(op <= 1);
476 switch ( srcAi ) {
477 case GL_TEXTURE:
478 alpha_arg[i] = radeon_texture_alpha[op][unit];
479 break;
480 case GL_CONSTANT:
481 alpha_arg[i] = radeon_tfactor_alpha[op];
482 break;
483 case GL_PRIMARY_COLOR:
484 alpha_arg[i] = radeon_primary_alpha[op];
485 break;
486 case GL_PREVIOUS:
487 alpha_arg[i] = radeon_previous_alpha[op];
488 break;
489 case GL_ZERO:
490 alpha_arg[i] = radeon_zero_alpha[op];
491 break;
492 case GL_ONE:
493 alpha_arg[i] = radeon_zero_alpha[op+1];
494 break;
495 case GL_TEXTURE0:
496 case GL_TEXTURE1:
497 case GL_TEXTURE2:
498 if (ctx->Texture.Unit[srcAi - GL_TEXTURE0]._ReallyEnabled)
499 alpha_arg[i] = radeon_texture_alpha[op][srcAi - GL_TEXTURE0];
500 else {
501 color_combine = color_combine0;
502 alpha_combine = alpha_combine0;
503 goto write_txblend;
504 }
505 break;
506 default:
507 return GL_FALSE;
508 }
509 }
510
511 /* Step 2:
512 * Build up the color and alpha combine functions.
513 */
514 switch ( texUnit->_CurrentCombine->ModeRGB ) {
515 case GL_REPLACE:
516 color_combine = (RADEON_COLOR_ARG_A_ZERO |
517 RADEON_COLOR_ARG_B_ZERO |
518 RADEON_BLEND_CTL_ADD |
519 RADEON_CLAMP_TX);
520 RADEON_COLOR_ARG( 0, C );
521 break;
522 case GL_MODULATE:
523 color_combine = (RADEON_COLOR_ARG_C_ZERO |
524 RADEON_BLEND_CTL_ADD |
525 RADEON_CLAMP_TX);
526 RADEON_COLOR_ARG( 0, A );
527 RADEON_COLOR_ARG( 1, B );
528 break;
529 case GL_ADD:
530 color_combine = (RADEON_COLOR_ARG_B_ZERO |
531 RADEON_COMP_ARG_B |
532 RADEON_BLEND_CTL_ADD |
533 RADEON_CLAMP_TX);
534 RADEON_COLOR_ARG( 0, A );
535 RADEON_COLOR_ARG( 1, C );
536 break;
537 case GL_ADD_SIGNED:
538 color_combine = (RADEON_COLOR_ARG_B_ZERO |
539 RADEON_COMP_ARG_B |
540 RADEON_BLEND_CTL_ADDSIGNED |
541 RADEON_CLAMP_TX);
542 RADEON_COLOR_ARG( 0, A );
543 RADEON_COLOR_ARG( 1, C );
544 break;
545 case GL_SUBTRACT:
546 color_combine = (RADEON_COLOR_ARG_B_ZERO |
547 RADEON_COMP_ARG_B |
548 RADEON_BLEND_CTL_SUBTRACT |
549 RADEON_CLAMP_TX);
550 RADEON_COLOR_ARG( 0, A );
551 RADEON_COLOR_ARG( 1, C );
552 break;
553 case GL_INTERPOLATE:
554 color_combine = (RADEON_BLEND_CTL_BLEND |
555 RADEON_CLAMP_TX);
556 RADEON_COLOR_ARG( 0, B );
557 RADEON_COLOR_ARG( 1, A );
558 RADEON_COLOR_ARG( 2, C );
559 break;
560
561 case GL_DOT3_RGB_EXT:
562 case GL_DOT3_RGBA_EXT:
563 /* The EXT version of the DOT3 extension does not support the
564 * scale factor, but the ARB version (and the version in OpenGL
565 * 1.3) does.
566 */
567 RGBshift = 0;
568 Ashift = 0;
569 /* FALLTHROUGH */
570
571 case GL_DOT3_RGB:
572 case GL_DOT3_RGBA:
573 /* The R100 / RV200 only support a 1X multiplier in hardware
574 * w/the ARB version.
575 */
576 if ( RGBshift != (RADEON_SCALE_1X >> RADEON_SCALE_SHIFT) ) {
577 return GL_FALSE;
578 }
579
580 RGBshift += 2;
581 Ashift = RGBshift;
582
583 color_combine = (RADEON_COLOR_ARG_C_ZERO |
584 RADEON_BLEND_CTL_DOT3 |
585 RADEON_CLAMP_TX);
586 RADEON_COLOR_ARG( 0, A );
587 RADEON_COLOR_ARG( 1, B );
588 break;
589
590 case GL_MODULATE_ADD_ATI:
591 color_combine = (RADEON_BLEND_CTL_ADD |
592 RADEON_CLAMP_TX);
593 RADEON_COLOR_ARG( 0, A );
594 RADEON_COLOR_ARG( 1, C );
595 RADEON_COLOR_ARG( 2, B );
596 break;
597 case GL_MODULATE_SIGNED_ADD_ATI:
598 color_combine = (RADEON_BLEND_CTL_ADDSIGNED |
599 RADEON_CLAMP_TX);
600 RADEON_COLOR_ARG( 0, A );
601 RADEON_COLOR_ARG( 1, C );
602 RADEON_COLOR_ARG( 2, B );
603 break;
604 case GL_MODULATE_SUBTRACT_ATI:
605 color_combine = (RADEON_BLEND_CTL_SUBTRACT |
606 RADEON_CLAMP_TX);
607 RADEON_COLOR_ARG( 0, A );
608 RADEON_COLOR_ARG( 1, C );
609 RADEON_COLOR_ARG( 2, B );
610 break;
611 default:
612 return GL_FALSE;
613 }
614
615 switch ( texUnit->_CurrentCombine->ModeA ) {
616 case GL_REPLACE:
617 alpha_combine = (RADEON_ALPHA_ARG_A_ZERO |
618 RADEON_ALPHA_ARG_B_ZERO |
619 RADEON_BLEND_CTL_ADD |
620 RADEON_CLAMP_TX);
621 RADEON_ALPHA_ARG( 0, C );
622 break;
623 case GL_MODULATE:
624 alpha_combine = (RADEON_ALPHA_ARG_C_ZERO |
625 RADEON_BLEND_CTL_ADD |
626 RADEON_CLAMP_TX);
627 RADEON_ALPHA_ARG( 0, A );
628 RADEON_ALPHA_ARG( 1, B );
629 break;
630 case GL_ADD:
631 alpha_combine = (RADEON_ALPHA_ARG_B_ZERO |
632 RADEON_COMP_ARG_B |
633 RADEON_BLEND_CTL_ADD |
634 RADEON_CLAMP_TX);
635 RADEON_ALPHA_ARG( 0, A );
636 RADEON_ALPHA_ARG( 1, C );
637 break;
638 case GL_ADD_SIGNED:
639 alpha_combine = (RADEON_ALPHA_ARG_B_ZERO |
640 RADEON_COMP_ARG_B |
641 RADEON_BLEND_CTL_ADDSIGNED |
642 RADEON_CLAMP_TX);
643 RADEON_ALPHA_ARG( 0, A );
644 RADEON_ALPHA_ARG( 1, C );
645 break;
646 case GL_SUBTRACT:
647 alpha_combine = (RADEON_COLOR_ARG_B_ZERO |
648 RADEON_COMP_ARG_B |
649 RADEON_BLEND_CTL_SUBTRACT |
650 RADEON_CLAMP_TX);
651 RADEON_ALPHA_ARG( 0, A );
652 RADEON_ALPHA_ARG( 1, C );
653 break;
654 case GL_INTERPOLATE:
655 alpha_combine = (RADEON_BLEND_CTL_BLEND |
656 RADEON_CLAMP_TX);
657 RADEON_ALPHA_ARG( 0, B );
658 RADEON_ALPHA_ARG( 1, A );
659 RADEON_ALPHA_ARG( 2, C );
660 break;
661
662 case GL_MODULATE_ADD_ATI:
663 alpha_combine = (RADEON_BLEND_CTL_ADD |
664 RADEON_CLAMP_TX);
665 RADEON_ALPHA_ARG( 0, A );
666 RADEON_ALPHA_ARG( 1, C );
667 RADEON_ALPHA_ARG( 2, B );
668 break;
669 case GL_MODULATE_SIGNED_ADD_ATI:
670 alpha_combine = (RADEON_BLEND_CTL_ADDSIGNED |
671 RADEON_CLAMP_TX);
672 RADEON_ALPHA_ARG( 0, A );
673 RADEON_ALPHA_ARG( 1, C );
674 RADEON_ALPHA_ARG( 2, B );
675 break;
676 case GL_MODULATE_SUBTRACT_ATI:
677 alpha_combine = (RADEON_BLEND_CTL_SUBTRACT |
678 RADEON_CLAMP_TX);
679 RADEON_ALPHA_ARG( 0, A );
680 RADEON_ALPHA_ARG( 1, C );
681 RADEON_ALPHA_ARG( 2, B );
682 break;
683 default:
684 return GL_FALSE;
685 }
686
687 if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGB_EXT)
688 || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGB) ) {
689 alpha_combine |= RADEON_DOT_ALPHA_DONT_REPLICATE;
690 }
691
692 /* Step 3:
693 * Apply the scale factor.
694 */
695 color_combine |= (RGBshift << RADEON_SCALE_SHIFT);
696 alpha_combine |= (Ashift << RADEON_SCALE_SHIFT);
697
698 /* All done!
699 */
700 }
701
702 write_txblend:
703 if ( rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] != color_combine ||
704 rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] != alpha_combine ) {
705 RADEON_STATECHANGE( rmesa, tex[unit] );
706 rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] = color_combine;
707 rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] = alpha_combine;
708 }
709
710 return GL_TRUE;
711 }
712
713 #define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK | \
714 RADEON_MIN_FILTER_MASK | \
715 RADEON_MAG_FILTER_MASK | \
716 RADEON_MAX_ANISO_MASK | \
717 RADEON_YUV_TO_RGB | \
718 RADEON_YUV_TEMPERATURE_MASK | \
719 RADEON_CLAMP_S_MASK | \
720 RADEON_CLAMP_T_MASK | \
721 RADEON_BORDER_MODE_D3D )
722
723 #define TEXOBJ_TXFORMAT_MASK (RADEON_TXFORMAT_WIDTH_MASK | \
724 RADEON_TXFORMAT_HEIGHT_MASK | \
725 RADEON_TXFORMAT_FORMAT_MASK | \
726 RADEON_TXFORMAT_F5_WIDTH_MASK | \
727 RADEON_TXFORMAT_F5_HEIGHT_MASK | \
728 RADEON_TXFORMAT_ALPHA_IN_MAP | \
729 RADEON_TXFORMAT_CUBIC_MAP_ENABLE | \
730 RADEON_TXFORMAT_NON_POWER2)
731
732
733 static void import_tex_obj_state( radeonContextPtr rmesa,
734 int unit,
735 radeonTexObjPtr texobj )
736 {
737 GLuint *cmd = RADEON_DB_STATE( tex[unit] );
738
739 cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
740 cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK;
741 cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
742 cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
743 cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset;
744 cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
745 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tex[unit] );
746
747 if (texobj->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
748 GLuint *txr_cmd = RADEON_DB_STATE( txr[unit] );
749 txr_cmd[TXR_PP_TEX_SIZE] = texobj->pp_txsize; /* NPOT only! */
750 txr_cmd[TXR_PP_TEX_PITCH] = texobj->pp_txpitch; /* NPOT only! */
751 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.txr[unit] );
752 }
753
754 texobj->dirty_state &= ~(1<<unit);
755 }
756
757
758
759
760 static void set_texgen_matrix( radeonContextPtr rmesa,
761 GLuint unit,
762 const GLfloat *s_plane,
763 const GLfloat *t_plane )
764 {
765 static const GLfloat scale_identity[4] = { 1,1,1,1 };
766
767 if (!TEST_EQ_4V( s_plane, scale_identity) ||
768 !TEST_EQ_4V( t_plane, scale_identity)) {
769 rmesa->TexGenEnabled |= RADEON_TEXMAT_0_ENABLE<<unit;
770 rmesa->TexGenMatrix[unit].m[0] = s_plane[0];
771 rmesa->TexGenMatrix[unit].m[4] = s_plane[1];
772 rmesa->TexGenMatrix[unit].m[8] = s_plane[2];
773 rmesa->TexGenMatrix[unit].m[12] = s_plane[3];
774
775 rmesa->TexGenMatrix[unit].m[1] = t_plane[0];
776 rmesa->TexGenMatrix[unit].m[5] = t_plane[1];
777 rmesa->TexGenMatrix[unit].m[9] = t_plane[2];
778 rmesa->TexGenMatrix[unit].m[13] = t_plane[3];
779 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
780 }
781 }
782
783 /* Ignoring the Q texcoord for now.
784 *
785 * Returns GL_FALSE if fallback required.
786 */
787 static GLboolean radeon_validate_texgen( GLcontext *ctx, GLuint unit )
788 {
789 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
790 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
791 GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
792 GLuint tmp = rmesa->TexGenEnabled;
793
794 rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit);
795 rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit);
796 rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift);
797 rmesa->TexGenNeedNormals[unit] = 0;
798
799 if ((texUnit->TexGenEnabled & (S_BIT|T_BIT)) == 0) {
800 /* Disabled, no fallback:
801 */
802 rmesa->TexGenEnabled |=
803 (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
804 return GL_TRUE;
805 }
806 else if (texUnit->TexGenEnabled & Q_BIT) {
807 /* Very easy to do this, in fact would remove a fallback case
808 * elsewhere, but I haven't done it yet... Fallback:
809 */
810 fprintf(stderr, "fallback Q_BIT\n");
811 return GL_FALSE;
812 }
813 else if ((texUnit->TexGenEnabled & (S_BIT|T_BIT)) != (S_BIT|T_BIT) ||
814 texUnit->GenModeS != texUnit->GenModeT) {
815 /* Mixed modes, fallback:
816 */
817 /* fprintf(stderr, "fallback mixed texgen\n"); */
818 return GL_FALSE;
819 }
820 else
821 rmesa->TexGenEnabled |= RADEON_TEXGEN_TEXMAT_0_ENABLE << unit;
822
823 switch (texUnit->GenModeS) {
824 case GL_OBJECT_LINEAR:
825 rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_OBJ << inputshift;
826 set_texgen_matrix( rmesa, unit,
827 texUnit->ObjectPlaneS,
828 texUnit->ObjectPlaneT);
829 break;
830
831 case GL_EYE_LINEAR:
832 rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE << inputshift;
833 set_texgen_matrix( rmesa, unit,
834 texUnit->EyePlaneS,
835 texUnit->EyePlaneT);
836 break;
837
838 case GL_REFLECTION_MAP_NV:
839 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
840 rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_REFLECT<<inputshift;
841 break;
842
843 case GL_NORMAL_MAP_NV:
844 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
845 rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_NORMAL<<inputshift;
846 break;
847
848 case GL_SPHERE_MAP:
849 default:
850 /* Unsupported mode, fallback:
851 */
852 /* fprintf(stderr, "fallback unsupported texgen\n"); */
853 return GL_FALSE;
854 }
855
856 if (tmp != rmesa->TexGenEnabled) {
857 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
858 }
859
860 return GL_TRUE;
861 }
862
863
864 static void disable_tex( GLcontext *ctx, int unit )
865 {
866 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
867
868 if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit)) {
869 /* Texture unit disabled */
870 if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
871 /* The old texture is no longer bound to this texture unit.
872 * Mark it as such.
873 */
874
875 rmesa->state.texture.unit[unit].texobj->base.bound &= ~(1UL << unit);
876 rmesa->state.texture.unit[unit].texobj = NULL;
877 }
878
879 RADEON_STATECHANGE( rmesa, ctx );
880 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &=
881 ~((RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit);
882
883 RADEON_STATECHANGE( rmesa, tcl );
884 switch (unit) {
885 case 0:
886 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST0 |
887 RADEON_TCL_VTX_Q0);
888 break;
889 case 1:
890 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST1 |
891 RADEON_TCL_VTX_Q1);
892 break;
893 default:
894 break;
895 }
896
897
898 if (rmesa->TclFallback & (RADEON_TCL_FALLBACK_TEXGEN_0<<unit)) {
899 TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
900 rmesa->recheck_texgen[unit] = GL_TRUE;
901 }
902
903
904
905 {
906 GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
907 GLuint tmp = rmesa->TexGenEnabled;
908
909 rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit);
910 rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit);
911 rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift);
912 rmesa->TexGenNeedNormals[unit] = 0;
913 rmesa->TexGenEnabled |=
914 (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
915
916 if (tmp != rmesa->TexGenEnabled) {
917 rmesa->recheck_texgen[unit] = GL_TRUE;
918 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
919 }
920 }
921 }
922 }
923
924 static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
925 {
926 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
927 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
928 struct gl_texture_object *tObj = texUnit->_Current;
929 radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
930
931 /* Need to load the 2d images associated with this unit.
932 */
933 if (t->pp_txformat & RADEON_TXFORMAT_NON_POWER2) {
934 t->pp_txformat &= ~RADEON_TXFORMAT_NON_POWER2;
935 t->base.dirty_images[0] = ~0;
936 }
937
938 ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
939
940 if ( t->base.dirty_images[0] ) {
941 RADEON_FIREVERTICES( rmesa );
942 radeonSetTexImages( rmesa, tObj );
943 radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 );
944 if ( !t->base.memBlock )
945 return GL_FALSE;
946 }
947
948 return GL_TRUE;
949 }
950
951 static GLboolean enable_tex_rect( GLcontext *ctx, int unit )
952 {
953 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
954 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
955 struct gl_texture_object *tObj = texUnit->_Current;
956 radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
957
958 if (!(t->pp_txformat & RADEON_TXFORMAT_NON_POWER2)) {
959 t->pp_txformat |= RADEON_TXFORMAT_NON_POWER2;
960 t->base.dirty_images[0] = ~0;
961 }
962
963 ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
964
965 if ( t->base.dirty_images[0] ) {
966 RADEON_FIREVERTICES( rmesa );
967 radeonSetTexImages( rmesa, tObj );
968 radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 );
969 if ( !t->base.memBlock /* && !rmesa->prefer_gart_client_texturing FIXME */ ) {
970 fprintf(stderr, "%s: upload failed\n", __FUNCTION__);
971 return GL_FALSE;
972 }
973 }
974
975 return GL_TRUE;
976 }
977
978
979 static GLboolean update_tex_common( GLcontext *ctx, int unit )
980 {
981 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
982 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
983 struct gl_texture_object *tObj = texUnit->_Current;
984 radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
985 GLenum format;
986
987 /* Fallback if there's a texture border */
988 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
989 fprintf(stderr, "%s: border\n", __FUNCTION__);
990 return GL_FALSE;
991 }
992
993 /* Update state if this is a different texture object to last
994 * time.
995 */
996 if ( rmesa->state.texture.unit[unit].texobj != t ) {
997 if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
998 /* The old texture is no longer bound to this texture unit.
999 * Mark it as such.
1000 */
1001
1002 rmesa->state.texture.unit[unit].texobj->base.bound &=
1003 ~(1UL << unit);
1004 }
1005
1006 rmesa->state.texture.unit[unit].texobj = t;
1007 t->base.bound |= (1UL << unit);
1008 t->dirty_state |= 1<<unit;
1009 driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
1010 }
1011
1012
1013 /* Newly enabled?
1014 */
1015 if ( !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit))) {
1016 RADEON_STATECHANGE( rmesa, ctx );
1017 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=
1018 (RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit;
1019
1020 RADEON_STATECHANGE( rmesa, tcl );
1021
1022 if (unit == 0)
1023 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST0;
1024 else
1025 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST1;
1026
1027 rmesa->recheck_texgen[unit] = GL_TRUE;
1028 }
1029
1030 if (t->dirty_state & (1<<unit)) {
1031 import_tex_obj_state( rmesa, unit, t );
1032 }
1033
1034 if (rmesa->recheck_texgen[unit]) {
1035 GLboolean fallback = !radeon_validate_texgen( ctx, unit );
1036 TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
1037 rmesa->recheck_texgen[unit] = 0;
1038 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1039 }
1040
1041 format = tObj->Image[0][tObj->BaseLevel]->Format;
1042 if ( rmesa->state.texture.unit[unit].format != format ||
1043 rmesa->state.texture.unit[unit].envMode != texUnit->EnvMode ) {
1044 rmesa->state.texture.unit[unit].format = format;
1045 rmesa->state.texture.unit[unit].envMode = texUnit->EnvMode;
1046 if ( ! radeonUpdateTextureEnv( ctx, unit ) ) {
1047 return GL_FALSE;
1048 }
1049 }
1050
1051 FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback );
1052 return !t->border_fallback;
1053 }
1054
1055
1056
1057 static GLboolean radeonUpdateTextureUnit( GLcontext *ctx, int unit )
1058 {
1059 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1060
1061 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_TEXRECT_0 << unit, 0 );
1062
1063 if ( texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT) ) {
1064 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_TEXRECT_0 << unit, 1 );
1065
1066 return (enable_tex_rect( ctx, unit ) &&
1067 update_tex_common( ctx, unit ));
1068 }
1069 else if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
1070 return (enable_tex_2d( ctx, unit ) &&
1071 update_tex_common( ctx, unit ));
1072 }
1073 else if ( texUnit->_ReallyEnabled ) {
1074 return GL_FALSE;
1075 }
1076 else {
1077 disable_tex( ctx, unit );
1078 return GL_TRUE;
1079 }
1080 }
1081
1082 void radeonUpdateTextureState( GLcontext *ctx )
1083 {
1084 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1085 GLboolean ok;
1086
1087 ok = (radeonUpdateTextureUnit( ctx, 0 ) &&
1088 radeonUpdateTextureUnit( ctx, 1 ));
1089
1090 FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, !ok );
1091
1092 if (rmesa->TclFallback)
1093 radeonChooseVertexState( ctx );
1094 }