71d264b0f19dbf0933ef0595b76c81d530f4eace
[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 <stdlib.h>
32 #include "mm.h"
33 #include "mgacontext.h"
34 #include "mgatex.h"
35 #include "mgaregs.h"
36 #include "mgatris.h"
37 #include "mgaioctl.h"
38
39 #include "context.h"
40 #include "enums.h"
41 #include "macros.h"
42 #include "imports.h"
43
44 #include "simple_list.h"
45 #include "texformat.h"
46
47 #define MGA_USE_TABLE_FOR_FORMAT
48 #ifdef MGA_USE_TABLE_FOR_FORMAT
49 #define TMC_nr_tformat (MESA_FORMAT_YCBCR_REV + 1)
50 static const unsigned TMC_tformat[ TMC_nr_tformat ] =
51 {
52 [MESA_FORMAT_ARGB8888] = TMC_tformat_tw32,
53 [MESA_FORMAT_RGB565] = TMC_tformat_tw16,
54 [MESA_FORMAT_ARGB4444] = TMC_tformat_tw12,
55 [MESA_FORMAT_ARGB1555] = TMC_tformat_tw15,
56 [MESA_FORMAT_AL88] = TMC_tformat_tw8al,
57 [MESA_FORMAT_I8] = TMC_tformat_tw8a,
58 [MESA_FORMAT_CI8] = TMC_tformat_tw8 ,
59 [MESA_FORMAT_YCBCR] = TMC_tformat_tw422uyvy,
60 [MESA_FORMAT_YCBCR_REV] = TMC_tformat_tw422,
61 };
62 #endif
63
64 static void
65 mgaSetTexImages( mgaContextPtr mmesa,
66 const struct gl_texture_object * tObj )
67 {
68 mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
69 struct gl_texture_image *baseImage = tObj->Image[0][ tObj->BaseLevel ];
70 GLint totalSize;
71 GLint width, height;
72 GLint i;
73 GLint numLevels;
74 GLint log2Width, log2Height;
75 GLuint txformat = 0;
76 GLint ofs;
77
78 /* Set the hardware texture format
79 */
80 #ifndef MGA_USE_TABLE_FOR_FORMAT
81 switch (baseImage->TexFormat->MesaFormat) {
82
83 case MESA_FORMAT_ARGB8888: txformat = TMC_tformat_tw32; break;
84 case MESA_FORMAT_RGB565: txformat = TMC_tformat_tw16; break;
85 case MESA_FORMAT_ARGB4444: txformat = TMC_tformat_tw12; break;
86 case MESA_FORMAT_ARGB1555: txformat = TMC_tformat_tw15; break;
87 case MESA_FORMAT_AL88: txformat = TMC_tformat_tw8al; break;
88 case MESA_FORMAT_I8: txformat = TMC_tformat_tw8a; break;
89 case MESA_FORMAT_CI8: txformat = TMC_tformat_tw8; break;
90 case MESA_FORMAT_YCBCR: txformat = TMC_tformat_tw422uyvy; break;
91 case MESA_FORMAT_YCBCR_REV: txformat = TMC_tformat_tw422; break;
92
93 default:
94 _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
95 return;
96 }
97 #else
98 if ( (baseImage->TexFormat->MesaFormat >= TMC_nr_tformat)
99 || (TMC_tformat[ baseImage->TexFormat->MesaFormat ] == 0) )
100 {
101 _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
102 return;
103 }
104
105 txformat = TMC_tformat[ baseImage->TexFormat->MesaFormat ];
106
107 #endif /* MGA_USE_TABLE_FOR_FORMAT */
108
109 driCalculateTextureFirstLastLevel( (driTextureObject *) t );
110 if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
111 log2Width = 0;
112 log2Height = 0;
113 } else {
114 log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2;
115 log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
116 }
117
118 width = tObj->Image[0][t->base.firstLevel]->Width;
119 height = tObj->Image[0][t->base.firstLevel]->Height;
120
121 numLevels = MIN2( t->base.lastLevel - t->base.firstLevel + 1,
122 MGA_IS_G200(mmesa) ? G200_TEX_MAXLEVELS : G400_TEX_MAXLEVELS);
123
124
125 totalSize = 0;
126 for ( i = 0 ; i < numLevels ; i++ ) {
127 const struct gl_texture_image * const texImage =
128 tObj->Image[0][ i + t->base.firstLevel ];
129 int size;
130
131 if (texImage == NULL)
132 break;
133
134 size = texImage->Width * texImage->Height *
135 baseImage->TexFormat->TexelBytes;
136
137 t->offsets[i] = totalSize;
138 t->base.dirty_images[0] |= (1<<i);
139
140 /* All mipmaps must be 32-byte aligned */
141 totalSize += (size + 31) & ~31;
142
143 /* Since G400 calculates the offsets in hardware
144 * it can't handle more than one < 32 byte mipmap.
145 *
146 * Further testing has indicated that it can't
147 * handle any < 32 byte mipmaps.
148 */
149 if (MGA_IS_G400( mmesa ) && size <= 32) {
150 i++;
151 break;
152 }
153 }
154
155 /* save these values */
156 numLevels = i;
157 t->base.lastLevel = t->base.firstLevel + numLevels - 1;
158 t->base.totalSize = totalSize;
159
160 /* setup hardware register values */
161 t->setup.texctl &= (TMC_tformat_MASK & TMC_tpitch_MASK
162 & TMC_tpitchext_MASK);
163 t->setup.texctl |= txformat;
164
165
166 /* Set the texture width. In order to support non-power of 2 textures and
167 * textures larger than 1024 texels wide, "linear" pitch must be used. For
168 * the linear pitch, if the width is 2048, a value of zero is used.
169 */
170
171 t->setup.texctl |= TMC_tpitchlin_enable;
172 t->setup.texctl |= MGA_FIELD( TMC_tpitchext, width & (2048 - 1) );
173
174
175 /* G400 specifies the number of mip levels in a strange way. Since there
176 * are up to 11 levels, it requires 4 bits. Three of the bits are at the
177 * high end of TEXFILTER. The other bit is in the middle. Weird.
178 */
179 numLevels--;
180 t->setup.texfilter &= TF_mapnb_MASK & TF_mapnbhigh_MASK & TF_reserved_MASK;
181 t->setup.texfilter |= MGA_FIELD( TF_mapnb, numLevels & 0x7 );
182 t->setup.texfilter |= MGA_FIELD( TF_mapnbhigh, (numLevels >> 3) & 0x1 );
183
184 /* warp texture registers */
185 ofs = MGA_IS_G200(mmesa) ? 28 : 11;
186
187 t->setup.texwidth = (MGA_FIELD(TW_twmask, width - 1) |
188 MGA_FIELD(TW_rfw, (10 - log2Width - 8) & 63 ) |
189 MGA_FIELD(TW_tw, (log2Width + ofs ) | 0x40 ));
190
191 t->setup.texheight = (MGA_FIELD(TH_thmask, height - 1) |
192 MGA_FIELD(TH_rfh, (10 - log2Height - 8) & 63 ) |
193 MGA_FIELD(TH_th, (log2Height + ofs ) | 0x40 ));
194
195 mgaUploadTexImages( mmesa, t );
196 }
197
198
199 /* ================================================================
200 * Texture unit state management
201 */
202
203 static void mgaUpdateTextureEnvG200( GLcontext *ctx, GLuint unit )
204 {
205 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
206 struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
207 mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
208 GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
209
210 if (tObj != ctx->Texture.Unit[0].Current2D &&
211 tObj != ctx->Texture.Unit[0].CurrentRect)
212 return;
213
214
215 t->setup.texctl &= ~TMC_tmodulate_enable;
216 t->setup.texctl2 &= ~(TMC_decalblend_enable |
217 TMC_idecal_enable |
218 TMC_decaldis_enable);
219
220 switch (ctx->Texture.Unit[0].EnvMode) {
221 case GL_REPLACE:
222 if (format == GL_ALPHA)
223 t->setup.texctl2 |= TMC_idecal_enable;
224
225 if (format == GL_RGB || format == GL_LUMINANCE)
226 mmesa->hw.alpha_sel = AC_alphasel_diffused;
227 else
228 mmesa->hw.alpha_sel = AC_alphasel_fromtex;
229 break;
230
231 case GL_MODULATE:
232 t->setup.texctl |= TMC_tmodulate_enable;
233
234 if (format == GL_ALPHA)
235 t->setup.texctl2 |= (TMC_idecal_enable |
236 TMC_decaldis_enable);
237
238 if (format == GL_RGB || format == GL_LUMINANCE)
239 mmesa->hw.alpha_sel = AC_alphasel_diffused;
240 else
241 mmesa->hw.alpha_sel = AC_alphasel_modulated;
242 break;
243
244 case GL_DECAL:
245 if (format == GL_RGB || format == GL_RGBA)
246 t->setup.texctl2 |= TMC_decalblend_enable;
247 else
248 t->setup.texctl2 |= TMC_idecal_enable;
249
250 mmesa->hw.alpha_sel = AC_alphasel_diffused;
251 break;
252
253 case GL_BLEND:
254 if (format == GL_ALPHA) {
255 t->setup.texctl2 |= TMC_idecal_enable;
256 mmesa->hw.alpha_sel = AC_alphasel_modulated;
257 } else {
258 t->texenv_fallback = GL_TRUE;
259 }
260 break;
261
262 default:
263 break;
264 }
265 }
266
267
268 #define MGA_REPLACE 0
269 #define MGA_MODULATE 1
270 #define MGA_DECAL 2
271 #define MGA_ADD 3
272 #define MGA_MAX_COMBFUNC 4
273
274 static const GLuint g400_color_combine[][MGA_MAX_COMBFUNC] =
275 {
276 /* Unit 0:
277 */
278 {
279 /* GL_REPLACE
280 * Cv = Cs
281 * Av = Af
282 */
283 (TD0_color_sel_arg1 |
284 TD0_alpha_arg2_diffuse |
285 TD0_alpha_sel_arg2),
286
287 /* GL_MODULATE
288 * Cv = Cf Cs
289 * Av = Af
290 */
291 (TD0_color_arg2_diffuse |
292 TD0_color_sel_mul |
293 TD0_alpha_arg2_diffuse |
294 TD0_alpha_sel_arg2),
295
296 /* GL_DECAL
297 * Cv = Cs
298 * Av = Af
299 */
300 (TD0_color_sel_arg1 |
301 TD0_alpha_arg2_diffuse |
302 TD0_alpha_sel_arg2),
303
304 /* GL_ADD
305 * Cv = Cf + Cs
306 * Av = Af
307 */
308 (TD0_color_arg2_diffuse |
309 TD0_color_add_add |
310 TD0_color_sel_add |
311 TD0_alpha_arg2_diffuse |
312 TD0_alpha_sel_arg2),
313 },
314
315 /* Unit 1:
316 */
317 {
318 /* GL_REPLACE
319 * Cv = Cs
320 * Av = Ap
321 */
322 (TD0_color_sel_arg1 |
323 TD0_alpha_arg2_prevstage |
324 TD0_alpha_sel_arg2),
325
326 /* GL_MODULATE
327 * Cv = Cp Cs
328 * Av = Ap
329 */
330 (TD0_color_arg2_prevstage |
331 TD0_color_sel_mul |
332 TD0_alpha_arg2_prevstage |
333 TD0_alpha_sel_arg2),
334
335 /* GL_DECAL
336 * Cv = Cs
337 * Av = Ap
338 */
339 (TD0_color_sel_arg1 |
340 TD0_alpha_arg2_prevstage |
341 TD0_alpha_sel_arg2),
342
343 /* GL_ADD
344 * Cv = Cp + Cs
345 * Av = Ap
346 */
347 (TD0_color_arg2_prevstage |
348 TD0_color_add_add |
349 TD0_color_sel_add |
350 TD0_alpha_arg2_prevstage |
351 TD0_alpha_sel_arg2),
352 },
353 };
354
355 static const GLuint g400_color_alpha_combine[][MGA_MAX_COMBFUNC] =
356 {
357 /* Unit 0:
358 */
359 {
360 /* GL_REPLACE
361 * Cv = Cs
362 * Av = As
363 */
364 (TD0_color_sel_arg1 |
365 TD0_alpha_sel_arg1),
366
367 /* GL_MODULATE
368 * Cv = Cf Cs
369 * Av = Af As
370 */
371 (TD0_color_arg2_diffuse |
372 TD0_color_sel_mul |
373 TD0_alpha_arg2_diffuse |
374 TD0_alpha_sel_mul),
375
376 /* GL_DECAL
377 * tmp = Cf ( 1 - As )
378 * Cv = tmp + Cs As
379 * Av = Af
380 */
381 (TD0_color_arg2_diffuse |
382 TD0_color_alpha_currtex |
383 TD0_color_alpha1inv_enable |
384 TD0_color_arg1mul_alpha1 |
385 TD0_color_blend_enable |
386 TD0_color_arg1add_mulout |
387 TD0_color_arg2add_mulout |
388 TD0_color_add_add |
389 TD0_color_sel_add |
390 TD0_alpha_arg2_diffuse |
391 TD0_alpha_sel_arg2),
392
393 /* GL_ADD
394 * Cv = Cf + Cs
395 * Av = Af As
396 */
397 (TD0_color_arg2_diffuse |
398 TD0_color_add_add |
399 TD0_color_sel_add |
400 TD0_alpha_arg2_diffuse |
401 TD0_alpha_sel_mul),
402 },
403
404 /* Unit 1:
405 */
406 {
407 /* GL_REPLACE
408 * Cv = Cs
409 * Av = As
410 */
411 (TD0_color_sel_arg1 |
412 TD0_alpha_sel_arg1),
413
414 /* GL_MODULATE
415 * Cv = Cp Cs
416 * Av = Ap As
417 */
418 (TD0_color_arg2_prevstage |
419 TD0_color_sel_mul |
420 TD0_alpha_arg2_prevstage |
421 TD0_alpha_sel_mul),
422
423 /* GL_DECAL
424 * tmp = Cp ( 1 - As )
425 * Cv = tmp + Cs As
426 * Av = Ap
427 */
428 (TD0_color_arg2_prevstage |
429 TD0_color_alpha_currtex |
430 TD0_color_alpha1inv_enable |
431 TD0_color_arg1mul_alpha1 |
432 TD0_color_blend_enable |
433 TD0_color_arg1add_mulout |
434 TD0_color_arg2add_mulout |
435 TD0_color_add_add |
436 TD0_color_sel_add |
437 TD0_alpha_arg2_prevstage |
438 TD0_alpha_sel_arg2),
439
440 /* GL_ADD
441 * Cv = Cp + Cs
442 * Av = Ap As
443 */
444 (TD0_color_arg2_prevstage |
445 TD0_color_add_add |
446 TD0_color_sel_add |
447 TD0_alpha_arg2_prevstage |
448 TD0_alpha_sel_mul),
449 },
450 };
451
452 static const GLuint g400_alpha_combine[][MGA_MAX_COMBFUNC] =
453 {
454 /* Unit 0:
455 */
456 {
457 /* GL_REPLACE
458 * Cv = Cf
459 * Av = As
460 */
461 (TD0_color_arg2_diffuse |
462 TD0_color_sel_arg2 |
463 TD0_alpha_sel_arg1),
464
465 /* GL_MODULATE
466 * Cv = Cf
467 * Av = Af As
468 */
469 (TD0_color_arg2_diffuse |
470 TD0_color_sel_arg2 |
471 TD0_alpha_arg2_diffuse |
472 TD0_alpha_sel_mul),
473
474 /* GL_DECAL (undefined)
475 * Cv = Cf
476 * Av = Af
477 */
478 (TD0_color_arg2_diffuse |
479 TD0_color_sel_arg2 |
480 TD0_alpha_arg2_diffuse |
481 TD0_alpha_sel_arg2),
482
483 /* GL_ADD
484 * Cv = Cf
485 * Av = Af As
486 */
487 (TD0_color_arg2_diffuse |
488 TD0_color_sel_arg2 |
489 TD0_alpha_arg2_diffuse |
490 TD0_alpha_sel_mul),
491 },
492
493 /* Unit 1:
494 */
495 {
496 /* GL_REPLACE
497 * Cv = Cp
498 * Av = As
499 */
500 (TD0_color_arg2_prevstage |
501 TD0_color_sel_arg2 |
502 TD0_alpha_sel_arg1),
503
504 /* GL_MODULATE
505 * Cv = Cp
506 * Av = Ap As
507 */
508 (TD0_color_arg2_prevstage |
509 TD0_color_sel_arg2 |
510 TD0_alpha_arg2_prevstage |
511 TD0_alpha_sel_mul),
512
513 /* GL_DECAL (undefined)
514 * Cv = Cp
515 * Av = Ap
516 */
517 (TD0_color_arg2_prevstage |
518 TD0_color_sel_arg2 |
519 TD0_alpha_arg2_prevstage |
520 TD0_alpha_sel_arg2),
521
522 /* GL_ADD
523 * Cv = Cp
524 * Av = Ap As
525 */
526 (TD0_color_arg2_prevstage |
527 TD0_color_sel_arg2 |
528 TD0_alpha_arg2_prevstage |
529 TD0_alpha_sel_mul),
530 },
531 };
532
533 static GLboolean mgaUpdateTextureEnvBlend( GLcontext *ctx, int unit )
534 {
535 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
536 const int source = mmesa->tmu_source[unit];
537 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
538 const struct gl_texture_object *tObj = texUnit->_Current;
539 GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
540 GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
541
542 *reg = 0;
543
544 if (format == GL_ALPHA) {
545 /* Cv = Cf */
546 *reg |= (TD0_color_arg2_diffuse |
547 TD0_color_sel_arg2);
548 /* Av = Af As */
549 *reg |= (TD0_alpha_arg2_diffuse |
550 TD0_alpha_sel_mul);
551 return GL_TRUE;
552 }
553
554 /* C1 = Cf ( 1 - Cs ) */
555 *reg |= (TD0_color_arg1_inv_enable |
556 TD0_color_arg2_diffuse |
557 TD0_color_sel_mul);
558
559 if (format == GL_RGB || format == GL_LUMINANCE) {
560 /* A1 = Af */
561 *reg |= (TD0_alpha_arg2_diffuse |
562 TD0_alpha_sel_arg2);
563 } else
564 if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) {
565 /* A1 = Af As */
566 *reg |= (TD0_alpha_arg2_diffuse |
567 TD0_alpha_sel_mul);
568 } else
569 if (format == GL_INTENSITY) {
570 /* A1 = Af ( 1 - As ) */
571 *reg |= (TD0_alpha_arg1_inv_enable |
572 TD0_alpha_arg2_diffuse |
573 TD0_alpha_sel_mul);
574 }
575
576 if (RGB_ZERO(mmesa->envcolor[source]) &&
577 (format != GL_INTENSITY || ALPHA_ZERO(mmesa->envcolor[source])))
578 return GL_TRUE; /* all done */
579
580 if (ctx->Texture._EnabledUnits == 0x03)
581 return GL_FALSE; /* need both units */
582
583 mmesa->force_dualtex = GL_TRUE;
584 reg = &mmesa->setup.tdualstage1;
585 *reg = 0;
586
587 if (RGB_ZERO(mmesa->envcolor[source])) {
588 /* Cv = C1 */
589 *reg |= (TD0_color_arg2_prevstage |
590 TD0_color_sel_arg2);
591 } else
592 if (RGB_ONE(mmesa->envcolor[source])) {
593 /* Cv = C1 + Cs */
594 *reg |= (TD0_color_arg2_prevstage |
595 TD0_color_add_add |
596 TD0_color_sel_add);
597 } else
598 if (RGBA_EQUAL(mmesa->envcolor[source])) {
599 /* Cv = C1 + Cc Cs */
600 *reg |= (TD0_color_arg2_prevstage |
601 TD0_color_alpha_fcol |
602 TD0_color_arg2mul_alpha2 |
603 TD0_color_arg1add_mulout |
604 TD0_color_add_add |
605 TD0_color_sel_add);
606
607 mmesa->setup.fcol = mmesa->envcolor[source];
608 } else {
609 return GL_FALSE;
610 }
611
612 if (format != GL_INTENSITY || ALPHA_ZERO(mmesa->envcolor[source])) {
613 /* Av = A1 */
614 *reg |= (TD0_alpha_arg2_prevstage |
615 TD0_alpha_sel_arg2);
616 } else
617 if (ALPHA_ONE(mmesa->envcolor[source])) {
618 /* Av = A1 + As */
619 *reg |= (TD0_alpha_arg2_prevstage |
620 TD0_alpha_add_enable |
621 TD0_alpha_sel_add);
622 } else {
623 return GL_FALSE;
624 }
625
626 return GL_TRUE;
627 }
628
629 static void mgaUpdateTextureEnvG400( GLcontext *ctx, GLuint unit )
630 {
631 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
632 const int source = mmesa->tmu_source[unit];
633 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
634 const struct gl_texture_object *tObj = texUnit->_Current;
635 GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
636 mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
637 GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
638
639 if (tObj != ctx->Texture.Unit[source].Current2D &&
640 tObj != ctx->Texture.Unit[source].CurrentRect)
641 return;
642
643 switch (ctx->Texture.Unit[source].EnvMode) {
644 case GL_REPLACE:
645 if (format == GL_ALPHA) {
646 *reg = g400_alpha_combine[unit][MGA_REPLACE];
647 } else if (format == GL_RGB || format == GL_LUMINANCE) {
648 *reg = g400_color_combine[unit][MGA_REPLACE];
649 } else {
650 *reg = g400_color_alpha_combine[unit][MGA_REPLACE];
651 }
652 break;
653
654 case GL_MODULATE:
655 if (format == GL_ALPHA) {
656 *reg = g400_alpha_combine[unit][MGA_MODULATE];
657 } else if (format == GL_RGB || format == GL_LUMINANCE) {
658 *reg = g400_color_combine[unit][MGA_MODULATE];
659 } else {
660 *reg = g400_color_alpha_combine[unit][MGA_MODULATE];
661 }
662 break;
663
664 case GL_DECAL:
665 if (format == GL_RGB) {
666 *reg = g400_color_combine[unit][MGA_DECAL];
667 } else if (format == GL_RGBA) {
668 *reg = g400_color_alpha_combine[unit][MGA_DECAL];
669 if (ctx->Texture._EnabledUnits != 0x03) {
670 /* Linear blending mode needs dual texturing enabled */
671 *(reg+1) = (TD0_color_arg2_prevstage |
672 TD0_color_sel_arg2 |
673 TD0_alpha_arg2_prevstage |
674 TD0_alpha_sel_arg2);
675 mmesa->force_dualtex = GL_TRUE;
676 }
677 } else {
678 /* Undefined */
679 *reg = g400_alpha_combine[unit][MGA_DECAL];
680 }
681 break;
682
683 case GL_ADD:
684 if (format == GL_ALPHA) {
685 *reg = g400_alpha_combine[unit][MGA_ADD];
686 } else if (format == GL_RGB || format == GL_LUMINANCE) {
687 *reg = g400_color_combine[unit][MGA_ADD];
688 } else if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) {
689 *reg = g400_color_alpha_combine[unit][MGA_ADD];
690 } else if (format == GL_INTENSITY) {
691 /* Cv = Cf + Cs
692 * Av = Af + As
693 */
694 if (unit == 0) {
695 *reg = (TD0_color_arg2_diffuse |
696 TD0_color_add_add |
697 TD0_color_sel_add |
698 TD0_alpha_arg2_diffuse |
699 TD0_alpha_add_enable |
700 TD0_alpha_sel_add);
701 } else {
702 *reg = (TD0_color_arg2_prevstage |
703 TD0_color_add_add |
704 TD0_color_sel_add |
705 TD0_alpha_arg2_prevstage |
706 TD0_alpha_add_enable |
707 TD0_alpha_sel_add);
708 }
709 }
710 break;
711
712 case GL_BLEND:
713 if (!mgaUpdateTextureEnvBlend(ctx, unit))
714 t->texenv_fallback = GL_TRUE;
715 break;
716
717 case GL_COMBINE:
718 if (!mgaUpdateTextureEnvCombine(ctx, unit))
719 t->texenv_fallback = GL_TRUE;
720 break;
721 default:
722 break;
723 }
724 }
725
726 static void disable_tex( GLcontext *ctx, int unit )
727 {
728 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
729
730 /* Texture unit disabled */
731
732 if ( mmesa->CurrentTexObj[unit] != NULL ) {
733 /* The old texture is no longer bound to this texture unit.
734 * Mark it as such.
735 */
736
737 mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit);
738 mmesa->CurrentTexObj[unit] = NULL;
739 }
740
741 if ( unit != 0 && !mmesa->force_dualtex ) {
742 mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
743 }
744
745 if ( ctx->Texture._EnabledUnits == 0 ) {
746 mmesa->setup.dwgctl &= DC_opcod_MASK;
747 mmesa->setup.dwgctl |= DC_opcod_trap;
748 mmesa->hw.alpha_sel = AC_alphasel_diffused;
749 }
750
751 mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
752 }
753
754 static GLboolean enable_tex( GLcontext *ctx, int unit )
755 {
756 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
757 const int source = mmesa->tmu_source[unit];
758 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
759 const struct gl_texture_object *tObj = texUnit->_Current;
760 mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
761
762 /* Upload teximages (not pipelined)
763 */
764 if (t->base.dirty_images[0]) {
765 FLUSH_BATCH( mmesa );
766 mgaSetTexImages( mmesa, tObj );
767 if ( t->base.memBlock == NULL ) {
768 return GL_FALSE;
769 }
770 }
771
772 return GL_TRUE;
773 }
774
775 static GLboolean update_tex_common( GLcontext *ctx, int unit )
776 {
777 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
778 const int source = mmesa->tmu_source[unit];
779 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
780 struct gl_texture_object *tObj = texUnit->_Current;
781 mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
782
783 /* Fallback if there's a texture border */
784 if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
785 return GL_FALSE;
786 }
787
788
789 /* Update state if this is a different texture object to last
790 * time.
791 */
792 if ( mmesa->CurrentTexObj[unit] != t ) {
793 if ( mmesa->CurrentTexObj[unit] != NULL ) {
794 /* The old texture is no longer bound to this texture unit.
795 * Mark it as such.
796 */
797
798 mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit);
799 }
800
801 mmesa->CurrentTexObj[unit] = t;
802 t->base.bound |= (1UL << unit);
803
804 driUpdateTextureLRU( (driTextureObject *) t ); /* done too often */
805 }
806
807 /* register setup */
808 if ( unit == 1 ) {
809 mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
810 }
811
812 t->texenv_fallback = GL_FALSE;
813
814 /* Set this before mgaUpdateTextureEnvG400() since
815 * GL_ARB_texture_env_crossbar may have to disable texturing.
816 */
817 mmesa->setup.dwgctl &= DC_opcod_MASK;
818 mmesa->setup.dwgctl |= DC_opcod_texture_trap;
819
820 /* FIXME: The Radeon has some cached state so that it can avoid calling
821 * FIXME: UpdateTextureEnv in some cases. Is that possible here?
822 */
823 if (MGA_IS_G400(mmesa)) {
824 /* G400: Regardless of texture env mode, we use the alpha from the
825 * texture unit (AC_alphasel_fromtex) since it will have already
826 * been modulated by the incoming fragment color, if needed.
827 * We don't want (AC_alphasel_modulate) since that'll effectively
828 * do the modulation twice.
829 */
830 mmesa->hw.alpha_sel = AC_alphasel_fromtex;
831
832 mgaUpdateTextureEnvG400( ctx, unit );
833 } else {
834 mgaUpdateTextureEnvG200( ctx, unit );
835 }
836
837 t->setup.texctl2 &= TMC_dualtex_MASK;
838 if (ctx->Texture._EnabledUnits == 0x03 || mmesa->force_dualtex) {
839 t->setup.texctl2 |= TMC_dualtex_enable;
840 }
841
842 mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
843
844 FALLBACK( ctx, MGA_FALLBACK_BORDER_MODE, t->border_fallback );
845 return !t->border_fallback && !t->texenv_fallback;
846 }
847
848
849 static GLboolean updateTextureUnit( GLcontext *ctx, int unit )
850 {
851 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
852 const int source = mmesa->tmu_source[unit];
853 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
854
855
856 if ( texUnit->_ReallyEnabled == TEXTURE_2D_BIT ||
857 texUnit->_ReallyEnabled == TEXTURE_RECT_BIT ) {
858 return(enable_tex( ctx, unit ) &&
859 update_tex_common( ctx, unit ));
860 }
861 else if ( texUnit->_ReallyEnabled ) {
862 return GL_FALSE;
863 }
864 else {
865 disable_tex( ctx, unit );
866 return GL_TRUE;
867 }
868 }
869
870 /* The G400 is now programmed quite differently wrt texture environment.
871 */
872 void mgaUpdateTextureState( GLcontext *ctx )
873 {
874 mgaContextPtr mmesa = MGA_CONTEXT( ctx );
875 GLboolean ok;
876 unsigned i;
877
878 mmesa->force_dualtex = GL_FALSE;
879 mmesa->fcol_used = GL_FALSE;
880
881 /* This works around a quirk with the MGA hardware. If only OpenGL
882 * TEXTURE1 is enabled, then the hardware TEXTURE0 must be used. The
883 * hardware TEXTURE1 can ONLY be used when hardware TEXTURE0 is also used.
884 */
885
886 mmesa->tmu_source[0] = 0;
887 mmesa->tmu_source[1] = 1;
888
889 if ((ctx->Texture._EnabledUnits & 0x03) == 0x02) {
890 /* only texture 1 enabled */
891 mmesa->tmu_source[0] = 1;
892 mmesa->tmu_source[1] = 0;
893 }
894
895 for ( i = 0, ok = GL_TRUE
896 ; (i < ctx->Const.MaxTextureUnits) && ok
897 ; i++ ) {
898 ok = updateTextureUnit( ctx, i );
899 }
900
901 FALLBACK( ctx, MGA_FALLBACK_TEXTURE, !ok );
902 }