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