change GL_ARB_texture_env_crossbar implementation behaviour to OGL 1.4 core specifica...
[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 GLint 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 /* implement ogl 1.4/1.5 core spec here, not specification of
459 * GL_ARB_texture_env_crossbar (which would require disabling blending
460 * instead of undefined results when referencing not enabled texunit) */
461 color_arg[i] = radeon_texture_color[op][srcRGBi - GL_TEXTURE0];
462 break;
463 default:
464 return GL_FALSE;
465 }
466 }
467
468 for ( i = 0 ; i < numAlphaArgs ; i++ ) {
469 const GLint op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA;
470 const GLuint srcAi = texUnit->_CurrentCombine->SourceA[i];
471 assert(op >= 0);
472 assert(op <= 1);
473 switch ( srcAi ) {
474 case GL_TEXTURE:
475 alpha_arg[i] = radeon_texture_alpha[op][unit];
476 break;
477 case GL_CONSTANT:
478 alpha_arg[i] = radeon_tfactor_alpha[op];
479 break;
480 case GL_PRIMARY_COLOR:
481 alpha_arg[i] = radeon_primary_alpha[op];
482 break;
483 case GL_PREVIOUS:
484 alpha_arg[i] = radeon_previous_alpha[op];
485 break;
486 case GL_ZERO:
487 alpha_arg[i] = radeon_zero_alpha[op];
488 break;
489 case GL_ONE:
490 alpha_arg[i] = radeon_zero_alpha[op+1];
491 break;
492 case GL_TEXTURE0:
493 case GL_TEXTURE1:
494 case GL_TEXTURE2:
495 alpha_arg[i] = radeon_texture_alpha[op][srcAi - GL_TEXTURE0];
496 break;
497 default:
498 return GL_FALSE;
499 }
500 }
501
502 /* Step 2:
503 * Build up the color and alpha combine functions.
504 */
505 switch ( texUnit->_CurrentCombine->ModeRGB ) {
506 case GL_REPLACE:
507 color_combine = (RADEON_COLOR_ARG_A_ZERO |
508 RADEON_COLOR_ARG_B_ZERO |
509 RADEON_BLEND_CTL_ADD |
510 RADEON_CLAMP_TX);
511 RADEON_COLOR_ARG( 0, C );
512 break;
513 case GL_MODULATE:
514 color_combine = (RADEON_COLOR_ARG_C_ZERO |
515 RADEON_BLEND_CTL_ADD |
516 RADEON_CLAMP_TX);
517 RADEON_COLOR_ARG( 0, A );
518 RADEON_COLOR_ARG( 1, B );
519 break;
520 case GL_ADD:
521 color_combine = (RADEON_COLOR_ARG_B_ZERO |
522 RADEON_COMP_ARG_B |
523 RADEON_BLEND_CTL_ADD |
524 RADEON_CLAMP_TX);
525 RADEON_COLOR_ARG( 0, A );
526 RADEON_COLOR_ARG( 1, C );
527 break;
528 case GL_ADD_SIGNED:
529 color_combine = (RADEON_COLOR_ARG_B_ZERO |
530 RADEON_COMP_ARG_B |
531 RADEON_BLEND_CTL_ADDSIGNED |
532 RADEON_CLAMP_TX);
533 RADEON_COLOR_ARG( 0, A );
534 RADEON_COLOR_ARG( 1, C );
535 break;
536 case GL_SUBTRACT:
537 color_combine = (RADEON_COLOR_ARG_B_ZERO |
538 RADEON_COMP_ARG_B |
539 RADEON_BLEND_CTL_SUBTRACT |
540 RADEON_CLAMP_TX);
541 RADEON_COLOR_ARG( 0, A );
542 RADEON_COLOR_ARG( 1, C );
543 break;
544 case GL_INTERPOLATE:
545 color_combine = (RADEON_BLEND_CTL_BLEND |
546 RADEON_CLAMP_TX);
547 RADEON_COLOR_ARG( 0, B );
548 RADEON_COLOR_ARG( 1, A );
549 RADEON_COLOR_ARG( 2, C );
550 break;
551
552 case GL_DOT3_RGB_EXT:
553 case GL_DOT3_RGBA_EXT:
554 /* The EXT version of the DOT3 extension does not support the
555 * scale factor, but the ARB version (and the version in OpenGL
556 * 1.3) does.
557 */
558 RGBshift = 0;
559 Ashift = 0;
560 /* FALLTHROUGH */
561
562 case GL_DOT3_RGB:
563 case GL_DOT3_RGBA:
564 /* The R100 / RV200 only support a 1X multiplier in hardware
565 * w/the ARB version.
566 */
567 if ( RGBshift != (RADEON_SCALE_1X >> RADEON_SCALE_SHIFT) ) {
568 return GL_FALSE;
569 }
570
571 RGBshift += 2;
572 Ashift = RGBshift;
573
574 color_combine = (RADEON_COLOR_ARG_C_ZERO |
575 RADEON_BLEND_CTL_DOT3 |
576 RADEON_CLAMP_TX);
577 RADEON_COLOR_ARG( 0, A );
578 RADEON_COLOR_ARG( 1, B );
579 break;
580
581 case GL_MODULATE_ADD_ATI:
582 color_combine = (RADEON_BLEND_CTL_ADD |
583 RADEON_CLAMP_TX);
584 RADEON_COLOR_ARG( 0, A );
585 RADEON_COLOR_ARG( 1, C );
586 RADEON_COLOR_ARG( 2, B );
587 break;
588 case GL_MODULATE_SIGNED_ADD_ATI:
589 color_combine = (RADEON_BLEND_CTL_ADDSIGNED |
590 RADEON_CLAMP_TX);
591 RADEON_COLOR_ARG( 0, A );
592 RADEON_COLOR_ARG( 1, C );
593 RADEON_COLOR_ARG( 2, B );
594 break;
595 case GL_MODULATE_SUBTRACT_ATI:
596 color_combine = (RADEON_BLEND_CTL_SUBTRACT |
597 RADEON_CLAMP_TX);
598 RADEON_COLOR_ARG( 0, A );
599 RADEON_COLOR_ARG( 1, C );
600 RADEON_COLOR_ARG( 2, B );
601 break;
602 default:
603 return GL_FALSE;
604 }
605
606 switch ( texUnit->_CurrentCombine->ModeA ) {
607 case GL_REPLACE:
608 alpha_combine = (RADEON_ALPHA_ARG_A_ZERO |
609 RADEON_ALPHA_ARG_B_ZERO |
610 RADEON_BLEND_CTL_ADD |
611 RADEON_CLAMP_TX);
612 RADEON_ALPHA_ARG( 0, C );
613 break;
614 case GL_MODULATE:
615 alpha_combine = (RADEON_ALPHA_ARG_C_ZERO |
616 RADEON_BLEND_CTL_ADD |
617 RADEON_CLAMP_TX);
618 RADEON_ALPHA_ARG( 0, A );
619 RADEON_ALPHA_ARG( 1, B );
620 break;
621 case GL_ADD:
622 alpha_combine = (RADEON_ALPHA_ARG_B_ZERO |
623 RADEON_COMP_ARG_B |
624 RADEON_BLEND_CTL_ADD |
625 RADEON_CLAMP_TX);
626 RADEON_ALPHA_ARG( 0, A );
627 RADEON_ALPHA_ARG( 1, C );
628 break;
629 case GL_ADD_SIGNED:
630 alpha_combine = (RADEON_ALPHA_ARG_B_ZERO |
631 RADEON_COMP_ARG_B |
632 RADEON_BLEND_CTL_ADDSIGNED |
633 RADEON_CLAMP_TX);
634 RADEON_ALPHA_ARG( 0, A );
635 RADEON_ALPHA_ARG( 1, C );
636 break;
637 case GL_SUBTRACT:
638 alpha_combine = (RADEON_COLOR_ARG_B_ZERO |
639 RADEON_COMP_ARG_B |
640 RADEON_BLEND_CTL_SUBTRACT |
641 RADEON_CLAMP_TX);
642 RADEON_ALPHA_ARG( 0, A );
643 RADEON_ALPHA_ARG( 1, C );
644 break;
645 case GL_INTERPOLATE:
646 alpha_combine = (RADEON_BLEND_CTL_BLEND |
647 RADEON_CLAMP_TX);
648 RADEON_ALPHA_ARG( 0, B );
649 RADEON_ALPHA_ARG( 1, A );
650 RADEON_ALPHA_ARG( 2, C );
651 break;
652
653 case GL_MODULATE_ADD_ATI:
654 alpha_combine = (RADEON_BLEND_CTL_ADD |
655 RADEON_CLAMP_TX);
656 RADEON_ALPHA_ARG( 0, A );
657 RADEON_ALPHA_ARG( 1, C );
658 RADEON_ALPHA_ARG( 2, B );
659 break;
660 case GL_MODULATE_SIGNED_ADD_ATI:
661 alpha_combine = (RADEON_BLEND_CTL_ADDSIGNED |
662 RADEON_CLAMP_TX);
663 RADEON_ALPHA_ARG( 0, A );
664 RADEON_ALPHA_ARG( 1, C );
665 RADEON_ALPHA_ARG( 2, B );
666 break;
667 case GL_MODULATE_SUBTRACT_ATI:
668 alpha_combine = (RADEON_BLEND_CTL_SUBTRACT |
669 RADEON_CLAMP_TX);
670 RADEON_ALPHA_ARG( 0, A );
671 RADEON_ALPHA_ARG( 1, C );
672 RADEON_ALPHA_ARG( 2, B );
673 break;
674 default:
675 return GL_FALSE;
676 }
677
678 if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGB_EXT)
679 || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGB) ) {
680 alpha_combine |= RADEON_DOT_ALPHA_DONT_REPLICATE;
681 }
682
683 /* Step 3:
684 * Apply the scale factor.
685 */
686 color_combine |= (RGBshift << RADEON_SCALE_SHIFT);
687 alpha_combine |= (Ashift << RADEON_SCALE_SHIFT);
688
689 /* All done!
690 */
691 }
692
693 if ( rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] != color_combine ||
694 rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] != alpha_combine ) {
695 RADEON_STATECHANGE( rmesa, tex[unit] );
696 rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] = color_combine;
697 rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] = alpha_combine;
698 }
699
700 return GL_TRUE;
701 }
702
703 #define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK | \
704 RADEON_MIN_FILTER_MASK | \
705 RADEON_MAG_FILTER_MASK | \
706 RADEON_MAX_ANISO_MASK | \
707 RADEON_YUV_TO_RGB | \
708 RADEON_YUV_TEMPERATURE_MASK | \
709 RADEON_CLAMP_S_MASK | \
710 RADEON_CLAMP_T_MASK | \
711 RADEON_BORDER_MODE_D3D )
712
713 #define TEXOBJ_TXFORMAT_MASK (RADEON_TXFORMAT_WIDTH_MASK | \
714 RADEON_TXFORMAT_HEIGHT_MASK | \
715 RADEON_TXFORMAT_FORMAT_MASK | \
716 RADEON_TXFORMAT_F5_WIDTH_MASK | \
717 RADEON_TXFORMAT_F5_HEIGHT_MASK | \
718 RADEON_TXFORMAT_ALPHA_IN_MAP | \
719 RADEON_TXFORMAT_CUBIC_MAP_ENABLE | \
720 RADEON_TXFORMAT_NON_POWER2)
721
722
723 static void import_tex_obj_state( radeonContextPtr rmesa,
724 int unit,
725 radeonTexObjPtr texobj )
726 {
727 GLuint *cmd = RADEON_DB_STATE( tex[unit] );
728
729 cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
730 cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK;
731 cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
732 cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
733 cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset;
734 cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
735 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tex[unit] );
736
737 if (texobj->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
738 GLuint *txr_cmd = RADEON_DB_STATE( txr[unit] );
739 txr_cmd[TXR_PP_TEX_SIZE] = texobj->pp_txsize; /* NPOT only! */
740 txr_cmd[TXR_PP_TEX_PITCH] = texobj->pp_txpitch; /* NPOT only! */
741 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.txr[unit] );
742 }
743
744 texobj->dirty_state &= ~(1<<unit);
745 }
746
747
748
749
750 static void set_texgen_matrix( radeonContextPtr rmesa,
751 GLuint unit,
752 const GLfloat *s_plane,
753 const GLfloat *t_plane )
754 {
755 static const GLfloat scale_identity[4] = { 1,1,1,1 };
756
757 if (!TEST_EQ_4V( s_plane, scale_identity) ||
758 !TEST_EQ_4V( t_plane, scale_identity)) {
759 rmesa->TexGenEnabled |= RADEON_TEXMAT_0_ENABLE<<unit;
760 rmesa->TexGenMatrix[unit].m[0] = s_plane[0];
761 rmesa->TexGenMatrix[unit].m[4] = s_plane[1];
762 rmesa->TexGenMatrix[unit].m[8] = s_plane[2];
763 rmesa->TexGenMatrix[unit].m[12] = s_plane[3];
764
765 rmesa->TexGenMatrix[unit].m[1] = t_plane[0];
766 rmesa->TexGenMatrix[unit].m[5] = t_plane[1];
767 rmesa->TexGenMatrix[unit].m[9] = t_plane[2];
768 rmesa->TexGenMatrix[unit].m[13] = t_plane[3];
769 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
770 }
771 }
772
773 /* Ignoring the Q texcoord for now.
774 *
775 * Returns GL_FALSE if fallback required.
776 */
777 static GLboolean radeon_validate_texgen( GLcontext *ctx, GLuint unit )
778 {
779 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
780 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
781 GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
782 GLuint tmp = rmesa->TexGenEnabled;
783
784 rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit);
785 rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit);
786 rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift);
787 rmesa->TexGenNeedNormals[unit] = 0;
788
789 if ((texUnit->TexGenEnabled & (S_BIT|T_BIT)) == 0) {
790 /* Disabled, no fallback:
791 */
792 rmesa->TexGenEnabled |=
793 (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
794 return GL_TRUE;
795 }
796 else if (texUnit->TexGenEnabled & Q_BIT) {
797 /* Very easy to do this, in fact would remove a fallback case
798 * elsewhere, but I haven't done it yet... Fallback:
799 */
800 fprintf(stderr, "fallback Q_BIT\n");
801 return GL_FALSE;
802 }
803 else if ((texUnit->TexGenEnabled & (S_BIT|T_BIT)) != (S_BIT|T_BIT) ||
804 texUnit->GenModeS != texUnit->GenModeT) {
805 /* Mixed modes, fallback:
806 */
807 /* fprintf(stderr, "fallback mixed texgen\n"); */
808 return GL_FALSE;
809 }
810 else
811 rmesa->TexGenEnabled |= RADEON_TEXGEN_TEXMAT_0_ENABLE << unit;
812
813 switch (texUnit->GenModeS) {
814 case GL_OBJECT_LINEAR:
815 rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_OBJ << inputshift;
816 set_texgen_matrix( rmesa, unit,
817 texUnit->ObjectPlaneS,
818 texUnit->ObjectPlaneT);
819 break;
820
821 case GL_EYE_LINEAR:
822 rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE << inputshift;
823 set_texgen_matrix( rmesa, unit,
824 texUnit->EyePlaneS,
825 texUnit->EyePlaneT);
826 break;
827
828 case GL_REFLECTION_MAP_NV:
829 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
830 rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_REFLECT<<inputshift;
831 break;
832
833 case GL_NORMAL_MAP_NV:
834 rmesa->TexGenNeedNormals[unit] = GL_TRUE;
835 rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_NORMAL<<inputshift;
836 break;
837
838 case GL_SPHERE_MAP:
839 default:
840 /* Unsupported mode, fallback:
841 */
842 /* fprintf(stderr, "fallback unsupported texgen\n"); */
843 return GL_FALSE;
844 }
845
846 if (tmp != rmesa->TexGenEnabled) {
847 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
848 }
849
850 return GL_TRUE;
851 }
852
853
854 static void disable_tex( GLcontext *ctx, int unit )
855 {
856 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
857
858 if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit)) {
859 /* Texture unit disabled */
860 if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
861 /* The old texture is no longer bound to this texture unit.
862 * Mark it as such.
863 */
864
865 rmesa->state.texture.unit[unit].texobj->base.bound &= ~(1UL << unit);
866 rmesa->state.texture.unit[unit].texobj = NULL;
867 }
868
869 RADEON_STATECHANGE( rmesa, ctx );
870 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &=
871 ~((RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit);
872
873 RADEON_STATECHANGE( rmesa, tcl );
874 switch (unit) {
875 case 0:
876 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST0 |
877 RADEON_TCL_VTX_Q0);
878 break;
879 case 1:
880 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST1 |
881 RADEON_TCL_VTX_Q1);
882 break;
883 default:
884 break;
885 }
886
887
888 if (rmesa->TclFallback & (RADEON_TCL_FALLBACK_TEXGEN_0<<unit)) {
889 TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
890 rmesa->recheck_texgen[unit] = GL_TRUE;
891 }
892
893
894
895 {
896 GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
897 GLuint tmp = rmesa->TexGenEnabled;
898
899 rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit);
900 rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit);
901 rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift);
902 rmesa->TexGenNeedNormals[unit] = 0;
903 rmesa->TexGenEnabled |=
904 (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
905
906 if (tmp != rmesa->TexGenEnabled) {
907 rmesa->recheck_texgen[unit] = GL_TRUE;
908 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
909 }
910 }
911 }
912 }
913
914 static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
915 {
916 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
917 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
918 struct gl_texture_object *tObj = texUnit->_Current;
919 radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
920
921 /* Need to load the 2d images associated with this unit.
922 */
923 if (t->pp_txformat & RADEON_TXFORMAT_NON_POWER2) {
924 t->pp_txformat &= ~RADEON_TXFORMAT_NON_POWER2;
925 t->base.dirty_images[0] = ~0;
926 }
927
928 ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
929
930 if ( t->base.dirty_images[0] ) {
931 RADEON_FIREVERTICES( rmesa );
932 radeonSetTexImages( rmesa, tObj );
933 radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 );
934 if ( !t->base.memBlock )
935 return GL_FALSE;
936 }
937
938 return GL_TRUE;
939 }
940
941 static GLboolean enable_tex_rect( GLcontext *ctx, int unit )
942 {
943 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
944 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
945 struct gl_texture_object *tObj = texUnit->_Current;
946 radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
947
948 if (!(t->pp_txformat & RADEON_TXFORMAT_NON_POWER2)) {
949 t->pp_txformat |= RADEON_TXFORMAT_NON_POWER2;
950 t->base.dirty_images[0] = ~0;
951 }
952
953 ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
954
955 if ( t->base.dirty_images[0] ) {
956 RADEON_FIREVERTICES( rmesa );
957 radeonSetTexImages( rmesa, tObj );
958 radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 );
959 if ( !t->base.memBlock /* && !rmesa->prefer_gart_client_texturing FIXME */ ) {
960 fprintf(stderr, "%s: upload failed\n", __FUNCTION__);
961 return GL_FALSE;
962 }
963 }
964
965 return GL_TRUE;
966 }
967
968
969 static GLboolean update_tex_common( GLcontext *ctx, int unit )
970 {
971 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
972 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
973 struct gl_texture_object *tObj = texUnit->_Current;
974 radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
975 GLenum format;
976
977 /* Fallback if there's a texture border */
978 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
979 fprintf(stderr, "%s: border\n", __FUNCTION__);
980 return GL_FALSE;
981 }
982
983 /* Update state if this is a different texture object to last
984 * time.
985 */
986 if ( rmesa->state.texture.unit[unit].texobj != t ) {
987 if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
988 /* The old texture is no longer bound to this texture unit.
989 * Mark it as such.
990 */
991
992 rmesa->state.texture.unit[unit].texobj->base.bound &=
993 ~(1UL << unit);
994 }
995
996 rmesa->state.texture.unit[unit].texobj = t;
997 t->base.bound |= (1UL << unit);
998 t->dirty_state |= 1<<unit;
999 driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
1000 }
1001
1002
1003 /* Newly enabled?
1004 */
1005 if ( !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit))) {
1006 RADEON_STATECHANGE( rmesa, ctx );
1007 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=
1008 (RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit;
1009
1010 RADEON_STATECHANGE( rmesa, tcl );
1011
1012 if (unit == 0)
1013 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST0;
1014 else
1015 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST1;
1016
1017 rmesa->recheck_texgen[unit] = GL_TRUE;
1018 }
1019
1020 if (t->dirty_state & (1<<unit)) {
1021 import_tex_obj_state( rmesa, unit, t );
1022 }
1023
1024 if (rmesa->recheck_texgen[unit]) {
1025 GLboolean fallback = !radeon_validate_texgen( ctx, unit );
1026 TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
1027 rmesa->recheck_texgen[unit] = 0;
1028 rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1029 }
1030
1031 format = tObj->Image[0][tObj->BaseLevel]->Format;
1032 if ( rmesa->state.texture.unit[unit].format != format ||
1033 rmesa->state.texture.unit[unit].envMode != texUnit->EnvMode ) {
1034 rmesa->state.texture.unit[unit].format = format;
1035 rmesa->state.texture.unit[unit].envMode = texUnit->EnvMode;
1036 if ( ! radeonUpdateTextureEnv( ctx, unit ) ) {
1037 return GL_FALSE;
1038 }
1039 }
1040
1041 FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback );
1042 return !t->border_fallback;
1043 }
1044
1045
1046
1047 static GLboolean radeonUpdateTextureUnit( GLcontext *ctx, int unit )
1048 {
1049 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1050
1051 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_TEXRECT_0 << unit, 0 );
1052
1053 if ( texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT) ) {
1054 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_TEXRECT_0 << unit, 1 );
1055
1056 return (enable_tex_rect( ctx, unit ) &&
1057 update_tex_common( ctx, unit ));
1058 }
1059 else if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
1060 return (enable_tex_2d( ctx, unit ) &&
1061 update_tex_common( ctx, unit ));
1062 }
1063 else if ( texUnit->_ReallyEnabled ) {
1064 return GL_FALSE;
1065 }
1066 else {
1067 disable_tex( ctx, unit );
1068 return GL_TRUE;
1069 }
1070 }
1071
1072 void radeonUpdateTextureState( GLcontext *ctx )
1073 {
1074 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1075 GLboolean ok;
1076
1077 ok = (radeonUpdateTextureUnit( ctx, 0 ) &&
1078 radeonUpdateTextureUnit( ctx, 1 ));
1079
1080 FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, !ok );
1081
1082 if (rmesa->TclFallback)
1083 radeonChooseVertexState( ctx );
1084 }