Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / tdfx / tdfx_texstate.c
1 /* -*- mode: c; c-basic-offset: 3 -*-
2  *
3  * Copyright 2000 VA Linux Systems Inc., Fremont, California.
4  *
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26
27 /*
28  * New fixes:
29  *      Daniel Borca <dborca@users.sourceforge.net>, 19 Jul 2004
30  *
31  * Original rewrite:
32  *      Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
33  *
34  * Authors:
35  *      Gareth Hughes <gareth@valinux.com>
36  *      Brian Paul <brianp@valinux.com>
37  *
38  */
39
40 #include "tdfx_state.h"
41 #include "tdfx_texman.h"
42 #include "tdfx_texstate.h"
43
44
45 /* =============================================================
46  * Texture
47  */
48
49 /*
50  * These macros are used below when handling COMBINE_EXT.
51  */
52 #define TEXENV_OPERAND_INVERTED(operand)                            \
53   (((operand) == GL_ONE_MINUS_SRC_ALPHA)                            \
54    || ((operand) == GL_ONE_MINUS_SRC_COLOR))
55 #define TEXENV_OPERAND_ALPHA(operand)                               \
56   (((operand) == GL_SRC_ALPHA) || ((operand) == GL_ONE_MINUS_SRC_ALPHA))
57 #define TEXENV_SETUP_ARG_A(param, source, operand, iteratedAlpha)   \
58     switch (source) {                                               \
59     case GL_TEXTURE:                                                \
60         param = GR_CMBX_LOCAL_TEXTURE_ALPHA;                        \
61         break;                                                      \
62     case GL_CONSTANT_EXT:                                           \
63         param = GR_CMBX_TMU_CALPHA;                                 \
64         break;                                                      \
65     case GL_PRIMARY_COLOR_EXT:                                      \
66         param = GR_CMBX_ITALPHA;                                    \
67         break;                                                      \
68     case GL_PREVIOUS_EXT:                                           \
69         param = iteratedAlpha;                                      \
70         break;                                                      \
71     default:                                                        \
72        /*                                                           \
73         * This is here just to keep from getting                    \
74         * compiler warnings.                                        \
75         */                                                          \
76         param = GR_CMBX_ZERO;                                       \
77         break;                                                      \
78     }
79
80 #define TEXENV_SETUP_ARG_RGB(param, source, operand, iteratedColor, iteratedAlpha) \
81     if (!TEXENV_OPERAND_ALPHA(operand)) {                           \
82         switch (source) {                                           \
83         case GL_TEXTURE:                                            \
84             param = GR_CMBX_LOCAL_TEXTURE_RGB;                      \
85             break;                                                  \
86         case GL_CONSTANT_EXT:                                       \
87             param = GR_CMBX_TMU_CCOLOR;                             \
88             break;                                                  \
89         case GL_PRIMARY_COLOR_EXT:                                  \
90             param = GR_CMBX_ITRGB;                                  \
91             break;                                                  \
92         case GL_PREVIOUS_EXT:                                       \
93             param = iteratedColor;                                  \
94             break;                                                  \
95         default:                                                    \
96            /*                                                       \
97             * This is here just to keep from getting                \
98             * compiler warnings.                                    \
99             */                                                      \
100             param = GR_CMBX_ZERO;                                   \
101             break;                                                  \
102         }                                                           \
103     } else {                                                        \
104         switch (source) {                                           \
105         case GL_TEXTURE:                                            \
106             param = GR_CMBX_LOCAL_TEXTURE_ALPHA;                    \
107             break;                                                  \
108         case GL_CONSTANT_EXT:                                       \
109             param = GR_CMBX_TMU_CALPHA;                             \
110             break;                                                  \
111         case GL_PRIMARY_COLOR_EXT:                                  \
112             param = GR_CMBX_ITALPHA;                                \
113             break;                                                  \
114         case GL_PREVIOUS_EXT:                                       \
115             param = iteratedAlpha;                                  \
116             break;                                                  \
117         default:                                                    \
118            /*                                                       \
119             * This is here just to keep from getting                \
120             * compiler warnings.                                    \
121             */                                                      \
122             param = GR_CMBX_ZERO;                                   \
123             break;                                                  \
124         }                                                           \
125     }
126
127 #define TEXENV_SETUP_MODE_RGB(param, operand)                       \
128     switch (operand) {                                              \
129     case GL_SRC_COLOR:                                              \
130     case GL_SRC_ALPHA:                                              \
131         param = GR_FUNC_MODE_X;                                     \
132         break;                                                      \
133     case GL_ONE_MINUS_SRC_ALPHA:                                    \
134     case GL_ONE_MINUS_SRC_COLOR:                                    \
135         param = GR_FUNC_MODE_ONE_MINUS_X;                           \
136         break;                                                      \
137     default:                                                        \
138         param = GR_FUNC_MODE_ZERO;                                  \
139         break;                                                      \
140     }
141
142 #define TEXENV_SETUP_MODE_A(param, operand)                         \
143     switch (operand) {                                              \
144     case GL_SRC_ALPHA:                                              \
145         param = GR_FUNC_MODE_X;                                     \
146         break;                                                      \
147     case GL_ONE_MINUS_SRC_ALPHA:                                    \
148         param = GR_FUNC_MODE_ONE_MINUS_X;                           \
149         break;                                                      \
150     default:                                                        \
151         param = GR_FUNC_MODE_ZERO;                                  \
152         break;                                                      \
153     }
154
155
156
157 /*
158  * Setup a texture environment on Voodoo5.
159  * Return GL_TRUE for success, GL_FALSE for failure.
160  * If we fail, we'll have to use software rendering.
161  */
162 static GLboolean
163 SetupTexEnvNapalm(struct gl_context *ctx, GLboolean useIteratedRGBA,
164                   const struct gl_texture_unit *texUnit, GLenum baseFormat,
165                   struct tdfx_texcombine_ext *env)
166 {
167     tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
168     GrTCCUColor_t incomingRGB, incomingAlpha;
169     const GLenum envMode = texUnit->EnvMode;
170
171     if (useIteratedRGBA) {
172         incomingRGB = GR_CMBX_ITRGB;
173         incomingAlpha = GR_CMBX_ITALPHA;
174     }
175     else {
176         incomingRGB = GR_CMBX_OTHER_TEXTURE_RGB;
177         incomingAlpha = GR_CMBX_OTHER_TEXTURE_ALPHA;
178     }
179
180     /* invariant: */
181     env->Color.Shift = 0;
182     env->Color.Invert = FXFALSE;
183     env->Alpha.Shift = 0;
184     env->Alpha.Invert = FXFALSE;
185
186     switch (envMode) {
187     case GL_REPLACE:
188         /* -- Setup RGB combiner */
189         if (baseFormat == GL_ALPHA) {
190             /* Rv = Rf */
191             env->Color.SourceA = incomingRGB;
192         }
193         else {
194             /* Rv = Rt */
195             env->Color.SourceA = GR_CMBX_LOCAL_TEXTURE_RGB;
196         }
197         env->Color.ModeA = GR_FUNC_MODE_X;
198         env->Color.SourceB = GR_CMBX_ZERO;
199         env->Color.ModeB = GR_FUNC_MODE_ZERO;
200         env->Color.SourceC = GR_CMBX_ZERO;
201         env->Color.InvertC = FXTRUE;
202         env->Color.SourceD = GR_CMBX_ZERO;
203         env->Color.InvertD = FXFALSE;
204         /* -- Setup Alpha combiner */
205         if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) {
206             /* Av = Af */
207            env->Alpha.SourceD = incomingAlpha;
208         }
209         else {
210             /* Av = At */
211            env->Alpha.SourceD = GR_CMBX_LOCAL_TEXTURE_ALPHA;
212         }
213         env->Alpha.SourceA = GR_CMBX_ITALPHA;
214         env->Alpha.ModeA = GR_FUNC_MODE_ZERO;
215         env->Alpha.SourceB = GR_CMBX_ITALPHA;
216         env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
217         env->Alpha.SourceC = GR_CMBX_ZERO;
218         env->Alpha.InvertC = FXFALSE;
219         env->Alpha.InvertD = FXFALSE;
220         break;
221
222     case GL_MODULATE:
223         /* -- Setup RGB combiner */
224         if (baseFormat == GL_ALPHA) {
225             /* Rv = Rf */
226            env->Color.SourceC = GR_CMBX_ZERO;
227            env->Color.InvertC = FXTRUE;
228         }
229         else {
230             /* Result = Frag * Tex */
231            env->Color.SourceC = GR_CMBX_LOCAL_TEXTURE_RGB;
232            env->Color.InvertC = FXFALSE;
233         }
234         env->Color.SourceA = incomingRGB;
235         env->Color.ModeA = GR_FUNC_MODE_X;
236         env->Color.SourceB = GR_CMBX_ZERO;
237         env->Color.ModeB = GR_FUNC_MODE_ZERO;
238         env->Color.SourceD = GR_CMBX_ZERO;
239         env->Color.InvertD = FXFALSE;
240         /* -- Setup Alpha combiner */
241         if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) {
242             /* Av = Af */
243            env->Alpha.SourceA = incomingAlpha;
244            env->Alpha.SourceC = GR_CMBX_ZERO;
245            env->Alpha.InvertC = FXTRUE;
246         }
247         else {
248             /* Av = Af * At */
249            env->Alpha.SourceA = GR_CMBX_LOCAL_TEXTURE_ALPHA;
250            env->Alpha.SourceC = incomingAlpha;
251            env->Alpha.InvertC = FXFALSE;
252         }
253         env->Alpha.ModeA = GR_FUNC_MODE_X;
254         env->Alpha.SourceB = GR_CMBX_ITALPHA;
255         env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
256         env->Alpha.SourceD = GR_CMBX_ZERO;
257         env->Alpha.InvertD = FXFALSE;
258         break;
259
260     case GL_DECAL:
261         /* -- Setup RGB combiner */
262         if (baseFormat == GL_RGB) {
263             /* Rv = Rt */
264            env->Color.SourceB = GR_CMBX_ZERO;
265            env->Color.ModeB = GR_FUNC_MODE_X;
266            env->Color.SourceC = GR_CMBX_ZERO;
267            env->Color.InvertC = FXTRUE;
268            env->Color.SourceD = GR_CMBX_ZERO;
269            env->Color.InvertD = FXFALSE;
270         }
271         else {
272             /* Rv = Rf * (1 - At) + Rt * At */
273            env->Color.SourceB = incomingRGB;
274            env->Color.ModeB = GR_FUNC_MODE_NEGATIVE_X;
275            env->Color.SourceC = GR_CMBX_LOCAL_TEXTURE_ALPHA;
276            env->Color.InvertC = FXFALSE;
277            env->Color.SourceD = GR_CMBX_B;
278            env->Color.InvertD = FXFALSE;
279         }
280         env->Color.SourceA = GR_CMBX_LOCAL_TEXTURE_RGB;
281         env->Color.ModeA = GR_FUNC_MODE_X;
282         /* -- Setup Alpha combiner */
283         /* Av = Af */
284         env->Alpha.SourceA = incomingAlpha;
285         env->Alpha.ModeA = GR_FUNC_MODE_X;
286         env->Alpha.SourceB = GR_CMBX_ITALPHA;
287         env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
288         env->Alpha.SourceC = GR_CMBX_ZERO;
289         env->Alpha.InvertC = FXTRUE;
290         env->Alpha.SourceD = GR_CMBX_ZERO;
291         env->Alpha.InvertD = FXFALSE;
292         break;
293
294     case GL_BLEND:
295         /* -- Setup RGB combiner */
296         if (baseFormat == GL_ALPHA) {
297             /* Rv = Rf */
298             env->Color.SourceA = incomingRGB;
299             env->Color.ModeA = GR_FUNC_MODE_X;
300             env->Color.SourceB = GR_CMBX_ZERO;
301             env->Color.ModeB = GR_FUNC_MODE_ZERO;
302             env->Color.SourceC = GR_CMBX_ZERO;
303             env->Color.InvertC = FXTRUE;
304             env->Color.SourceD = GR_CMBX_ZERO;
305             env->Color.InvertD = FXFALSE;
306         }
307         else {
308             /* Rv = Rf * (1 - Rt) + Rc * Rt */
309             env->Color.SourceA = GR_CMBX_TMU_CCOLOR;
310             env->Color.ModeA = GR_FUNC_MODE_X;
311             env->Color.SourceB = incomingRGB;
312             env->Color.ModeB = GR_FUNC_MODE_NEGATIVE_X;
313             env->Color.SourceC = GR_CMBX_LOCAL_TEXTURE_RGB;
314             env->Color.InvertC = FXFALSE;
315             env->Color.SourceD = GR_CMBX_B;
316             env->Color.InvertD = FXFALSE;
317         }
318         /* -- Setup Alpha combiner */
319         if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) {
320             /* Av = Af */
321             env->Alpha.SourceA = incomingAlpha;
322             env->Alpha.ModeA = GR_FUNC_MODE_X;
323             env->Alpha.SourceB = GR_CMBX_ZERO;
324             env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
325             env->Alpha.SourceC = GR_CMBX_ZERO;
326             env->Alpha.InvertC = FXTRUE;
327             env->Alpha.SourceD = GR_CMBX_ZERO;
328             env->Alpha.InvertD = FXFALSE;
329         }
330         else if (baseFormat == GL_INTENSITY) {
331             /* Av = Af * (1 - It) + Ac * It */
332             env->Alpha.SourceA = GR_CMBX_TMU_CALPHA;
333             env->Alpha.ModeA = GR_FUNC_MODE_X;
334             env->Alpha.SourceB = incomingAlpha;
335             env->Alpha.ModeB = GR_FUNC_MODE_NEGATIVE_X;
336             env->Alpha.SourceC = GR_CMBX_LOCAL_TEXTURE_ALPHA;
337             env->Alpha.InvertC = FXFALSE;
338             env->Alpha.SourceD = GR_CMBX_B;
339             env->Alpha.InvertD = FXFALSE;
340         }
341         else {
342             /* Av = Af * At */
343             env->Alpha.SourceA = GR_CMBX_LOCAL_TEXTURE_ALPHA;
344             env->Alpha.ModeA = GR_FUNC_MODE_X;
345             env->Alpha.SourceB = GR_CMBX_ITALPHA;
346             env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
347             env->Alpha.SourceC = incomingAlpha;
348             env->Alpha.InvertC = FXFALSE;
349             env->Alpha.SourceD = GR_CMBX_ZERO;
350             env->Alpha.InvertD = FXFALSE;
351         }
352         /* Also have to set up the tex env constant color */
353         env->EnvColor = PACK_RGBA32(texUnit->EnvColor[0] * 255.0F,
354                                     texUnit->EnvColor[1] * 255.0F,
355                                     texUnit->EnvColor[2] * 255.0F,
356                                     texUnit->EnvColor[3] * 255.0F);
357         break;
358     case GL_ADD:
359         /* -- Setup RGB combiner */
360         if (baseFormat == GL_ALPHA) {
361             /* Rv = Rf */
362            env->Color.SourceB = GR_CMBX_ZERO;
363            env->Color.ModeB = GR_FUNC_MODE_ZERO;
364         }
365         else {
366             /* Rv = Rf + Tt */
367            env->Color.SourceB = GR_CMBX_LOCAL_TEXTURE_RGB;
368            env->Color.ModeB = GR_FUNC_MODE_X;
369         }
370         env->Color.SourceA = incomingRGB;
371         env->Color.ModeA = GR_FUNC_MODE_X;
372         env->Color.SourceC = GR_CMBX_ZERO;
373         env->Color.InvertC = FXTRUE;
374         env->Color.SourceD = GR_CMBX_ZERO;
375         env->Color.InvertD = FXFALSE;
376         /* -- Setup Alpha combiner */
377         if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) {
378             /* Av = Af */
379            env->Alpha.SourceA = incomingAlpha;
380            env->Alpha.SourceB = GR_CMBX_ITALPHA;
381            env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
382            env->Alpha.SourceC = GR_CMBX_ZERO;
383            env->Alpha.InvertC = FXTRUE;
384
385         }
386         else if (baseFormat == GL_INTENSITY) {
387             /* Av = Af + It */
388            env->Alpha.SourceA = incomingAlpha;
389            env->Alpha.SourceB = GR_CMBX_LOCAL_TEXTURE_ALPHA;
390            env->Alpha.ModeB = GR_FUNC_MODE_X;
391            env->Alpha.SourceC = GR_CMBX_ZERO;
392            env->Alpha.InvertC = FXTRUE;
393         }
394         else {
395             /* Av = Af * At */
396            env->Alpha.SourceA = GR_CMBX_LOCAL_TEXTURE_ALPHA;
397            env->Alpha.SourceB = GR_CMBX_ITALPHA;
398            env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
399            env->Alpha.SourceC = incomingAlpha;
400            env->Alpha.InvertC = FXFALSE;
401         }
402         env->Alpha.ModeA = GR_FUNC_MODE_X;
403         env->Alpha.SourceD = GR_CMBX_ZERO;
404         env->Alpha.InvertD = FXFALSE;
405         break;
406
407     case GL_COMBINE_EXT:
408         {
409             FxU32 A_RGB, B_RGB, C_RGB, D_RGB;
410             FxU32 Amode_RGB, Bmode_RGB;
411             FxBool Cinv_RGB, Dinv_RGB, Ginv_RGB;
412             FxU32 Shift_RGB;
413             FxU32 A_A, B_A, C_A, D_A;
414             FxU32 Amode_A, Bmode_A;
415             FxBool Cinv_A, Dinv_A, Ginv_A;
416             FxU32 Shift_A;
417
418            /*
419             *
420             * In the formulas below, we write:
421             *  o "1(x)" for the identity function applied to x,
422             *    so 1(x) = x.
423             *  o "0(x)" for the constant function 0, so
424             *    0(x) = 0 for all values of x.
425             *
426             * Calculate the color combination.
427             */
428             Shift_RGB = texUnit->Combine.ScaleShiftRGB;
429             Shift_A = texUnit->Combine.ScaleShiftA;
430             switch (texUnit->Combine.ModeRGB) {
431             case GL_REPLACE:
432                /*
433                 * The formula is: Arg0
434                 * We implement this by the formula:
435                 *   (Arg0 + 0(0))*(1-0) + 0
436                 */
437                 TEXENV_SETUP_ARG_RGB(A_RGB,
438                                      texUnit->Combine.SourceRGB[0],
439                                      texUnit->Combine.OperandRGB[0],
440                                      incomingRGB, incomingAlpha);
441                 TEXENV_SETUP_MODE_RGB(Amode_RGB,
442                                       texUnit->Combine.OperandRGB[0]);
443                 B_RGB = C_RGB = D_RGB = GR_CMBX_ZERO;
444                 Bmode_RGB = GR_FUNC_MODE_ZERO;
445                 Cinv_RGB = FXTRUE;
446                 Dinv_RGB = Ginv_RGB = FXFALSE;
447                 break;
448             case GL_MODULATE:
449                /*
450                 * The formula is: Arg0 * Arg1
451                 *
452                 * We implement this by the formula
453                 *   (Arg0 + 0(0)) * Arg1 + 0(0)
454                 */
455                 TEXENV_SETUP_ARG_RGB(A_RGB,
456                                      texUnit->Combine.SourceRGB[0],
457                                      texUnit->Combine.OperandRGB[0],
458                                      incomingRGB, incomingAlpha);
459                 TEXENV_SETUP_MODE_RGB(Amode_RGB,
460                                       texUnit->Combine.OperandRGB[0]);
461                 B_RGB = GR_CMBX_ZERO;
462                 Bmode_RGB = GR_CMBX_ZERO;
463                 TEXENV_SETUP_ARG_RGB(C_RGB,
464                                      texUnit->Combine.SourceRGB[1],
465                                      texUnit->Combine.OperandRGB[1],
466                                      incomingRGB, incomingAlpha);
467                 Cinv_RGB = TEXENV_OPERAND_INVERTED
468                                (texUnit->Combine.OperandRGB[1]);
469                 D_RGB = GR_CMBX_ZERO;
470                 Dinv_RGB = Ginv_RGB = FXFALSE;
471                 break;
472             case GL_ADD:
473                /*
474                 * The formula is Arg0 + Arg1
475                 */
476                 TEXENV_SETUP_ARG_RGB(A_RGB,
477                                      texUnit->Combine.SourceRGB[0],
478                                      texUnit->Combine.OperandRGB[0],
479                                      incomingRGB, incomingAlpha);
480                 TEXENV_SETUP_MODE_RGB(Amode_RGB,
481                                       texUnit->Combine.OperandRGB[0]);
482                 TEXENV_SETUP_ARG_RGB(B_RGB,
483                                      texUnit->Combine.SourceRGB[1],
484                                      texUnit->Combine.OperandRGB[1],
485                                      incomingRGB, incomingAlpha);
486                 TEXENV_SETUP_MODE_RGB(Bmode_RGB,
487                                       texUnit->Combine.OperandRGB[1]);
488                 C_RGB = D_RGB = GR_CMBX_ZERO;
489                 Cinv_RGB = FXTRUE;
490                 Dinv_RGB = Ginv_RGB = FXFALSE;
491                 break;
492             case GL_ADD_SIGNED_EXT:
493                /*
494                 * The formula is: Arg0 + Arg1 - 0.5.
495                 * We compute this by calculating:
496                 *      (Arg0 - 1/2) + Arg1         if op0 is SRC_{COLOR,ALPHA}
497                 *      Arg0 + (Arg1 - 1/2)         if op1 is SRC_{COLOR,ALPHA}
498                 * If both op0 and op1 are ONE_MINUS_SRC_{COLOR,ALPHA}
499                 * we cannot implement the formula properly.
500                 */
501                 TEXENV_SETUP_ARG_RGB(A_RGB,
502                                      texUnit->Combine.SourceRGB[0],
503                                      texUnit->Combine.OperandRGB[0],
504                                      incomingRGB, incomingAlpha);
505                 TEXENV_SETUP_ARG_RGB(B_RGB,
506                                      texUnit->Combine.SourceRGB[1],
507                                      texUnit->Combine.OperandRGB[1],
508                                      incomingRGB, incomingAlpha);
509                 if (!TEXENV_OPERAND_INVERTED(texUnit->Combine.OperandRGB[0])) {
510                    /*
511                     * A is not inverted.  So, choose it.
512                     */
513                     Amode_RGB = GR_FUNC_MODE_X_MINUS_HALF;
514                     if (!TEXENV_OPERAND_INVERTED
515                             (texUnit->Combine.OperandRGB[1])) {
516                         Bmode_RGB = GR_FUNC_MODE_X;
517                     }
518                     else {
519                         Bmode_RGB = GR_FUNC_MODE_ONE_MINUS_X;
520                     }
521                 }
522                 else {
523                    /*
524                     * A is inverted, so try to subtract 1/2
525                     * from B.
526                     */
527                     Amode_RGB = GR_FUNC_MODE_ONE_MINUS_X;
528                     if (!TEXENV_OPERAND_INVERTED
529                             (texUnit->Combine.OperandRGB[1])) {
530                         Bmode_RGB = GR_FUNC_MODE_X_MINUS_HALF;
531                     }
532                     else {
533                        /*
534                         * Both are inverted.  This is the case
535                         * we cannot handle properly.  We just
536                         * choose to not add the - 1/2.
537                         */
538                         Bmode_RGB = GR_FUNC_MODE_ONE_MINUS_X;
539                         return GL_FALSE;
540                     }
541                 }
542                 C_RGB = D_RGB = GR_CMBX_ZERO;
543                 Cinv_RGB = FXTRUE;
544                 Dinv_RGB = Ginv_RGB = FXFALSE;
545                 break;
546             case GL_INTERPOLATE_EXT:
547                /*
548                 * The formula is: Arg0 * Arg2 + Arg1 * (1 - Arg2).
549                 * We compute this by the formula:
550                 *            (Arg0 - Arg1) * Arg2 + Arg1
551                 *               == Arg0 * Arg2 - Arg1 * Arg2 + Arg1
552                 *               == Arg0 * Arg2 + Arg1 * (1 - Arg2)
553                 * However, if both Arg1 is ONE_MINUS_X, the HW does
554                 * not support it properly.
555                 */
556                 TEXENV_SETUP_ARG_RGB(A_RGB,
557                                      texUnit->Combine.SourceRGB[0],
558                                      texUnit->Combine.OperandRGB[0],
559                                      incomingRGB, incomingAlpha);
560                 TEXENV_SETUP_MODE_RGB(Amode_RGB,
561                                       texUnit->Combine.OperandRGB[0]);
562                 TEXENV_SETUP_ARG_RGB(B_RGB,
563                                      texUnit->Combine.SourceRGB[1],
564                                      texUnit->Combine.OperandRGB[1],
565                                      incomingRGB, incomingAlpha);
566                 if (TEXENV_OPERAND_INVERTED(texUnit->Combine.OperandRGB[1])) {
567                    /*
568                     * This case is wrong.
569                     */
570                    Bmode_RGB = GR_FUNC_MODE_NEGATIVE_X;
571                    return GL_FALSE;
572                 }
573                 else {
574                     Bmode_RGB = GR_FUNC_MODE_NEGATIVE_X;
575                 }
576                /*
577                 * The Source/Operand for the C value must
578                 * specify some kind of alpha value.
579                 */
580                 TEXENV_SETUP_ARG_A(C_RGB,
581                                    texUnit->Combine.SourceRGB[2],
582                                    texUnit->Combine.OperandRGB[2],
583                                    incomingAlpha);
584                 Cinv_RGB = FXFALSE;
585                 D_RGB = GR_CMBX_B;
586                 Dinv_RGB = Ginv_RGB = FXFALSE;
587                 break;
588             default:
589                /*
590                 * This is here mostly to keep from getting
591                 * a compiler warning about these not being set.
592                 * However, this should set all the texture values
593                 * to zero.
594                 */
595                 A_RGB = B_RGB = C_RGB = D_RGB = GR_CMBX_ZERO;
596                 Amode_RGB = Bmode_RGB = GR_FUNC_MODE_X;
597                 Cinv_RGB = Dinv_RGB = Ginv_RGB = FXFALSE;
598                 break;
599             }
600            /*
601             * Calculate the alpha combination.
602             */
603             switch (texUnit->Combine.ModeA) {
604             case GL_REPLACE:
605                /*
606                 * The formula is: Arg0
607                 * We implement this by the formula:
608                 *   (Arg0 + 0(0))*(1-0) + 0
609                 */
610                 TEXENV_SETUP_ARG_A(A_A,
611                                    texUnit->Combine.SourceA[0],
612                                    texUnit->Combine.OperandA[0],
613                                    incomingAlpha);
614                 TEXENV_SETUP_MODE_A(Amode_A,
615                                     texUnit->Combine.OperandA[0]);
616                 B_A = GR_CMBX_ITALPHA;
617                 Bmode_A = GR_FUNC_MODE_ZERO;
618                 C_A = D_A = GR_CMBX_ZERO;
619                 Cinv_A = FXTRUE;
620                 Dinv_A = Ginv_A = FXFALSE;
621                 break;
622             case GL_MODULATE:
623                /*
624                 * The formula is: Arg0 * Arg1
625                 *
626                 * We implement this by the formula
627                 *   (Arg0 + 0(0)) * Arg1 + 0(0)
628                 */
629                 TEXENV_SETUP_ARG_A(A_A,
630                                    texUnit->Combine.SourceA[0],
631                                    texUnit->Combine.OperandA[0],
632                                    incomingAlpha);
633                 TEXENV_SETUP_MODE_A(Amode_A,
634                                     texUnit->Combine.OperandA[0]);
635                 B_A = GR_CMBX_ZERO;
636                 Bmode_A = GR_CMBX_ZERO;
637                 TEXENV_SETUP_ARG_A(C_A,
638                                    texUnit->Combine.SourceA[1],
639                                    texUnit->Combine.OperandA[1],
640                                    incomingAlpha);
641                 Cinv_A = TEXENV_OPERAND_INVERTED
642                                (texUnit->Combine.OperandA[1]);
643                 D_A = GR_CMBX_ZERO;
644                 Dinv_A = Ginv_A = FXFALSE;
645                 break;
646             case GL_ADD:
647                /*
648                 * The formula is Arg0 + Arg1
649                 */
650                 TEXENV_SETUP_ARG_A(A_A,
651                                    texUnit->Combine.SourceA[0],
652                                    texUnit->Combine.OperandA[0],
653                                    incomingAlpha);
654                 TEXENV_SETUP_MODE_A(Amode_A,
655                                     texUnit->Combine.OperandA[0]);
656                 TEXENV_SETUP_ARG_A(B_A,
657                                    texUnit->Combine.SourceA[1],
658                                    texUnit->Combine.OperandA[1],
659                                    incomingAlpha);
660                 TEXENV_SETUP_MODE_A(Bmode_A,
661                                     texUnit->Combine.OperandA[1]);
662                 C_A = D_A = GR_CMBX_ZERO;
663                 Cinv_A = FXTRUE;
664                 Dinv_A = Ginv_A = FXFALSE;
665                 break;
666             case GL_ADD_SIGNED_EXT:
667                /*
668                 * The formula is: Arg0 + Arg1 - 0.5.
669                 * We compute this by calculating:
670                 *      (Arg0 - 1/2) + Arg1         if op0 is SRC_{COLOR,ALPHA}
671                 *      Arg0 + (Arg1 - 1/2)         if op1 is SRC_{COLOR,ALPHA}
672                 * If both op0 and op1 are ONE_MINUS_SRC_{COLOR,ALPHA}
673                 * we cannot implement the formula properly.
674                 */
675                 TEXENV_SETUP_ARG_A(A_A,
676                                    texUnit->Combine.SourceA[0],
677                                    texUnit->Combine.OperandA[0],
678                                    incomingAlpha);
679                 TEXENV_SETUP_ARG_A(B_A,
680                                    texUnit->Combine.SourceA[1],
681                                    texUnit->Combine.OperandA[1],
682                                    incomingAlpha);
683                 if (!TEXENV_OPERAND_INVERTED(texUnit->Combine.OperandA[0])) {
684                    /*
685                     * A is not inverted.  So, choose it.
686                     */
687                     Amode_A = GR_FUNC_MODE_X_MINUS_HALF;
688                     if (!TEXENV_OPERAND_INVERTED
689                             (texUnit->Combine.OperandA[1])) {
690                         Bmode_A = GR_FUNC_MODE_X;
691                     } else {
692                         Bmode_A = GR_FUNC_MODE_ONE_MINUS_X;
693                     }
694                 } else {
695                    /*
696                     * A is inverted, so try to subtract 1/2
697                     * from B.
698                     */
699                     Amode_A = GR_FUNC_MODE_ONE_MINUS_X;
700                     if (!TEXENV_OPERAND_INVERTED
701                             (texUnit->Combine.OperandA[1])) {
702                         Bmode_A = GR_FUNC_MODE_X_MINUS_HALF;
703                     } else {
704                        /*
705                         * Both are inverted.  This is the case
706                         * we cannot handle properly.  We just
707                         * choose to not add the - 1/2.
708                         */
709                         Bmode_A = GR_FUNC_MODE_ONE_MINUS_X;
710                         return GL_FALSE;
711                     }
712                 }
713                 C_A = D_A = GR_CMBX_ZERO;
714                 Cinv_A = FXTRUE;
715                 Dinv_A = Ginv_A = FXFALSE;
716                 break;
717             case GL_INTERPOLATE_EXT:
718                /*
719                 * The formula is: Arg0 * Arg2 + Arg1 * (1 - Arg2).
720                 * We compute this by the formula:
721                 *            (Arg0 - Arg1) * Arg2 + Arg1
722                 *               == Arg0 * Arg2 - Arg1 * Arg2 + Arg1
723                 *               == Arg0 * Arg2 + Arg1 * (1 - Arg2)
724                 * However, if both Arg1 is ONE_MINUS_X, the HW does
725                 * not support it properly.
726                 */
727                 TEXENV_SETUP_ARG_A(A_A,
728                                    texUnit->Combine.SourceA[0],
729                                    texUnit->Combine.OperandA[0],
730                                    incomingAlpha);
731                 TEXENV_SETUP_MODE_A(Amode_A,
732                                     texUnit->Combine.OperandA[0]);
733                 TEXENV_SETUP_ARG_A(B_A,
734                                    texUnit->Combine.SourceA[1],
735                                    texUnit->Combine.OperandA[1],
736                                    incomingAlpha);
737                 if (!TEXENV_OPERAND_INVERTED(texUnit->Combine.OperandA[1])) {
738                     Bmode_A = GR_FUNC_MODE_NEGATIVE_X;
739                 }
740                 else {
741                    /*
742                     * This case is wrong.
743                     */
744                     Bmode_A = GR_FUNC_MODE_NEGATIVE_X;
745                     return GL_FALSE;
746                 }
747                /*
748                 * The Source/Operand for the C value must
749                 * specify some kind of alpha value.
750                 */
751                 TEXENV_SETUP_ARG_A(C_A,
752                                    texUnit->Combine.SourceA[2],
753                                    texUnit->Combine.OperandA[2],
754                                    incomingAlpha);
755                 Cinv_A = FXFALSE;
756                 D_A = GR_CMBX_B;
757                 Dinv_A = Ginv_A = FXFALSE;
758                 break;
759             default:
760                /*
761                 * This is here mostly to keep from getting
762                 * a compiler warning about these not being set.
763                 * However, this should set all the alpha values
764                 * to one.
765                 */
766                 A_A = B_A = C_A = D_A = GR_CMBX_ZERO;
767                 Amode_A = Bmode_A = GR_FUNC_MODE_X;
768                 Cinv_A = Dinv_A = FXFALSE;
769                 Ginv_A = FXTRUE;
770                 break;
771             }
772            /*
773             * Save the parameters.
774             */
775             env->Color.SourceA = A_RGB;
776             env->Color.ModeA = Amode_RGB;
777             env->Color.SourceB = B_RGB;
778             env->Color.ModeB = Bmode_RGB;
779             env->Color.SourceC = C_RGB;
780             env->Color.InvertC = Cinv_RGB;
781             env->Color.SourceD = D_RGB;
782             env->Color.InvertD = Dinv_RGB;
783             env->Color.Shift = Shift_RGB;
784             env->Color.Invert = Ginv_RGB;
785             env->Alpha.SourceA = A_A;
786             env->Alpha.ModeA = Amode_A;
787             env->Alpha.SourceB = B_A;
788             env->Alpha.ModeB = Bmode_A;
789             env->Alpha.SourceC = C_A;
790             env->Alpha.InvertC = Cinv_A;
791             env->Alpha.SourceD = D_A;
792             env->Alpha.InvertD = Dinv_A;
793             env->Alpha.Shift = Shift_A;
794             env->Alpha.Invert = Ginv_A;
795             env->EnvColor = PACK_RGBA32(texUnit->EnvColor[0] * 255.0F,
796                                         texUnit->EnvColor[1] * 255.0F,
797                                         texUnit->EnvColor[2] * 255.0F,
798                                         texUnit->EnvColor[3] * 255.0F);
799         }
800         break;
801
802     default:
803         _mesa_problem(ctx, "%s: Bad envMode", __FUNCTION__);
804     }
805
806     fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_ENV;
807
808     fxMesa->ColorCombineExt.SourceA = GR_CMBX_TEXTURE_RGB;
809     fxMesa->ColorCombineExt.ModeA = GR_FUNC_MODE_X,
810     fxMesa->ColorCombineExt.SourceB = GR_CMBX_ZERO;
811     fxMesa->ColorCombineExt.ModeB = GR_FUNC_MODE_X;
812     fxMesa->ColorCombineExt.SourceC = GR_CMBX_ZERO;
813     fxMesa->ColorCombineExt.InvertC = FXTRUE;
814     fxMesa->ColorCombineExt.SourceD = GR_CMBX_ZERO;
815     fxMesa->ColorCombineExt.InvertD = FXFALSE;
816     fxMesa->ColorCombineExt.Shift = 0;
817     fxMesa->ColorCombineExt.Invert = FXFALSE;
818     fxMesa->dirty |= TDFX_UPLOAD_COLOR_COMBINE;
819     fxMesa->AlphaCombineExt.SourceA = GR_CMBX_TEXTURE_ALPHA;
820     fxMesa->AlphaCombineExt.ModeA = GR_FUNC_MODE_X;
821     fxMesa->AlphaCombineExt.SourceB = GR_CMBX_ZERO;
822     fxMesa->AlphaCombineExt.ModeB = GR_FUNC_MODE_X;
823     fxMesa->AlphaCombineExt.SourceC = GR_CMBX_ZERO;
824     fxMesa->AlphaCombineExt.InvertC = FXTRUE;
825     fxMesa->AlphaCombineExt.SourceD = GR_CMBX_ZERO;
826     fxMesa->AlphaCombineExt.InvertD = FXFALSE;
827     fxMesa->AlphaCombineExt.Shift = 0;
828     fxMesa->AlphaCombineExt.Invert = FXFALSE;
829     fxMesa->dirty |= TDFX_UPLOAD_ALPHA_COMBINE;
830     return GL_TRUE; /* success */
831 }
832
833
834
835 /*
836  * Setup the Voodoo3 texture environment for a single texture unit.
837  * Return GL_TRUE for success, GL_FALSE for failure.
838  * If failure, we'll use software rendering.
839  */
840 static GLboolean
841 SetupSingleTexEnvVoodoo3(struct gl_context *ctx, int unit,
842                          GLenum envMode, GLenum baseFormat)
843 {
844    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
845    GrCombineLocal_t localc, locala;
846    struct tdfx_combine alphaComb, colorComb;
847
848    if (1 /*iteratedRGBA*/)
849       localc = locala = GR_COMBINE_LOCAL_ITERATED;
850    else
851       localc = locala = GR_COMBINE_LOCAL_CONSTANT;
852
853    switch (envMode) {
854    case GL_DECAL:
855       alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
856       alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
857       alphaComb.Local = locala;
858       alphaComb.Other = GR_COMBINE_OTHER_NONE;
859       alphaComb.Invert = FXFALSE;
860       colorComb.Function = GR_COMBINE_FUNCTION_BLEND;
861       colorComb.Factor = GR_COMBINE_FACTOR_TEXTURE_ALPHA;
862       colorComb.Local = localc;
863       colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
864       colorComb.Invert = FXFALSE;
865       break;
866    case GL_MODULATE:
867       alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
868       alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
869       alphaComb.Local = locala;
870       alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
871       alphaComb.Invert = FXFALSE;
872       if (baseFormat == GL_ALPHA) {
873          colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
874          colorComb.Factor = GR_COMBINE_FACTOR_NONE;
875          colorComb.Local = localc;
876          colorComb.Other = GR_COMBINE_OTHER_NONE;
877          colorComb.Invert = FXFALSE;
878       }
879       else {
880          colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
881          colorComb.Factor = GR_COMBINE_FACTOR_LOCAL;
882          colorComb.Local = localc;
883          colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
884          colorComb.Invert = FXFALSE;
885       }
886       break;
887
888    case GL_BLEND:
889       /*
890        * XXX we can't do real GL_BLEND mode.  These settings assume that
891        * the TexEnv color is black and incoming fragment color is white.
892        */
893       if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) {
894          /* Av = Af */
895          alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
896          alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
897          alphaComb.Local = locala;
898          alphaComb.Other = GR_COMBINE_OTHER_NONE;
899          alphaComb.Invert = FXFALSE;
900       }
901       else if (baseFormat == GL_INTENSITY) {
902          /* Av = Af * (1 - It) + Ac * It */
903          alphaComb.Function = GR_COMBINE_FUNCTION_BLEND;
904          alphaComb.Factor = GR_COMBINE_FACTOR_TEXTURE_ALPHA;
905          alphaComb.Local = locala;
906          alphaComb.Other = GR_COMBINE_OTHER_CONSTANT;
907          alphaComb.Invert = FXFALSE;
908       }
909       else {
910          /* Av = Af * At */
911          alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
912          alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
913          alphaComb.Local = locala;
914          alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
915          alphaComb.Invert = FXFALSE;
916       }
917       if (baseFormat == GL_ALPHA) {
918          colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
919          colorComb.Factor = GR_COMBINE_FACTOR_NONE;
920          colorComb.Local = localc;
921          colorComb.Other = GR_COMBINE_OTHER_NONE;
922          colorComb.Invert = FXFALSE;
923       }
924       else {
925          colorComb.Function = GR_COMBINE_FUNCTION_BLEND;
926          colorComb.Factor = GR_COMBINE_FACTOR_TEXTURE_RGB;
927          colorComb.Local = localc;
928          colorComb.Other = GR_COMBINE_OTHER_CONSTANT;
929          colorComb.Invert = FXTRUE;
930       }
931       fxMesa->Color.MonoColor = PACK_RGBA32(
932          ctx->Texture.Unit[unit].EnvColor[0] * 255.0f,
933          ctx->Texture.Unit[unit].EnvColor[1] * 255.0f,
934          ctx->Texture.Unit[unit].EnvColor[2] * 255.0f,
935          ctx->Texture.Unit[unit].EnvColor[3] * 255.0f);
936       fxMesa->dirty |= TDFX_UPLOAD_CONSTANT_COLOR;
937       break;
938
939    case GL_REPLACE:
940       if ((baseFormat == GL_RGB) || (baseFormat == GL_LUMINANCE)) {
941          alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
942          alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
943          alphaComb.Local = locala;
944          alphaComb.Other = GR_COMBINE_OTHER_NONE;
945          alphaComb.Invert = FXFALSE;
946       }
947       else {
948          alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
949          alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
950          alphaComb.Local = locala;
951          alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
952          alphaComb.Invert = FXFALSE;
953       }
954       if (baseFormat == GL_ALPHA) {
955          colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
956          colorComb.Factor = GR_COMBINE_FACTOR_NONE;
957          colorComb.Local = localc;
958          colorComb.Other = GR_COMBINE_OTHER_NONE;
959          colorComb.Invert = FXFALSE;
960       }
961       else {
962          colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
963          colorComb.Factor = GR_COMBINE_FACTOR_ONE;
964          colorComb.Local = localc;
965          colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
966          colorComb.Invert = FXFALSE;
967       }
968       break;
969
970    case GL_ADD:
971       if (baseFormat == GL_ALPHA ||
972           baseFormat == GL_LUMINANCE_ALPHA ||
973           baseFormat == GL_RGBA) {
974          /* product of texel and fragment alpha */
975          alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
976          alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
977          alphaComb.Local = locala;
978          alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
979          alphaComb.Invert = FXFALSE;
980       }
981       else if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) {
982          /* fragment alpha is unchanged */
983          alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
984          alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
985          alphaComb.Local = locala;
986          alphaComb.Other = GR_COMBINE_OTHER_NONE;
987          alphaComb.Invert = FXFALSE;
988       }
989       else {
990          ASSERT(baseFormat == GL_INTENSITY);
991          /* sum of texel and fragment alpha */
992          alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
993          alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
994          alphaComb.Local = locala;
995          alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
996          alphaComb.Invert = FXFALSE;
997       }
998       if (baseFormat == GL_ALPHA) {
999          /* rgb unchanged */
1000          colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
1001          colorComb.Factor = GR_COMBINE_FACTOR_NONE;
1002          colorComb.Local = localc;
1003          colorComb.Other = GR_COMBINE_OTHER_NONE;
1004          colorComb.Invert = FXFALSE;
1005       }
1006       else {
1007          /* sum of texel and fragment rgb */
1008          colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
1009          colorComb.Factor = GR_COMBINE_FACTOR_ONE;
1010          colorComb.Local = localc;
1011          colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
1012          colorComb.Invert = FXFALSE;
1013       }
1014       break;
1015
1016    default: {
1017       (void) memcpy(&colorComb, &fxMesa->ColorCombine, sizeof(colorComb));
1018       (void) memcpy(&alphaComb, &fxMesa->AlphaCombine, sizeof(alphaComb));
1019       _mesa_problem(ctx, "bad texture env mode in %s", __FUNCTION__);
1020    }
1021    }
1022
1023    if (colorComb.Function != fxMesa->ColorCombine.Function ||
1024        colorComb.Factor != fxMesa->ColorCombine.Factor ||
1025        colorComb.Local != fxMesa->ColorCombine.Local ||
1026        colorComb.Other != fxMesa->ColorCombine.Other ||
1027        colorComb.Invert != fxMesa->ColorCombine.Invert) {
1028       fxMesa->ColorCombine = colorComb;
1029       fxMesa->dirty |= TDFX_UPLOAD_COLOR_COMBINE;
1030    }
1031
1032    if (alphaComb.Function != fxMesa->AlphaCombine.Function ||
1033        alphaComb.Factor != fxMesa->AlphaCombine.Factor ||
1034        alphaComb.Local != fxMesa->AlphaCombine.Local ||
1035        alphaComb.Other != fxMesa->AlphaCombine.Other ||
1036        alphaComb.Invert != fxMesa->AlphaCombine.Invert) {
1037       fxMesa->AlphaCombine = alphaComb;
1038       fxMesa->dirty |= TDFX_UPLOAD_ALPHA_COMBINE;
1039    }
1040    return GL_TRUE;
1041 }
1042
1043
1044 /*
1045  * Setup the Voodoo3 texture environment for dual texture units.
1046  * Return GL_TRUE for success, GL_FALSE for failure.
1047  * If failure, we'll use software rendering.
1048  */
1049 static GLboolean
1050 SetupDoubleTexEnvVoodoo3(struct gl_context *ctx, int tmu0,
1051                          GLenum envMode0, GLenum baseFormat0,
1052                          GLenum envMode1, GLenum baseFormat1)
1053 {
1054    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1055    const GrCombineLocal_t locala = GR_COMBINE_LOCAL_ITERATED;
1056    const GrCombineLocal_t localc = GR_COMBINE_LOCAL_ITERATED;
1057    const int tmu1 = 1 - tmu0;
1058
1059    if (envMode0 == GL_MODULATE && envMode1 == GL_MODULATE) {
1060       GLboolean isalpha[TDFX_NUM_TMU];
1061
1062       isalpha[tmu0] = (baseFormat0 == GL_ALPHA);
1063       isalpha[tmu1] = (baseFormat1 == GL_ALPHA);
1064
1065       if (isalpha[TDFX_TMU1]) {
1066          fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
1067          fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1068          fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1069          fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1070          fxMesa->TexCombine[1].InvertRGB = FXTRUE;
1071          fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1072       }
1073       else {
1074          fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1075          fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1076          fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1077          fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1078          fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1079          fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1080       }
1081       if (isalpha[TDFX_TMU0]) {
1082          fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
1083          fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE;
1084          fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
1085          fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
1086          fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1087          fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1088       }
1089       else {
1090          fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
1091          fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_LOCAL;
1092          fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
1093          fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
1094          fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1095          fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1096       }
1097       fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1098       fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_LOCAL;
1099       fxMesa->ColorCombine.Local = localc;
1100       fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1101       fxMesa->ColorCombine.Invert = FXFALSE;
1102       fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1103       fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_LOCAL;
1104       fxMesa->AlphaCombine.Local = locala;
1105       fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1106       fxMesa->AlphaCombine.Invert = FXFALSE;
1107    }
1108    else if (envMode0 == GL_REPLACE && envMode1 == GL_BLEND) { /* Quake */
1109       if (tmu0 == TDFX_TMU1) {
1110          fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1111          fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1112          fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1113          fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1114          fxMesa->TexCombine[1].InvertRGB = FXTRUE;
1115          fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1116          fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
1117          fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_LOCAL;
1118          fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
1119          fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
1120          fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1121          fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1122       }
1123       else {
1124          fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1125          fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1126          fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1127          fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1128          fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1129          fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1130          fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
1131          fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE_MINUS_LOCAL;
1132          fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
1133          fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE_MINUS_LOCAL;
1134          fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1135          fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1136       }
1137       fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1138       fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_ONE;
1139       fxMesa->ColorCombine.Local = localc;
1140       fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1141       fxMesa->ColorCombine.Invert = FXFALSE;
1142       fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
1143       fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE;
1144       fxMesa->AlphaCombine.Local = locala;
1145       fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE;
1146       fxMesa->AlphaCombine.Invert = FXFALSE;
1147    }
1148    else if (envMode0 == GL_REPLACE && envMode1 == GL_MODULATE) {
1149       /* Quake 2/3 */
1150       if (tmu1 == TDFX_TMU1) {
1151          fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1152          fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1153          fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_ZERO;
1154          fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1155          fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1156          fxMesa->TexCombine[1].InvertAlpha = FXTRUE;
1157          fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
1158          fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_LOCAL;
1159          fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
1160          fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
1161          fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1162          fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1163       }
1164       else {
1165          fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1166          fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1167          fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1168          fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1169          fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1170          fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1171          fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
1172          fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_LOCAL;
1173          fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
1174          fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE;
1175          fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1176          fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1177       }
1178
1179       fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1180       fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_ONE;
1181       fxMesa->ColorCombine.Local = localc;
1182       fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1183       fxMesa->ColorCombine.Invert = FXFALSE;
1184       if (baseFormat0 == GL_RGB) {
1185          fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
1186          fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE;
1187          fxMesa->AlphaCombine.Local = locala;
1188          fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE;
1189          fxMesa->AlphaCombine.Invert = FXFALSE;
1190       }
1191       else {
1192          fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1193          fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_ONE;
1194          fxMesa->AlphaCombine.Local = locala;
1195          fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE;
1196          fxMesa->AlphaCombine.Invert = FXFALSE;
1197       }
1198    }
1199    else if (envMode0 == GL_MODULATE && envMode1 == GL_ADD) {
1200       /* Quake 3 sky */
1201       GLboolean isalpha[TDFX_NUM_TMU];
1202
1203       isalpha[tmu0] = (baseFormat0 == GL_ALPHA);
1204       isalpha[tmu1] = (baseFormat1 == GL_ALPHA);
1205
1206       if (isalpha[TDFX_TMU1]) {
1207          fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
1208          fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1209          fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1210          fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1211          fxMesa->TexCombine[1].InvertRGB = FXTRUE;
1212          fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1213       }
1214       else {
1215          fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1216          fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1217          fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1218          fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1219          fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1220          fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1221       }
1222       if (isalpha[TDFX_TMU0]) {
1223          fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER;
1224          fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE;
1225          fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
1226          fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE;
1227          fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1228          fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1229       }
1230       else {
1231          fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
1232          fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE;
1233          fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
1234          fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE;
1235          fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1236          fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1237       }
1238       fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1239       fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_LOCAL;
1240       fxMesa->ColorCombine.Local = localc;
1241       fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1242       fxMesa->ColorCombine.Invert = FXFALSE;
1243       fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1244       fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_LOCAL;
1245       fxMesa->AlphaCombine.Local = locala;
1246       fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1247       fxMesa->AlphaCombine.Invert = FXFALSE;
1248    }
1249    else if (envMode0 == GL_REPLACE && envMode1 == GL_ADD) {
1250       /* Vulpine sky */
1251       GLboolean isalpha[TDFX_NUM_TMU];
1252
1253       isalpha[tmu0] = (baseFormat0 == GL_ALPHA);
1254       isalpha[tmu1] = (baseFormat1 == GL_ALPHA);
1255
1256       if (isalpha[TDFX_TMU1]) {
1257          fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
1258          fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1259          fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1260          fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1261          fxMesa->TexCombine[1].InvertRGB = FXTRUE;
1262          fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1263       } else {
1264          fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1265          fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1266          fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1267          fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1268          fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1269          fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1270       }
1271
1272       if (isalpha[TDFX_TMU0]) {
1273          fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER;
1274          fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE;
1275          fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
1276          fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE;
1277          fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1278          fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1279       } else {
1280          fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
1281          fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE;
1282          fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
1283          fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE;
1284          fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1285          fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1286       }
1287
1288       fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1289       fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_ONE;
1290       fxMesa->ColorCombine.Local = localc;
1291       fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1292       fxMesa->ColorCombine.Invert = FXFALSE;
1293       fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1294       fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_ONE;
1295       fxMesa->AlphaCombine.Local = locala;
1296       fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1297       fxMesa->AlphaCombine.Invert = FXFALSE;
1298    }
1299    else if (envMode1 == GL_REPLACE) {
1300       /* Homeworld2 */
1301
1302       fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
1303       fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1304       fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_ZERO;
1305       fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1306       fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1307       fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1308
1309       fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1310       fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_NONE;
1311       fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1312       fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1313       fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1314       fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1315
1316       if ((baseFormat0 == GL_RGB) || (baseFormat0 == GL_LUMINANCE)) {
1317          fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
1318          fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE;
1319          fxMesa->AlphaCombine.Local = locala;
1320          fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE;
1321          fxMesa->AlphaCombine.Invert = FXFALSE;
1322       } else {
1323          fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1324          fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_ONE;
1325          fxMesa->AlphaCombine.Local = locala;
1326          fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1327          fxMesa->AlphaCombine.Invert = FXFALSE;
1328       }
1329       if (baseFormat0 == GL_ALPHA) {
1330          fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
1331          fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_NONE;
1332          fxMesa->ColorCombine.Local = localc;
1333          fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_NONE;
1334          fxMesa->ColorCombine.Invert = FXFALSE;
1335       } else {
1336          fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1337          fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_ONE;
1338          fxMesa->ColorCombine.Local = localc;
1339          fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1340          fxMesa->ColorCombine.Invert = FXFALSE;
1341       }
1342    }
1343    else {
1344       _mesa_problem(ctx, "%s: Unexpected dual texture mode encountered", __FUNCTION__);
1345       return GL_FALSE;
1346    }
1347
1348    fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_ENV;
1349    fxMesa->dirty |= TDFX_UPLOAD_COLOR_COMBINE;
1350    fxMesa->dirty |= TDFX_UPLOAD_ALPHA_COMBINE;
1351    return GL_TRUE;
1352 }
1353
1354
1355 /*
1356  * This function makes sure that the correct mipmap levels are loaded
1357  * in the right places in memory and then makes the Glide calls to
1358  * setup the texture source pointers.
1359  */
1360 static void
1361 setupSingleTMU(tdfxContextPtr fxMesa, struct gl_texture_object *tObj)
1362 {
1363    struct tdfxSharedState *shared = (struct tdfxSharedState *) fxMesa->glCtx->Shared->DriverData;
1364    tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
1365    const struct gl_context *ctx = fxMesa->glCtx;
1366
1367    /* Make sure we're not loaded incorrectly */
1368    if (ti->isInTM && !shared->umaTexMemory) {
1369       /* if doing filtering between mipmap levels, alternate mipmap levels
1370        * must be in alternate TMUs.
1371        */
1372       if (ti->LODblend) {
1373          if (ti->whichTMU != TDFX_TMU_SPLIT)
1374             tdfxTMMoveOutTM_NoLock(fxMesa, tObj);
1375       }
1376       else {
1377          if (ti->whichTMU == TDFX_TMU_SPLIT)
1378             tdfxTMMoveOutTM_NoLock(fxMesa, tObj);
1379       }
1380    }
1381
1382    /* Make sure we're loaded correctly */
1383    if (!ti->isInTM) {
1384       /* Have to download the texture */
1385       if (shared->umaTexMemory) {
1386          tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU0);
1387       }
1388       else {
1389          /* Voodoo3 (split texture memory) */
1390          if (ti->LODblend) {
1391             tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU_SPLIT);
1392          }
1393          else {
1394 #if 0
1395             /* XXX putting textures into the second memory bank when the
1396              * first bank is full is not working at this time.
1397              */
1398             if (fxMesa->haveTwoTMUs) {
1399                GLint memReq = fxMesa->Glide.grTexTextureMemRequired(
1400                                        GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
1401                if (shared->freeTexMem[TDFX_TMU0] > memReq) {
1402                   tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU0);
1403                }
1404                else {
1405                   tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU1);
1406                }
1407             }
1408             else
1409 #endif
1410             {
1411                tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU0);
1412             }
1413          }
1414       }
1415    }
1416
1417    if (ti->LODblend && ti->whichTMU == TDFX_TMU_SPLIT) {
1418       /* mipmap levels split between texture banks */
1419       GLint u;
1420
1421       if (ti->info.format == GR_TEXFMT_P_8 && !ctx->Texture.SharedPalette) {
1422          fxMesa->TexPalette.Type = ti->paltype;
1423          fxMesa->TexPalette.Data = &(ti->palette);
1424          fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE;
1425       }
1426
1427       for (u = 0; u < 2; u++) {
1428          fxMesa->TexParams[u].sClamp = ti->sClamp;
1429          fxMesa->TexParams[u].tClamp = ti->tClamp;
1430          fxMesa->TexParams[u].minFilt = ti->minFilt;
1431          fxMesa->TexParams[u].magFilt = ti->magFilt;
1432          fxMesa->TexParams[u].mmMode = ti->mmMode;
1433          fxMesa->TexParams[u].LODblend = ti->LODblend;
1434          fxMesa->TexParams[u].LodBias = ctx->Texture.Unit[u].LodBias;
1435       }
1436       fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS;
1437
1438       fxMesa->TexSource[0].StartAddress = ti->tm[TDFX_TMU0]->startAddr;
1439       fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_ODD;
1440       fxMesa->TexSource[0].Info = &(ti->info);
1441       fxMesa->TexSource[1].StartAddress = ti->tm[TDFX_TMU1]->startAddr;
1442       fxMesa->TexSource[1].EvenOdd = GR_MIPMAPLEVELMASK_EVEN;
1443       fxMesa->TexSource[1].Info = &(ti->info);
1444       fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE;
1445    }
1446    else {
1447       FxU32 tmu;
1448
1449       if (ti->whichTMU == TDFX_TMU_BOTH)
1450          tmu = TDFX_TMU0;
1451       else
1452          tmu = ti->whichTMU;
1453
1454       if (shared->umaTexMemory) {
1455          assert(ti->whichTMU == TDFX_TMU0);
1456          assert(tmu == TDFX_TMU0);
1457       }
1458
1459       if (ti->info.format == GR_TEXFMT_P_8 && !ctx->Texture.SharedPalette) {
1460          fxMesa->TexPalette.Type = ti->paltype;
1461          fxMesa->TexPalette.Data = &(ti->palette);
1462          fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE;
1463       }
1464
1465       /* KW: The alternative is to do the download to the other tmu.  If
1466        * we get to this point, I think it means we are thrashing the
1467        * texture memory, so perhaps it's not a good idea.
1468        */
1469
1470       if (fxMesa->TexParams[tmu].sClamp != ti->sClamp ||
1471           fxMesa->TexParams[tmu].tClamp != ti->tClamp ||
1472           fxMesa->TexParams[tmu].minFilt != ti->minFilt ||
1473           fxMesa->TexParams[tmu].magFilt != ti->magFilt ||
1474           fxMesa->TexParams[tmu].mmMode != ti->mmMode ||
1475           fxMesa->TexParams[tmu].LODblend != FXFALSE ||
1476           fxMesa->TexParams[tmu].LodBias != ctx->Texture.Unit[tmu].LodBias) {
1477          fxMesa->TexParams[tmu].sClamp = ti->sClamp;
1478          fxMesa->TexParams[tmu].tClamp = ti->tClamp;
1479          fxMesa->TexParams[tmu].minFilt = ti->minFilt;
1480          fxMesa->TexParams[tmu].magFilt = ti->magFilt;
1481          fxMesa->TexParams[tmu].mmMode = ti->mmMode;
1482          fxMesa->TexParams[tmu].LODblend = FXFALSE;
1483          fxMesa->TexParams[tmu].LodBias = ctx->Texture.Unit[tmu].LodBias;
1484          fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS;
1485       }
1486
1487       /* Glide texture source info */
1488       fxMesa->TexSource[0].Info = NULL;
1489       fxMesa->TexSource[1].Info = NULL;
1490       if (ti->tm[tmu]) {
1491          fxMesa->TexSource[tmu].StartAddress = ti->tm[tmu]->startAddr;
1492          fxMesa->TexSource[tmu].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
1493          fxMesa->TexSource[tmu].Info = &(ti->info);
1494          fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE;
1495       }
1496    }
1497
1498    fxMesa->sScale0 = ti->sScale;
1499    fxMesa->tScale0 = ti->tScale;
1500 }
1501
1502 static void
1503 selectSingleTMUSrc(tdfxContextPtr fxMesa, GLint tmu, FxBool LODblend)
1504 {
1505    if (LODblend) {
1506       fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND;
1507       fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION;
1508       fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND;
1509       fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION;
1510       fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1511       fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1512
1513       if (fxMesa->haveTwoTMUs) {
1514          const struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
1515          const struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
1516          int tmu;
1517
1518          if (shared->umaTexMemory)
1519             tmu = GR_TMU0;
1520          else
1521             tmu = GR_TMU1;
1522
1523          fxMesa->TexCombine[tmu].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1524          fxMesa->TexCombine[tmu].FactorRGB = GR_COMBINE_FACTOR_NONE;
1525          fxMesa->TexCombine[tmu].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1526          fxMesa->TexCombine[tmu].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1527          fxMesa->TexCombine[tmu].InvertRGB = FXFALSE;
1528          fxMesa->TexCombine[tmu].InvertAlpha = FXFALSE;
1529       }
1530       fxMesa->tmuSrc = TDFX_TMU_SPLIT;
1531    }
1532    else {
1533       if (tmu != TDFX_TMU1) {
1534          fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1535          fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_NONE;
1536          fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1537          fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1538          fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1539          fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1540          if (fxMesa->haveTwoTMUs) {
1541             fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
1542             fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1543             fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_ZERO;
1544             fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1545             fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1546             fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1547          }
1548          fxMesa->tmuSrc = TDFX_TMU0;
1549       }
1550       else {
1551          fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1552          fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1553          fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1554          fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1555          fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1556          fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1557          /* GR_COMBINE_FUNCTION_SCALE_OTHER doesn't work ?!? */
1558          fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND;
1559          fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE;
1560          fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND;
1561          fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE;
1562          fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1563          fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1564          fxMesa->tmuSrc = TDFX_TMU1;
1565       }
1566    }
1567
1568    fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_ENV;
1569 }
1570
1571 #if 0
1572 static void print_state(tdfxContextPtr fxMesa)
1573 {
1574    struct gl_context *ctx = fxMesa->glCtx;
1575    struct gl_texture_object *tObj0 = ctx->Texture.Unit[0]._Current;
1576    struct gl_texture_object *tObj1 = ctx->Texture.Unit[1]._Current;
1577    GLenum base0 = tObj0->Image[0][tObj0->BaseLevel] ? tObj0->Image[0][tObj0->BaseLevel]->Format : 99;
1578    GLenum base1 = tObj1->Image[0][tObj1->BaseLevel] ? tObj1->Image[0][tObj1->BaseLevel]->Format : 99;
1579
1580    printf("Unit 0: Enabled:  GL=%d   Gr=%d\n", ctx->Texture.Unit[0]._ReallyEnabled,
1581           fxMesa->TexState.Enabled[0]);
1582    printf("   EnvMode: GL=0x%x  Gr=0x%x\n", ctx->Texture.Unit[0].EnvMode,
1583           fxMesa->TexState.EnvMode[0]);
1584    printf("   BaseFmt: GL=0x%x  Gr=0x%x\n", base0, fxMesa->TexState.TexFormat[0]);
1585
1586
1587    printf("Unit 1: Enabled:  GL=%d  Gr=%d\n", ctx->Texture.Unit[1]._ReallyEnabled,
1588           fxMesa->TexState.Enabled[1]);
1589    printf("   EnvMode: GL=0x%x  Gr:0x%x\n", ctx->Texture.Unit[1].EnvMode,
1590           fxMesa->TexState.EnvMode[1]);
1591    printf("   BaseFmt: GL=0x%x  Gr:0x%x\n", base1, fxMesa->TexState.TexFormat[1]);
1592 }
1593 #endif
1594
1595 /*
1596  * When we're only using a single texture unit, we always use the 0th
1597  * Glide/hardware unit, regardless if it's GL_TEXTURE0_ARB or GL_TEXTURE1_ARB
1598  * that's enalbed.
1599  * Input:  ctx - the context
1600  *         unit - the OpenGL texture unit to use.
1601  */
1602 static void setupTextureSingleTMU(struct gl_context * ctx, GLuint unit)
1603 {
1604    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1605    tdfxTexInfo *ti;
1606    struct gl_texture_object *tObj;
1607    int tmu;
1608    GLenum envMode, baseFormat;
1609
1610    tObj = ctx->Texture.Unit[unit]._Current;
1611    if (tObj->Image[0][tObj->BaseLevel]->Border > 0) {
1612       FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_BORDER, GL_TRUE);
1613       return;
1614    }
1615
1616    setupSingleTMU(fxMesa, tObj);
1617
1618    ti = TDFX_TEXTURE_DATA(tObj);
1619    if (ti->whichTMU == TDFX_TMU_BOTH)
1620       tmu = TDFX_TMU0;
1621    else
1622       tmu = ti->whichTMU;
1623
1624    if (fxMesa->tmuSrc != tmu) {
1625       selectSingleTMUSrc(fxMesa, tmu, ti->LODblend);
1626    }
1627
1628    if (ti->reloadImages)
1629       fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_IMAGES;
1630
1631    /* Check if we really need to update the texenv state */
1632    envMode = ctx->Texture.Unit[unit].EnvMode;
1633    baseFormat = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
1634
1635    if (TDFX_IS_NAPALM(fxMesa)) {
1636       /* see if we really need to update the unit */
1637       if (1/*fxMesa->TexState.Enabled[unit] != ctx->Texture.Unit[unit]._ReallyEnabled ||
1638           envMode != fxMesa->TexState.EnvMode[0] ||
1639           envMode == GL_COMBINE_EXT ||
1640           baseFormat != fxMesa->TexState.TexFormat[0]*/) {
1641          struct tdfx_texcombine_ext *otherEnv;
1642          if (!SetupTexEnvNapalm(ctx, GL_TRUE,
1643                                 &ctx->Texture.Unit[unit], baseFormat,
1644                                 &fxMesa->TexCombineExt[0])) {
1645             /* software fallback */
1646             FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE);
1647          }
1648          /* disable other unit */
1649          otherEnv = &fxMesa->TexCombineExt[1];
1650          otherEnv->Color.SourceA = GR_CMBX_ZERO;
1651          otherEnv->Color.ModeA = GR_FUNC_MODE_ZERO;
1652          otherEnv->Color.SourceB = GR_CMBX_ZERO;
1653          otherEnv->Color.ModeB = GR_FUNC_MODE_ZERO;
1654          otherEnv->Color.SourceC = GR_CMBX_ZERO;
1655          otherEnv->Color.InvertC = FXFALSE;
1656          otherEnv->Color.SourceD = GR_CMBX_ZERO;
1657          otherEnv->Color.InvertD = FXFALSE;
1658          otherEnv->Color.Shift = 0;
1659          otherEnv->Color.Invert = FXFALSE;
1660          otherEnv->Alpha.SourceA = GR_CMBX_ITALPHA;
1661          otherEnv->Alpha.ModeA = GR_FUNC_MODE_ZERO;
1662          otherEnv->Alpha.SourceB = GR_CMBX_ITALPHA;
1663          otherEnv->Alpha.ModeB = GR_FUNC_MODE_ZERO;
1664          otherEnv->Alpha.SourceC = GR_CMBX_ZERO;
1665          otherEnv->Alpha.InvertC = FXFALSE;
1666          otherEnv->Alpha.SourceD = GR_CMBX_ZERO;
1667          otherEnv->Alpha.InvertD = FXFALSE;
1668          otherEnv->Alpha.Shift = 0;
1669          otherEnv->Alpha.Invert = FXFALSE;
1670
1671 #if 0/*JJJ*/
1672          fxMesa->TexState.Enabled[unit] = ctx->Texture.Unit[unit]._ReallyEnabled;
1673          fxMesa->TexState.EnvMode[0] = envMode;
1674          fxMesa->TexState.TexFormat[0] = baseFormat;
1675          fxMesa->TexState.EnvMode[1] = 0;
1676          fxMesa->TexState.TexFormat[1] = 0;
1677 #endif
1678       }
1679    }
1680    else {
1681       /* Voodoo3 */
1682
1683       /* see if we really need to update the unit */
1684       if (1/*fxMesa->TexState.Enabled[unit] != ctx->Texture.Unit[unit]._ReallyEnabled ||
1685           envMode != fxMesa->TexState.EnvMode[0] ||
1686           envMode == GL_COMBINE_EXT ||
1687           baseFormat != fxMesa->TexState.TexFormat[0]*/) {
1688          if (!SetupSingleTexEnvVoodoo3(ctx, unit, envMode, baseFormat)) {
1689             /* software fallback */
1690             FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE);
1691          }
1692 #if 0/*JJJ*/
1693          fxMesa->TexState.Enabled[unit] = ctx->Texture.Unit[unit]._ReallyEnabled;
1694          fxMesa->TexState.EnvMode[0] = envMode;
1695          fxMesa->TexState.TexFormat[0] = baseFormat;
1696          fxMesa->TexState.EnvMode[1] = 0;
1697          fxMesa->TexState.TexFormat[1] = 0;
1698 #endif
1699       }
1700    }
1701 }
1702
1703
1704 static void
1705 setupDoubleTMU(tdfxContextPtr fxMesa,
1706                struct gl_texture_object *tObj0,
1707                struct gl_texture_object *tObj1)
1708 {
1709 #define T0_NOT_IN_TMU  0x01
1710 #define T1_NOT_IN_TMU  0x02
1711 #define T0_IN_TMU0     0x04
1712 #define T1_IN_TMU0     0x08
1713 #define T0_IN_TMU1     0x10
1714 #define T1_IN_TMU1     0x20
1715
1716     const struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
1717     const struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
1718     const struct gl_context *ctx = fxMesa->glCtx;
1719     tdfxTexInfo *ti0 = TDFX_TEXTURE_DATA(tObj0);
1720     tdfxTexInfo *ti1 = TDFX_TEXTURE_DATA(tObj1);
1721     GLuint tstate = 0;
1722     int tmu0 = 0, tmu1 = 1;
1723
1724     if (shared->umaTexMemory) {
1725        if (!ti0->isInTM) {
1726           tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU0);
1727           assert(ti0->isInTM);
1728        }
1729        if (!ti1->isInTM) {
1730           tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU0);
1731           assert(ti1->isInTM);
1732        }
1733     }
1734     else {
1735        /* We shouldn't need to do this. There is something wrong with
1736           multitexturing when the TMUs are swapped. So, we're forcing
1737           them to always be loaded correctly. !!! */
1738        if (ti0->whichTMU == TDFX_TMU1)
1739            tdfxTMMoveOutTM_NoLock(fxMesa, tObj0);
1740        if (ti1->whichTMU == TDFX_TMU0)
1741            tdfxTMMoveOutTM_NoLock(fxMesa, tObj1);
1742
1743        if (ti0->isInTM) {
1744            switch (ti0->whichTMU) {
1745            case TDFX_TMU0:
1746                tstate |= T0_IN_TMU0;
1747                break;
1748            case TDFX_TMU1:
1749                tstate |= T0_IN_TMU1;
1750                break;
1751            case TDFX_TMU_BOTH:
1752                tstate |= T0_IN_TMU0 | T0_IN_TMU1;
1753                break;
1754            case TDFX_TMU_SPLIT:
1755                tstate |= T0_NOT_IN_TMU;
1756                break;
1757            }
1758        }
1759        else
1760            tstate |= T0_NOT_IN_TMU;
1761
1762        if (ti1->isInTM) {
1763            switch (ti1->whichTMU) {
1764            case TDFX_TMU0:
1765                tstate |= T1_IN_TMU0;
1766                break;
1767            case TDFX_TMU1:
1768                tstate |= T1_IN_TMU1;
1769                break;
1770            case TDFX_TMU_BOTH:
1771                tstate |= T1_IN_TMU0 | T1_IN_TMU1;
1772                break;
1773            case TDFX_TMU_SPLIT:
1774                tstate |= T1_NOT_IN_TMU;
1775                break;
1776            }
1777        }
1778        else
1779            tstate |= T1_NOT_IN_TMU;
1780
1781        /* Move texture maps into TMUs */
1782
1783        if (!(((tstate & T0_IN_TMU0) && (tstate & T1_IN_TMU1)) ||
1784              ((tstate & T0_IN_TMU1) && (tstate & T1_IN_TMU0)))) {
1785            if (tObj0 == tObj1) {
1786               tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU_BOTH);
1787            }
1788            else {
1789                /* Find the minimal way to correct the situation */
1790                if ((tstate & T0_IN_TMU0) || (tstate & T1_IN_TMU1)) {
1791                    /* We have one in the standard order, setup the other */
1792                    if (tstate & T0_IN_TMU0) {
1793                       /* T0 is in TMU0, put T1 in TMU1 */
1794                       tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU1);
1795                    }
1796                    else {
1797                        tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU0);
1798                    }
1799                    /* tmu0 and tmu1 are setup */
1800                }
1801                else if ((tstate & T0_IN_TMU1) || (tstate & T1_IN_TMU0)) {
1802                    /* we have one in the reverse order, setup the other */
1803                    if (tstate & T1_IN_TMU0) {
1804                       /* T1 is in TMU0, put T0 in TMU1 */
1805                       tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU1);
1806                    }
1807                    else {
1808                        tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU0);
1809                    }
1810                    tmu0 = 1;
1811                    tmu1 = 0;
1812                }
1813                else {              /* Nothing is loaded */
1814                    tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU0);
1815                    tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU1);
1816                    /* tmu0 and tmu1 are setup */
1817                }
1818            }
1819        }
1820     }
1821
1822     ti0->lastTimeUsed = fxMesa->texBindNumber;
1823     ti1->lastTimeUsed = fxMesa->texBindNumber;
1824
1825
1826     if (!ctx->Texture.SharedPalette) {
1827         if (ti0->info.format == GR_TEXFMT_P_8) {
1828             fxMesa->TexPalette.Type = ti0->paltype;
1829             fxMesa->TexPalette.Data = &(ti0->palette);
1830             fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE;
1831         }
1832         else if (ti1->info.format == GR_TEXFMT_P_8) {
1833             fxMesa->TexPalette.Type = ti1->paltype;
1834             fxMesa->TexPalette.Data = &(ti1->palette);
1835             fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE;
1836         }
1837         else {
1838             fxMesa->TexPalette.Data = NULL;
1839         }
1840     }
1841
1842     /*
1843      * Setup Unit 0
1844      */
1845     assert(ti0->isInTM);
1846     assert(ti0->tm[tmu0]);
1847     fxMesa->TexSource[tmu0].StartAddress = ti0->tm[tmu0]->startAddr;
1848     fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
1849     fxMesa->TexSource[tmu0].Info = &(ti0->info);
1850     fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE;
1851
1852     if (fxMesa->TexParams[tmu0].sClamp != ti0->sClamp ||
1853         fxMesa->TexParams[tmu0].tClamp != ti0->tClamp ||
1854         fxMesa->TexParams[tmu0].minFilt != ti0->minFilt ||
1855         fxMesa->TexParams[tmu0].magFilt != ti0->magFilt ||
1856         fxMesa->TexParams[tmu0].mmMode != ti0->mmMode ||
1857         fxMesa->TexParams[tmu0].LODblend != FXFALSE ||
1858         fxMesa->TexParams[tmu0].LodBias != ctx->Texture.Unit[tmu0].LodBias) {
1859        fxMesa->TexParams[tmu0].sClamp = ti0->sClamp;
1860        fxMesa->TexParams[tmu0].tClamp = ti0->tClamp;
1861        fxMesa->TexParams[tmu0].minFilt = ti0->minFilt;
1862        fxMesa->TexParams[tmu0].magFilt = ti0->magFilt;
1863        fxMesa->TexParams[tmu0].mmMode = ti0->mmMode;
1864        fxMesa->TexParams[tmu0].LODblend = FXFALSE;
1865        fxMesa->TexParams[tmu0].LodBias = ctx->Texture.Unit[tmu0].LodBias;
1866        fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS;
1867     }
1868
1869     /*
1870      * Setup Unit 1
1871      */
1872     if (shared->umaTexMemory) {
1873         ASSERT(ti1->isInTM);
1874         ASSERT(ti1->tm[0]);
1875         fxMesa->TexSource[tmu1].StartAddress = ti1->tm[0]->startAddr;
1876         fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
1877         fxMesa->TexSource[tmu1].Info = &(ti1->info);
1878     }
1879     else {
1880         ASSERT(ti1->isInTM);
1881         ASSERT(ti1->tm[tmu1]);
1882         fxMesa->TexSource[tmu1].StartAddress = ti1->tm[tmu1]->startAddr;
1883         fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
1884         fxMesa->TexSource[tmu1].Info = &(ti1->info);
1885     }
1886
1887     if (fxMesa->TexParams[tmu1].sClamp != ti1->sClamp ||
1888         fxMesa->TexParams[tmu1].tClamp != ti1->tClamp ||
1889         fxMesa->TexParams[tmu1].minFilt != ti1->minFilt ||
1890         fxMesa->TexParams[tmu1].magFilt != ti1->magFilt ||
1891         fxMesa->TexParams[tmu1].mmMode != ti1->mmMode ||
1892         fxMesa->TexParams[tmu1].LODblend != FXFALSE ||
1893         fxMesa->TexParams[tmu1].LodBias != ctx->Texture.Unit[tmu1].LodBias) {
1894        fxMesa->TexParams[tmu1].sClamp = ti1->sClamp;
1895        fxMesa->TexParams[tmu1].tClamp = ti1->tClamp;
1896        fxMesa->TexParams[tmu1].minFilt = ti1->minFilt;
1897        fxMesa->TexParams[tmu1].magFilt = ti1->magFilt;
1898        fxMesa->TexParams[tmu1].mmMode = ti1->mmMode;
1899        fxMesa->TexParams[tmu1].LODblend = FXFALSE;
1900        fxMesa->TexParams[tmu1].LodBias = ctx->Texture.Unit[tmu1].LodBias;
1901        fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS;
1902     }
1903
1904     fxMesa->sScale0 = ti0->sScale;
1905     fxMesa->tScale0 = ti0->tScale;
1906     fxMesa->sScale1 = ti1->sScale;
1907     fxMesa->tScale1 = ti1->tScale;
1908
1909 #undef T0_NOT_IN_TMU
1910 #undef T1_NOT_IN_TMU
1911 #undef T0_IN_TMU0
1912 #undef T1_IN_TMU0
1913 #undef T0_IN_TMU1
1914 #undef T1_IN_TMU1
1915 }
1916
1917 static void setupTextureDoubleTMU(struct gl_context * ctx)
1918 {
1919    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1920    struct gl_texture_object *tObj0 = ctx->Texture.Unit[1]._Current;
1921    struct gl_texture_object *tObj1 = ctx->Texture.Unit[0]._Current;
1922    tdfxTexInfo *ti0 = TDFX_TEXTURE_DATA(tObj0);
1923    tdfxTexInfo *ti1 = TDFX_TEXTURE_DATA(tObj1);
1924    struct gl_texture_image *baseImage0 = tObj0->Image[0][tObj0->BaseLevel];
1925    struct gl_texture_image *baseImage1 = tObj1->Image[0][tObj1->BaseLevel];
1926 #if 0/*JJJ*/
1927    const GLenum envMode0 = ctx->Texture.Unit[0].EnvMode;
1928    const GLenum envMode1 = ctx->Texture.Unit[1].EnvMode;
1929 #endif
1930
1931    if (baseImage0->Border > 0 || baseImage1->Border > 0) {
1932       FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_BORDER, GL_TRUE);
1933       return;
1934    }
1935
1936    setupDoubleTMU(fxMesa, tObj0, tObj1);
1937
1938    if (ti0->reloadImages || ti1->reloadImages)
1939       fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_IMAGES;
1940
1941    fxMesa->tmuSrc = TDFX_TMU_BOTH;
1942
1943    if (TDFX_IS_NAPALM(fxMesa)) {
1944       /* Remember, Glide has its texture units numbered in backward
1945        * order compared to OpenGL.
1946        */
1947       GLboolean hw1 = GL_TRUE, hw2 = GL_TRUE;
1948
1949       /* check if we really need to update glide unit 1 */
1950       if (1/*fxMesa->TexState.Enabled[0] != ctx->Texture.Unit[0]._ReallyEnabled ||
1951           envMode0 != fxMesa->TexState.EnvMode[1] ||
1952           envMode0 == GL_COMBINE_EXT ||
1953           baseImage0->Format != fxMesa->TexState.TexFormat[1] ||
1954           (fxMesa->Fallback & TDFX_FALLBACK_TEXTURE_ENV)*/) {
1955          hw1 = SetupTexEnvNapalm(ctx, GL_TRUE, &ctx->Texture.Unit[0],
1956                                 baseImage0->_BaseFormat, &fxMesa->TexCombineExt[1]);
1957 #if 0/*JJJ*/
1958          fxMesa->TexState.EnvMode[1] = envMode0;
1959          fxMesa->TexState.TexFormat[1] = baseImage0->_BaseFormat;
1960          fxMesa->TexState.Enabled[0] = ctx->Texture.Unit[0]._ReallyEnabled;
1961 #endif
1962       }
1963
1964       /* check if we really need to update glide unit 0 */
1965       if (1/*fxMesa->TexState.Enabled[1] != ctx->Texture.Unit[1]._ReallyEnabled ||
1966           envMode1 != fxMesa->TexState.EnvMode[0] ||
1967           envMode1 == GL_COMBINE_EXT ||
1968           baseImage1->_BaseFormat != fxMesa->TexState.TexFormat[0] ||
1969           (fxMesa->Fallback & TDFX_FALLBACK_TEXTURE_ENV)*/) {
1970          hw2 = SetupTexEnvNapalm(ctx, GL_FALSE, &ctx->Texture.Unit[1],
1971                                 baseImage1->_BaseFormat, &fxMesa->TexCombineExt[0]);
1972 #if 0/*JJJ*/
1973          fxMesa->TexState.EnvMode[0] = envMode1;
1974          fxMesa->TexState.TexFormat[0] = baseImage1->_BaseFormat;
1975          fxMesa->TexState.Enabled[1] = ctx->Texture.Unit[1]._ReallyEnabled;
1976 #endif
1977       }
1978
1979
1980       if (!hw1 || !hw2) {
1981          FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE);
1982       }
1983    }
1984    else {
1985       int unit0, unit1;
1986       if ((ti0->whichTMU == TDFX_TMU1) || (ti1->whichTMU == TDFX_TMU0))
1987          unit0 = 1;
1988       else
1989          unit0 = 0;
1990       unit1 = 1 - unit0;
1991
1992       if (1/*fxMesa->TexState.Enabled[0] != ctx->Texture.Unit[0]._ReallyEnabled ||
1993           fxMesa->TexState.Enabled[1] != ctx->Texture.Unit[1]._ReallyEnabled ||
1994           envMode0 != fxMesa->TexState.EnvMode[unit0] ||
1995           envMode0 == GL_COMBINE_EXT ||
1996           envMode1 != fxMesa->TexState.EnvMode[unit1] ||
1997           envMode1 == GL_COMBINE_EXT ||
1998           baseImage0->_BaseFormat != fxMesa->TexState.TexFormat[unit0] ||
1999           baseImage1->_BaseFormat != fxMesa->TexState.TexFormat[unit1] ||
2000           (fxMesa->Fallback & TDFX_FALLBACK_TEXTURE_ENV)*/) {
2001
2002          if (!SetupDoubleTexEnvVoodoo3(ctx, unit0,
2003                          ctx->Texture.Unit[0].EnvMode, baseImage0->_BaseFormat,
2004                          ctx->Texture.Unit[1].EnvMode, baseImage1->_BaseFormat)) {
2005             FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE);
2006          }
2007
2008 #if 0/*JJJ*/
2009          fxMesa->TexState.EnvMode[unit0] = envMode0;
2010          fxMesa->TexState.TexFormat[unit0] = baseImage0->_BaseFormat;
2011          fxMesa->TexState.EnvMode[unit1] = envMode1;
2012          fxMesa->TexState.TexFormat[unit1] = baseImage1->_BaseFormat;
2013          fxMesa->TexState.Enabled[0] = ctx->Texture.Unit[0]._ReallyEnabled;
2014          fxMesa->TexState.Enabled[1] = ctx->Texture.Unit[1]._ReallyEnabled;
2015 #endif
2016       }
2017    }
2018 }
2019
2020
2021 void
2022 tdfxUpdateTextureState( struct gl_context *ctx )
2023 {
2024    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
2025
2026    FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_BORDER, GL_FALSE);
2027    FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_FALSE);
2028
2029    if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT) &&
2030        ctx->Texture.Unit[1]._ReallyEnabled == 0) {
2031       LOCK_HARDWARE( fxMesa );  /* XXX remove locking eventually */
2032       setupTextureSingleTMU(ctx, 0);
2033       UNLOCK_HARDWARE( fxMesa );
2034    }
2035    else if (ctx->Texture.Unit[0]._ReallyEnabled == 0 && 
2036             ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
2037       LOCK_HARDWARE( fxMesa );
2038       setupTextureSingleTMU(ctx, 1);
2039       UNLOCK_HARDWARE( fxMesa );
2040    }
2041    else if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT) &&
2042             ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
2043       LOCK_HARDWARE( fxMesa );
2044       setupTextureDoubleTMU(ctx);
2045       UNLOCK_HARDWARE( fxMesa );
2046    }
2047    else {
2048       /* disable hardware texturing */
2049       if (TDFX_IS_NAPALM(fxMesa)) {
2050          fxMesa->ColorCombineExt.SourceA = GR_CMBX_ITRGB;
2051          fxMesa->ColorCombineExt.ModeA = GR_FUNC_MODE_X;
2052          fxMesa->ColorCombineExt.SourceB = GR_CMBX_ZERO;
2053          fxMesa->ColorCombineExt.ModeB = GR_FUNC_MODE_ZERO;
2054          fxMesa->ColorCombineExt.SourceC = GR_CMBX_ZERO;
2055          fxMesa->ColorCombineExt.InvertC = FXTRUE;
2056          fxMesa->ColorCombineExt.SourceD = GR_CMBX_ZERO;
2057          fxMesa->ColorCombineExt.InvertD = FXFALSE;
2058          fxMesa->ColorCombineExt.Shift = 0;
2059          fxMesa->ColorCombineExt.Invert = FXFALSE;
2060          fxMesa->AlphaCombineExt.SourceA = GR_CMBX_ITALPHA;
2061          fxMesa->AlphaCombineExt.ModeA = GR_FUNC_MODE_X;
2062          fxMesa->AlphaCombineExt.SourceB = GR_CMBX_ZERO;
2063          fxMesa->AlphaCombineExt.ModeB = GR_FUNC_MODE_ZERO;
2064          fxMesa->AlphaCombineExt.SourceC = GR_CMBX_ZERO;
2065          fxMesa->AlphaCombineExt.InvertC = FXTRUE;
2066          fxMesa->AlphaCombineExt.SourceD = GR_CMBX_ZERO;
2067          fxMesa->AlphaCombineExt.InvertD = FXFALSE;
2068          fxMesa->AlphaCombineExt.Shift = 0;
2069          fxMesa->AlphaCombineExt.Invert = FXFALSE;
2070       }
2071       else {
2072          /* Voodoo 3*/
2073          fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
2074          fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_NONE;
2075          fxMesa->ColorCombine.Local = GR_COMBINE_LOCAL_ITERATED;
2076          fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_NONE;
2077          fxMesa->ColorCombine.Invert = FXFALSE;
2078          fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
2079          fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE;
2080          fxMesa->AlphaCombine.Local = GR_COMBINE_LOCAL_ITERATED;
2081          fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE;
2082          fxMesa->AlphaCombine.Invert = FXFALSE;
2083       }
2084
2085       fxMesa->TexState.Enabled[0] = 0;
2086       fxMesa->TexState.Enabled[1] = 0;
2087       fxMesa->TexState.EnvMode[0] = 0;
2088       fxMesa->TexState.EnvMode[1] = 0;
2089
2090       fxMesa->dirty |= TDFX_UPLOAD_COLOR_COMBINE;
2091       fxMesa->dirty |= TDFX_UPLOAD_ALPHA_COMBINE;
2092
2093       if (ctx->Texture.Unit[0]._ReallyEnabled != 0 ||
2094           ctx->Texture.Unit[1]._ReallyEnabled != 0) {
2095          /* software texture (cube map, rect tex, etc */
2096          FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE);
2097       }
2098    }
2099 }
2100
2101
2102
2103 /*
2104  * This is a special case of texture state update.
2105  * It's used when we've simply bound a new texture to a texture
2106  * unit and the new texture has the exact same attributes as the
2107  * previously bound texture.
2108  * This is very common in Quake3.
2109  */
2110 void
2111 tdfxUpdateTextureBinding( struct gl_context *ctx )
2112 {
2113    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
2114    struct gl_texture_object *tObj0 = ctx->Texture.Unit[0]._Current;
2115    struct gl_texture_object *tObj1 = ctx->Texture.Unit[1]._Current;
2116    tdfxTexInfo *ti0 = TDFX_TEXTURE_DATA(tObj0);
2117    tdfxTexInfo *ti1 = TDFX_TEXTURE_DATA(tObj1);
2118
2119     const struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
2120     const struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
2121
2122    if (ti0) {
2123       fxMesa->sScale0 = ti0->sScale;
2124       fxMesa->tScale0 = ti0->tScale;
2125       if (ti0->info.format == GR_TEXFMT_P_8) {
2126          fxMesa->TexPalette.Type = ti0->paltype;
2127          fxMesa->TexPalette.Data = &(ti0->palette);
2128          fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE;
2129       }
2130       else if (ti1 && ti1->info.format == GR_TEXFMT_P_8) {
2131          fxMesa->TexPalette.Type = ti1->paltype;
2132          fxMesa->TexPalette.Data = &(ti1->palette);
2133          fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE;
2134       }
2135    }
2136    if (ti1) {
2137       fxMesa->sScale1 = ti1->sScale;
2138       fxMesa->tScale1 = ti1->tScale;
2139    }
2140
2141    if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT) &&
2142        ctx->Texture.Unit[0]._ReallyEnabled == 0) {
2143       /* Only unit 0 2D enabled */
2144       if (shared->umaTexMemory) {
2145          assert(ti0);
2146          fxMesa->TexSource[0].StartAddress = ti0->tm[0]->startAddr;
2147          fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2148          fxMesa->TexSource[0].Info = &(ti0->info);
2149       }
2150       else {
2151          assert(ti0);
2152          if (ti0->LODblend && ti0->whichTMU == TDFX_TMU_SPLIT) {
2153             fxMesa->TexSource[0].StartAddress = ti0->tm[TDFX_TMU0]->startAddr;
2154             fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_ODD;
2155             fxMesa->TexSource[0].Info = &(ti0->info);
2156             fxMesa->TexSource[1].StartAddress = ti0->tm[TDFX_TMU1]->startAddr;
2157             fxMesa->TexSource[1].EvenOdd = GR_MIPMAPLEVELMASK_EVEN;
2158             fxMesa->TexSource[1].Info = &(ti0->info);
2159          }
2160          else {
2161             FxU32 tmu;
2162             if (ti0->whichTMU == TDFX_TMU_BOTH)
2163                tmu = TDFX_TMU0;
2164             else
2165                tmu = ti0->whichTMU;
2166             fxMesa->TexSource[0].Info = NULL;
2167             fxMesa->TexSource[1].Info = NULL;
2168             if (ti0->tm[tmu]) {
2169                fxMesa->TexSource[tmu].StartAddress = ti0->tm[tmu]->startAddr;
2170                fxMesa->TexSource[tmu].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2171                fxMesa->TexSource[tmu].Info = &(ti0->info);
2172             }
2173          }
2174       }
2175    }
2176    else if (ctx->Texture.Unit[0]._ReallyEnabled == 0 && 
2177             ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
2178       /* Only unit 1 2D enabled */
2179       if (shared->umaTexMemory) {
2180          fxMesa->TexSource[0].StartAddress = ti1->tm[0]->startAddr;
2181          fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2182          fxMesa->TexSource[0].Info = &(ti1->info);
2183       }
2184    }
2185    else if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT) && 
2186             ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
2187       /* Both 2D enabled */
2188       if (shared->umaTexMemory) {
2189          const FxU32 tmu0 = 0, tmu1 = 1;
2190
2191          assert(ti0);
2192          fxMesa->TexSource[tmu0].StartAddress = ti0->tm[0]->startAddr;
2193          fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2194          fxMesa->TexSource[tmu0].Info = &(ti0->info);
2195
2196          assert(ti1);
2197          fxMesa->TexSource[tmu1].StartAddress = ti1->tm[0]->startAddr;
2198          fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2199          fxMesa->TexSource[tmu1].Info = &(ti1->info);
2200       }
2201       else {
2202          const FxU32 tmu0 = 0, tmu1 = 1;
2203
2204          assert(ti0);
2205          fxMesa->TexSource[tmu0].StartAddress = ti0->tm[tmu0]->startAddr;
2206          fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2207          fxMesa->TexSource[tmu0].Info = &(ti0->info);
2208
2209          assert(ti1);
2210          fxMesa->TexSource[tmu1].StartAddress = ti1->tm[tmu1]->startAddr;
2211          fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2212          fxMesa->TexSource[tmu1].Info = &(ti1->info);
2213       }
2214    }
2215
2216
2217    fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE;
2218 }