patch to import Jon Smirl's work from Bitkeeper
[mesa.git] / src / mesa / drivers / dri / mga / mga_texstate.c
1 /*
2 * Copyright 2000-2001 VA Linux Systems, Inc.
3 * (c) Copyright IBM Corporation 2002
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * on the rights to use, copy, modify, merge, publish, distribute, sub
10 * license, and/or sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 * VA LINUX SYSTEMS, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 * Ian Romanick <idr@us.ibm.com>
27 * Keith Whitwell <keithw@tungstengraphics.com>
28 */
29 /* $XFree86:$ */
30
31 #include "mm.h"
32 #include "mgacontext.h"
33 #include "mgatex.h"
34 #include "mgaregs.h"
35 #include "mgatris.h"
36 #include "mgaioctl.h"
37
38 #include "context.h"
39 #include "enums.h"
40 #include "macros.h"
41 #include "imports.h"
42
43 #include "simple_list.h"
44 #include "texformat.h"
45
46 #define MGA_USE_TABLE_FOR_FORMAT
47 #ifdef MGA_USE_TABLE_FOR_FORMAT
48 #define TMC_nr_tformat (MESA_FORMAT_YCBCR_REV + 1)
49 static const unsigned TMC_tformat[ TMC_nr_tformat ] =
50 {
51 [MESA_FORMAT_ARGB8888] = TMC_tformat_tw32 | TMC_takey_1 | TMC_tamask_0,
52 [MESA_FORMAT_RGB565] = TMC_tformat_tw16 | TMC_takey_1 | TMC_tamask_0,
53 [MESA_FORMAT_ARGB4444] = TMC_tformat_tw12 | TMC_takey_1 | TMC_tamask_0,
54 [MESA_FORMAT_ARGB1555] = TMC_tformat_tw15 | TMC_takey_1 | TMC_tamask_0,
55 [MESA_FORMAT_CI8] = TMC_tformat_tw8 | TMC_takey_1 | TMC_tamask_0,
56 [MESA_FORMAT_YCBCR] = TMC_tformat_tw422uyvy | TMC_takey_1 | TMC_tamask_0,
57 [MESA_FORMAT_YCBCR_REV] = TMC_tformat_tw422 | TMC_takey_1 | TMC_tamask_0,
58 };
59 #endif
60
61 static void
62 mgaSetTexImages( mgaContextPtr mmesa,
63 const struct gl_texture_object * tObj )
64 {
65 mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
66 struct gl_texture_image *baseImage = tObj->Image[ tObj->BaseLevel ];
67 GLint totalSize;
68 GLint width, height;
69 GLint i;
70 GLint firstLevel, lastLevel, numLevels;
71 GLint log2Width, log2Height;
72 GLuint txformat = 0;
73 GLint ofs;
74
75 /* Set the hardware texture format
76 */
77 #ifndef MGA_USE_TABLE_FOR_FORMAT
78 switch (baseImage->TexFormat->MesaFormat) {
79
80 case MESA_FORMAT_ARGB8888: txformat = TMC_tformat_tw32; break;
81 case MESA_FORMAT_RGB565: txformat = TMC_tformat_tw16; break;
82 case MESA_FORMAT_ARGB4444: txformat = TMC_tformat_tw12; break;
83 case MESA_FORMAT_ARGB1555: txformat = TMC_tformat_tw15; break;
84 case MESA_FORMAT_CI8: txformat = TMC_tformat_tw8; break;
85 case MESA_FORMAT_YCBCR: txformat = TMC_tformat_tw422uyvy; break;
86 case MESA_FORMAT_YCBCR_REV: txformat = TMC_tformat_tw422; break;
87
88 default:
89 _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
90 return;
91 }
92 #else
93 if ( (baseImage->TexFormat->MesaFormat >= TMC_nr_tformat)
94 || (TMC_tformat[ baseImage->TexFormat->MesaFormat ] == 0) )
95 {
96 _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
97 return;
98 }
99
100 txformat = TMC_tformat[ baseImage->TexFormat->MesaFormat ];
101
102 #endif /* MGA_USE_TABLE_FOR_FORMAT */
103
104 if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
105 /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
106 */
107
108 firstLevel = lastLevel = tObj->BaseLevel;
109 } else {
110 /* Compute which mipmap levels we really want to send to the hardware.
111 * This depends on the base image size, GL_TEXTURE_MIN_LOD,
112 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
113 * Yes, this looks overly complicated, but it's all needed.
114 */
115
116 firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
117 firstLevel = MAX2(firstLevel, tObj->BaseLevel);
118 lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
119 lastLevel = MAX2(lastLevel, tObj->BaseLevel);
120 lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
121 lastLevel = MIN2(lastLevel, tObj->MaxLevel);
122 lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
123 }
124
125 log2Width = tObj->Image[firstLevel]->WidthLog2;
126 log2Height = tObj->Image[firstLevel]->HeightLog2;
127 width = tObj->Image[firstLevel]->Width;
128 height = tObj->Image[firstLevel]->Height;
129
130 numLevels = MIN2( lastLevel - firstLevel + 1,
131 MGA_IS_G200(mmesa) ? G200_TEX_MAXLEVELS : G400_TEX_MAXLEVELS);
132
133
134 totalSize = 0;
135 for ( i = 0 ; i < numLevels ; i++ ) {
136 const struct gl_texture_image * const texImage = tObj->Image[i+firstLevel];
137
138 if ( (texImage == NULL)
139 || ((i != 0)
140 && ((texImage->Width < 8) || (texImage->Height < 8))) ) {
141 break;
142 }
143
144 t->offsets[i] = totalSize;
145 t->base.dirty_images[0] |= (1<<i);
146
147 totalSize += ((MAX2( texImage->Width, 8 ) *
148 MAX2( texImage->Height, 8 ) *
149 baseImage->TexFormat->TexelBytes) + 31) & ~31;
150 }
151
152 numLevels = i;
153 lastLevel = firstLevel + numLevels - 1;
154
155 /* save these values */
156 t->base.firstLevel = firstLevel;
157 t->base.lastLevel = lastLevel;
158
159 t->base.totalSize = totalSize;
160
161 /* setup hardware register values */
162 t->setup.texctl &= (TMC_tformat_MASK & TMC_tpitch_MASK
163 & TMC_tpitchext_MASK);
164 t->setup.texctl |= txformat;
165
166
167 /* Set the texture width. In order to support non-power of 2 textures and
168 * textures larger than 1024 texels wide, "linear" pitch must be used. For
169 * the linear pitch, if the width is 2048, a value of zero is used.
170 */
171
172 t->setup.texctl |= TMC_tpitchlin_enable;
173 t->setup.texctl |= (width & (2048 - 1)) << TMC_tpitchext_SHIFT;
174
175
176 /* G400 specifies the number of mip levels in a strange way. Since there
177 * are up to 12 levels, it requires 4 bits. Three of the bits are at the
178 * high end of TEXFILTER. The other bit is in the middle. Weird.
179 */
180
181 t->setup.texfilter &= TF_mapnb_MASK & TF_mapnbhigh_MASK & TF_reserved_MASK;
182 t->setup.texfilter |= (((numLevels-1) & 0x07) << (TF_mapnb_SHIFT));
183 t->setup.texfilter |= (((numLevels-1) & 0x08) << (TF_mapnbhigh_SHIFT - 3));
184
185 /* warp texture registers */
186 ofs = MGA_IS_G200(mmesa) ? 28 : 11;
187
188 t->setup.texwidth = (MGA_FIELD(TW_twmask, width - 1) |
189 MGA_FIELD(TW_rfw, (10 - log2Width - 8) & 63 ) |
190 MGA_FIELD(TW_tw, (log2Width + ofs ) | 0x40 ));
191
192 t->setup.texheight = (MGA_FIELD(TH_thmask, height - 1) |
193 MGA_FIELD(TH_rfh, (10 - log2Height - 8) & 63 ) |
194 MGA_FIELD(TH_th, (log2Height + ofs ) | 0x40 ));
195
196 mgaUploadTexImages( mmesa, t );
197 }
198
199
200 /* ================================================================
201 * Texture unit state management
202 */
203
204 static void mgaUpdateTextureEnvG200( GLcontext *ctx, GLuint unit )
205 {
206 struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
207 mgaTextureObjectPtr t;
208
209 if (!tObj || !tObj->DriverData)
210 return;
211
212 t = (mgaTextureObjectPtr)tObj->DriverData;
213
214 t->setup.texctl2 &= ~TMC_decalblend_enable;
215
216 switch (ctx->Texture.Unit[0].EnvMode) {
217 case GL_REPLACE:
218 t->setup.texctl &= ~TMC_tmodulate_enable;
219 break;
220 case GL_MODULATE:
221 t->setup.texctl |= TMC_tmodulate_enable;
222 break;
223 case GL_DECAL:
224 t->setup.texctl &= ~TMC_tmodulate_enable;
225 t->setup.texctl2 |= TMC_decalblend_enable;
226 break;
227 case GL_BLEND:
228 FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
229 break;
230 default:
231 break;
232 }
233 }
234
235
236 #define MGA_DISABLE 0
237 #define MGA_REPLACE 1
238 #define MGA_MODULATE 2
239 #define MGA_DECAL 3
240 #define MGA_BLEND 4
241 #define MGA_ADD 5
242 #define MGA_MAX_COMBFUNC 6
243
244 static const GLuint g400_color_combine[][MGA_MAX_COMBFUNC] =
245 {
246 /* Unit 0:
247 */
248 {
249 /* Disable combiner stage
250 */
251 (0),
252
253 /* GL_REPLACE
254 */
255 (TD0_color_sel_arg1 |
256 TD0_alpha_arg2_diffuse |
257 TD0_alpha_sel_arg2 ),
258
259 /* GL_MODULATE
260 */
261 (TD0_color_arg2_diffuse |
262 TD0_color_sel_mul |
263 TD0_alpha_arg2_diffuse |
264 TD0_alpha_sel_mul),
265
266 /* GL_DECAL
267 */
268 (TD0_color_sel_arg1 |
269 TD0_alpha_arg2_diffuse |
270 TD0_alpha_sel_arg2),
271
272 /* GL_BLEND
273 */
274 (0),
275
276 /* GL_ADD
277 */
278 (TD0_color_arg2_diffuse |
279 TD0_color_add_add |
280 TD0_color_sel_add |
281 TD0_alpha_arg2_diffuse |
282 TD0_alpha_sel_mul),
283 },
284
285 /* Unit 1:
286 */
287 {
288 /* Disable combiner stage
289 */
290 (0),
291
292 /* GL_REPLACE
293 */
294 (TD0_color_sel_arg1 |
295 TD0_alpha_arg2_diffuse |
296 TD0_alpha_sel_arg2 ),
297
298 /* GL_MODULATE
299 */
300 (TD0_color_arg2_prevstage |
301 TD0_color_alpha_prevstage |
302 TD0_color_sel_mul |
303 TD0_alpha_arg2_prevstage |
304 TD0_alpha_sel_mul),
305
306 /* GL_DECAL
307 */
308 (TD0_color_sel_arg1 |
309 TD0_alpha_arg2_prevstage |
310 TD0_alpha_sel_arg2 ),
311
312 /* GL_BLEND
313 */
314 (0),
315
316 /* GL_ADD
317 */
318 (TD0_color_arg2_prevstage |
319 TD0_color_alpha_prevstage |
320 TD0_color_add_add |
321 TD0_color_sel_add |
322 TD0_alpha_arg2_prevstage |
323 TD0_alpha_sel_mul),
324 },
325 };
326
327 static const GLuint g400_alpha_combine[][MGA_MAX_COMBFUNC] =
328 {
329 /* Unit 0:
330 */
331 {
332 /* Disable combiner stage
333 */
334 (0),
335
336 /* GL_REPLACE
337 */
338 (TD0_color_sel_arg2 |
339 TD0_color_arg2_diffuse |
340 TD0_alpha_sel_arg1 ),
341
342 /* GL_MODULATE
343 * FIXME: Is this correct?
344 */
345 (TD0_color_arg2_diffuse |
346 TD0_color_sel_mul |
347 TD0_alpha_arg2_diffuse |
348 TD0_alpha_sel_mul),
349
350 /* GL_DECAL
351 */
352 (TD0_color_arg2_diffuse |
353 TD0_color_sel_arg2 |
354 TD0_alpha_arg2_diffuse |
355 TD0_alpha_sel_arg2),
356
357 /* GL_BLEND
358 */
359 (TD0_color_arg2_diffuse |
360 TD0_color_sel_mul |
361 TD0_alpha_arg2_diffuse |
362 TD0_alpha_sel_mul),
363
364 /* GL_ADD
365 */
366 (TD0_color_arg2_diffuse |
367 TD0_color_sel_mul |
368 TD0_alpha_arg2_diffuse |
369 TD0_alpha_sel_mul),
370 },
371
372 /* Unit 1:
373 */
374 {
375 /* Disable combiner stage
376 */
377 (0),
378
379 /* GL_REPLACE
380 */
381 (TD0_color_sel_arg2 |
382 TD0_color_arg2_diffuse |
383 TD0_alpha_sel_arg1 ),
384
385 /* GL_MODULATE
386 * FIXME: Is this correct?
387 */
388 (TD0_color_arg2_prevstage |
389 TD0_color_alpha_prevstage |
390 TD0_color_sel_mul |
391 TD0_alpha_arg2_prevstage |
392 TD0_alpha_sel_mul),
393
394 /* GL_DECAL
395 */
396 (TD0_color_arg2_prevstage |
397 TD0_color_sel_arg2 |
398 TD0_alpha_arg2_prevstage |
399 TD0_alpha_sel_arg2),
400
401 /* GL_BLEND
402 */
403 (TD0_color_arg2_diffuse |
404 TD0_color_sel_mul |
405 TD0_alpha_arg2_diffuse |
406 TD0_alpha_sel_mul),
407
408 /* GL_ADD
409 */
410 (TD0_color_arg2_prevstage |
411 TD0_color_sel_mul |
412 TD0_alpha_arg2_prevstage |
413 TD0_alpha_sel_mul),
414 },
415 };
416
417 static void mgaUpdateTextureEnvG400( GLcontext *ctx, GLuint unit )
418 {
419 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
420 const int source = mmesa->tmu_source[unit];
421 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
422 const struct gl_texture_object *tObj = texUnit->_Current;
423 GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
424 GLenum format;
425
426 if ( tObj != ctx->Texture.Unit[source].Current2D || !tObj )
427 return;
428
429 format = tObj->Image[tObj->BaseLevel]->Format;
430
431 switch (ctx->Texture.Unit[source].EnvMode) {
432 case GL_REPLACE:
433 if (format == GL_RGB || format == GL_LUMINANCE) {
434 *reg = g400_color_combine[unit][MGA_REPLACE];
435 }
436 else if (format == GL_ALPHA) {
437 *reg = g400_alpha_combine[unit][MGA_REPLACE];
438 }
439 else {
440 *reg = (TD0_color_sel_arg1 |
441 TD0_alpha_sel_arg1 );
442 }
443 break;
444
445 case GL_MODULATE:
446 *reg = g400_color_combine[unit][MGA_MODULATE];
447 break;
448 case GL_DECAL:
449 if (format == GL_RGB) {
450 *reg = g400_color_combine[unit][MGA_DECAL];
451 }
452 else if ( format == GL_RGBA ) {
453 #if 0
454 if (unit == 0) {
455 /* this doesn't work */
456 *reg = (TD0_color_arg2_diffuse |
457 TD0_color_alpha_currtex |
458 TD0_color_alpha2inv_enable |
459 TD0_color_arg2mul_alpha2 |
460 TD0_color_arg1mul_alpha1 |
461 TD0_color_blend_enable |
462 TD0_color_arg1add_mulout |
463 TD0_color_arg2add_mulout |
464 TD0_color_add_add |
465 TD0_color_sel_mul |
466 TD0_alpha_arg2_diffuse |
467 TD0_alpha_sel_arg2 );
468 }
469 else {
470 *reg = (TD0_color_arg2_prevstage |
471 TD0_color_alpha_currtex |
472 TD0_color_alpha2inv_enable |
473 TD0_color_arg2mul_alpha2 |
474 TD0_color_arg1mul_alpha1 |
475 TD0_color_add_add |
476 TD0_color_sel_add |
477 TD0_alpha_arg2_prevstage |
478 TD0_alpha_sel_arg2 );
479 }
480 #else
481 /* s/w fallback, pretty sure we can't do in h/w */
482 FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
483 if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
484 fprintf( stderr, "FALLBACK: GL_DECAL RGBA texture, unit=%d\n",
485 unit );
486 #endif
487 }
488 else {
489 *reg = g400_alpha_combine[unit][MGA_DECAL];
490 }
491 break;
492
493 case GL_ADD:
494 if (format == GL_INTENSITY) {
495 if (unit == 0) {
496 *reg = ( TD0_color_arg2_diffuse |
497 TD0_color_add_add |
498 TD0_color_sel_add |
499 TD0_alpha_arg2_diffuse |
500 TD0_alpha_add_enable |
501 TD0_alpha_sel_add);
502 }
503 else {
504 *reg = ( TD0_color_arg2_prevstage |
505 TD0_color_add_add |
506 TD0_color_sel_add |
507 TD0_alpha_arg2_prevstage |
508 TD0_alpha_add_enable |
509 TD0_alpha_sel_add);
510 }
511 }
512 else if (format == GL_ALPHA) {
513 *reg = g400_alpha_combine[unit][MGA_ADD];
514 }
515 else {
516 *reg = g400_color_combine[unit][MGA_ADD];
517 }
518 break;
519
520 case GL_BLEND:
521 if (format == GL_ALPHA) {
522 *reg = g400_alpha_combine[unit][MGA_BLEND];
523 }
524 else {
525 FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
526 if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
527 fprintf( stderr, "FALLBACK: GL_BLEND envcolor=0x%08x\n",
528 mmesa->envcolor );
529
530 /* Do singletexture GL_BLEND with 'all ones' env-color
531 * by using both texture units. Multitexture gl_blend
532 * is a fallback.
533 */
534 if (unit == 0) {
535 /* Part 1: R1 = Rf ( 1 - Rt )
536 * A1 = Af At
537 */
538 *reg = ( TD0_color_arg2_diffuse |
539 TD0_color_arg1_inv_enable |
540 TD0_color_sel_mul |
541 TD0_alpha_arg2_diffuse |
542 TD0_alpha_sel_arg1);
543 } else {
544 /* Part 2: R2 = R1 + Rt
545 * A2 = A1
546 */
547 *reg = ( TD0_color_arg2_prevstage |
548 TD0_color_add_add |
549 TD0_color_sel_add |
550 TD0_alpha_arg2_prevstage |
551 TD0_alpha_sel_arg2);
552 }
553 }
554 break;
555 default:
556 break;
557 }
558 }
559
560
561 static void disable_tex( GLcontext *ctx, int unit )
562 {
563 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
564
565 /* Texture unit disabled */
566
567 if ( mmesa->CurrentTexObj[unit] != NULL ) {
568 /* The old texture is no longer bound to this texture unit.
569 * Mark it as such.
570 */
571
572 mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit);
573 mmesa->CurrentTexObj[unit] = NULL;
574 }
575
576 if ( unit != 0 ) {
577 mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
578 }
579
580 if ( ctx->Texture._EnabledUnits == 0 ) {
581 mmesa->setup.dwgctl &= DC_opcod_MASK;
582 mmesa->setup.dwgctl |= DC_opcod_trap;
583 mmesa->hw.alpha_sel = AC_alphasel_diffused;
584 }
585
586 mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
587 }
588
589 static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
590 {
591 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
592 const int source = mmesa->tmu_source[unit];
593 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
594 const struct gl_texture_object *tObj = texUnit->_Current;
595 mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
596
597 /* Upload teximages (not pipelined)
598 */
599 if (t->base.dirty_images[0]) {
600 FLUSH_BATCH( mmesa );
601 mgaSetTexImages( mmesa, tObj );
602 if ( t->base.memBlock == NULL ) {
603 return GL_FALSE;
604 }
605 }
606
607 return GL_TRUE;
608 }
609
610 static GLboolean update_tex_common( GLcontext *ctx, int unit )
611 {
612 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
613 const int source = mmesa->tmu_source[unit];
614 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
615 struct gl_texture_object *tObj = texUnit->_Current;
616 mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
617
618 /* Fallback if there's a texture border */
619 if ( tObj->Image[tObj->BaseLevel]->Border > 0 ) {
620 return GL_FALSE;
621 }
622
623
624 /* Update state if this is a different texture object to last
625 * time.
626 */
627 if ( mmesa->CurrentTexObj[unit] != t ) {
628 if ( mmesa->CurrentTexObj[unit] != NULL ) {
629 /* The old texture is no longer bound to this texture unit.
630 * Mark it as such.
631 */
632
633 mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit);
634 }
635
636 mmesa->CurrentTexObj[unit] = t;
637 t->base.bound |= (1UL << unit);
638
639 driUpdateTextureLRU( (driTextureObject *) t ); /* done too often */
640 }
641
642 /* register setup */
643 if ( unit == 1 ) {
644 mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
645 }
646
647 t->setup.texctl2 &= TMC_dualtex_MASK;
648 if (ctx->Texture._EnabledUnits == 0x03) {
649 t->setup.texctl2 |= TMC_dualtex_enable;
650 }
651
652 /* FIXME: The Radeon has some cached state so that it can avoid calling
653 * FIXME: UpdateTextureEnv in some cases. Is that possible here?
654 */
655 if (MGA_IS_G400(mmesa)) {
656 /* G400: Regardless of texture env mode, we use the alpha from the
657 * texture unit (AC_alphasel_fromtex) since it will have already
658 * been modulated by the incoming fragment color, if needed.
659 * We don't want (AC_alphasel_modulate) since that'll effectively
660 * do the modulation twice.
661 */
662 mmesa->hw.alpha_sel = AC_alphasel_fromtex;
663
664 mgaUpdateTextureEnvG400( ctx, unit );
665 } else {
666 mmesa->hw.alpha_sel = 0;
667 switch (ctx->Texture.Unit[0].EnvMode) {
668 case GL_DECAL:
669 mmesa->hw.alpha_sel |= AC_alphasel_diffused;
670 case GL_REPLACE:
671 mmesa->hw.alpha_sel |= AC_alphasel_fromtex;
672 break;
673 case GL_BLEND:
674 case GL_MODULATE:
675 mmesa->hw.alpha_sel |= AC_alphasel_modulated;
676 break;
677 default:
678 break;
679 }
680
681 mgaUpdateTextureEnvG200( ctx, unit );
682 }
683
684 mmesa->setup.dwgctl &= DC_opcod_MASK;
685 mmesa->setup.dwgctl |= DC_opcod_texture_trap;
686 mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
687
688 FALLBACK( ctx, MGA_FALLBACK_BORDER_MODE, t->border_fallback );
689 return !t->border_fallback;
690 }
691
692
693 static GLboolean updateTextureUnit( GLcontext *ctx, int unit )
694 {
695 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
696 const int source = mmesa->tmu_source[unit];
697 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
698
699
700 if ( texUnit->_ReallyEnabled == TEXTURE_2D_BIT) {
701 return(enable_tex_2d( ctx, unit ) &&
702 update_tex_common( ctx, unit ));
703 }
704 else if ( texUnit->_ReallyEnabled ) {
705 return GL_FALSE;
706 }
707 else {
708 disable_tex( ctx, unit );
709 return GL_TRUE;
710 }
711 }
712
713 /* The G400 is now programmed quite differently wrt texture environment.
714 */
715 void mgaUpdateTextureState( GLcontext *ctx )
716 {
717 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
718 GLboolean ok;
719 unsigned i;
720
721
722 /* This works around a quirk with the MGA hardware. If only OpenGL
723 * TEXTURE1 is enabled, then the hardware TEXTURE0 must be used. The
724 * hardware TEXTURE1 can ONLY be used when hardware TEXTURE0 is also used.
725 */
726
727 mmesa->tmu_source[0] = 0;
728 mmesa->tmu_source[1] = 1;
729
730 if ((ctx->Texture._EnabledUnits & 0x03) == 0x02) {
731 /* only texture 1 enabled */
732 mmesa->tmu_source[0] = 1;
733 mmesa->tmu_source[1] = 0;
734 }
735
736 for ( i = 0, ok = GL_TRUE
737 ; (i < ctx->Const.MaxTextureUnits) && ok
738 ; i++ ) {
739 ok = updateTextureUnit( ctx, i );
740 }
741
742 FALLBACK( ctx, MGA_FALLBACK_TEXTURE, !ok );
743
744 /* FIXME: I believe that ChooseVertexState should be called here instead of
745 * FIXME: in mgaDDValidateState.
746 */
747 }