Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / mga / mga_texcombine.c
1 /*
2  * Copyright (c) 2003 Ville Syrjala
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  *
22  * Authors:
23  *    Ville Syrjala <syrjala@sci.fi>
24  */
25
26 #include "main/glheader.h"
27
28 #include "mgacontext.h"
29 #include "mgatex.h"
30 #include "mgaregs.h"
31
32 /*
33  * GL_ARB_texture_env_combine
34  * GL_EXT_texture_env_combine
35  * GL_ARB_texture_env_crossbar
36  * GL_ATI_texture_env_combine3
37  */
38
39 #define ARG_DISABLE 0xffffffff
40 #define MGA_ARG1  0
41 #define MGA_ARG2  1
42 #define MGA_ALPHA 2
43
44 GLboolean mgaUpdateTextureEnvCombine( struct gl_context *ctx, int unit )
45 {
46    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
47    const int source = mmesa->tmu_source[unit];
48    const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
49    GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
50    GLuint numColorArgs = 0, numAlphaArgs = 0;
51    GLuint arg1[3], arg2[3], alpha[3];
52    int args[3];
53    int i;
54
55    switch (texUnit->Combine.ModeRGB) {
56    case GL_REPLACE:
57       numColorArgs = 1;
58       break;
59    case GL_MODULATE:
60    case GL_ADD:
61    case GL_ADD_SIGNED:
62    case GL_SUBTRACT:
63       numColorArgs = 2;
64       break;
65    case GL_INTERPOLATE:
66    case GL_MODULATE_ADD_ATI:
67    case GL_MODULATE_SIGNED_ADD_ATI:
68    case GL_MODULATE_SUBTRACT_ATI:
69       numColorArgs = 3;
70       break;
71    default:
72       return GL_FALSE;
73    }
74
75    switch (texUnit->Combine.ModeA) {
76    case GL_REPLACE:
77       numAlphaArgs = 1;
78       break;
79    case GL_MODULATE:
80    case GL_ADD:
81    case GL_ADD_SIGNED:
82    case GL_SUBTRACT:
83       numAlphaArgs = 2;
84       break;
85    default:
86       return GL_FALSE;
87    }
88
89    /* Start fresh :) */
90    *reg = 0;
91
92    /* COLOR */
93    for (i = 0; i < 3; i++) {
94       arg1[i] = 0;
95       arg2[i] = 0;
96       alpha[i] = 0;
97    }
98
99    for (i = 0;i < numColorArgs; i++) {
100       switch (texUnit->Combine.SourceRGB[i]) {
101       case GL_TEXTURE:
102          arg1[i] |= 0;
103          arg2[i] |= ARG_DISABLE;
104          alpha[i] |= TD0_color_alpha_currtex;
105          break;
106       case GL_TEXTURE0:
107          if (source == 0) {
108             arg1[i] |= 0;
109             arg2[i] |= ARG_DISABLE;
110             alpha[i] |= TD0_color_alpha_currtex;
111          } else {
112             if (ctx->Texture._EnabledUnits != 0x03) {
113                /* disable texturing */
114                mmesa->setup.dwgctl &= DC_opcod_MASK;
115                mmesa->setup.dwgctl |= DC_opcod_trap;
116                mmesa->hw.alpha_sel = AC_alphasel_diffused;
117                /* return GL_TRUE since we don't need a fallback */
118                return GL_TRUE;
119             }
120             arg1[i] |= ARG_DISABLE;
121             arg2[i] |= ARG_DISABLE;
122             alpha[i] |= TD0_color_alpha_prevtex;
123          }
124          break;
125       case GL_TEXTURE1:
126          if (source == 0) {
127             if (ctx->Texture._EnabledUnits != 0x03) {
128                /* disable texturing */
129                mmesa->setup.dwgctl &= DC_opcod_MASK;
130                mmesa->setup.dwgctl |= DC_opcod_trap;
131                mmesa->hw.alpha_sel = AC_alphasel_diffused;
132                /* return GL_TRUE since we don't need a fallback */
133                return GL_TRUE;
134             }
135             arg1[i] |= ARG_DISABLE;
136             /* G400 specs (TDUALSTAGE0) */
137             arg2[i] |= TD0_color_arg2_prevstage;
138             alpha[i] |= TD0_color_alpha_prevstage;
139          } else {
140             arg1[i] |= 0;
141             arg2[i] |= ARG_DISABLE;
142             alpha[i] |= TD0_color_alpha_currtex;
143          }
144          break;
145       case GL_CONSTANT:
146          if (mmesa->fcol_used &&
147              mmesa->envcolor[source] != mmesa->envcolor[!source])
148             return GL_FALSE;
149
150          arg1[i] |= ARG_DISABLE;
151          arg2[i] |= TD0_color_arg2_fcol;
152          alpha[i] |= TD0_color_alpha_fcol;
153
154          mmesa->setup.fcol = mmesa->envcolor[source];
155          mmesa->fcol_used = GL_TRUE;
156          break;
157       case GL_PRIMARY_COLOR:
158          arg1[i] |= ARG_DISABLE;
159          /* G400 specs (TDUALSTAGE1) */
160          if (unit == 0 || (mmesa->setup.tdualstage0 &
161                            ((TD0_color_sel_mul & TD0_color_sel_add) |
162                             (TD0_alpha_sel_mul & TD0_alpha_sel_add)))) {
163             arg2[i] |= TD0_color_arg2_diffuse;
164             alpha[i] |= TD0_color_alpha_diffuse;
165          } else {
166             arg2[i] |= ARG_DISABLE;
167             alpha[i] |= ARG_DISABLE;
168          }
169          break;
170       case GL_PREVIOUS:
171          arg1[i] |= ARG_DISABLE;
172          if (unit == 0) {
173             arg2[i] |= TD0_color_arg2_diffuse;
174             alpha[i] |= TD0_color_alpha_diffuse;
175          } else {
176             arg2[i] |= TD0_color_arg2_prevstage;
177             alpha[i] |= TD0_color_alpha_prevstage;
178          }
179          break;
180       default:
181          return GL_FALSE;
182       }
183
184       switch (texUnit->Combine.OperandRGB[i]) {
185       case GL_SRC_COLOR:
186          arg1[i] |= 0;
187          arg2[i] |= 0;
188          if (texUnit->Combine.SourceRGB[i] == GL_CONSTANT &&
189              RGBA_EQUAL( mmesa->envcolor[source] )) {
190             alpha[i] |= 0;
191          } else {
192             alpha[i] |= ARG_DISABLE;
193          }
194          break;
195       case GL_ONE_MINUS_SRC_COLOR:
196          arg1[i] |= TD0_color_arg1_inv_enable;
197          arg2[i] |= TD0_color_arg2_inv_enable;
198          if (texUnit->Combine.SourceRGB[i] == GL_CONSTANT &&
199              RGBA_EQUAL( mmesa->envcolor[source] )) {
200             alpha[i] |= (TD0_color_alpha1inv_enable |
201                          TD0_color_alpha2inv_enable);
202          } else {
203             alpha[i] |= ARG_DISABLE;
204          }
205          break;
206       case GL_SRC_ALPHA:
207          arg1[i] |= TD0_color_arg1_replicatealpha_enable;
208          arg2[i] |= TD0_color_arg2_replicatealpha_enable;
209          alpha[i] |= 0;
210          break;
211       case GL_ONE_MINUS_SRC_ALPHA:
212          arg1[i] |= (TD0_color_arg1_replicatealpha_enable |
213                      TD0_color_arg1_inv_enable);
214          arg2[i] |= (TD0_color_arg2_replicatealpha_enable |
215                      TD0_color_arg2_inv_enable);
216          alpha[i] |= (TD0_color_alpha1inv_enable |
217                       TD0_color_alpha2inv_enable);
218          break;
219       }
220    }
221
222    switch (texUnit->Combine.ModeRGB) {
223    case GL_MODULATE_ADD_ATI:
224    case GL_MODULATE_SIGNED_ADD_ATI:
225       /* Special handling for ATI_texture_env_combine3.
226        * If Arg1 == Arg0 or Arg1 == Arg2 we can use arg1 or arg2 as input for
227        * both multiplier and adder.
228        */
229       /* Arg1 == arg1 */
230       if (arg1[1] == arg1[0]) {
231          if ((arg1[1] | arg2[2]) != ARG_DISABLE) {
232             *reg |= arg1[1] | arg2[2];
233             args[0] = MGA_ARG1; args[1] = MGA_ARG1; args[2] = MGA_ARG2;
234             break;
235          } else
236          if ((arg1[1] | alpha[2]) != ARG_DISABLE) {
237             *reg |= arg1[1] | alpha[2];
238             args[0] = MGA_ARG1; args[1] = MGA_ARG1; args[2] = MGA_ALPHA;
239             break;
240          }
241       }
242       if (arg1[1] == arg1[2]) {
243          if ((arg1[1] | arg2[0]) != ARG_DISABLE) {
244             *reg |= arg1[1] | arg2[0];
245             args[0] = MGA_ARG2; args[1] = MGA_ARG1; args[2] = MGA_ARG1;
246             break;
247          } else
248          if ((arg1[1] | alpha[0]) != ARG_DISABLE) {
249             *reg |= arg1[1] | alpha[0];
250             args[0] = MGA_ALPHA; args[1] = MGA_ARG1; args[2] = MGA_ARG1;
251             break;
252          }
253       }
254       /* fallthrough */
255    case GL_MODULATE_SUBTRACT_ATI:
256       /* Arg1 == arg2 */
257       if (arg2[1] == arg2[0]) {
258          if ((arg2[1] | arg1[2]) != ARG_DISABLE) {
259             *reg |= arg2[1] | arg1[2];
260             args[0] = MGA_ARG2; args[1] = MGA_ARG2; args[2] = MGA_ARG1;
261             break;
262          } else
263          if ((arg2[1] | alpha[2]) != ARG_DISABLE) {
264             *reg |= arg2[1] | alpha[2];
265             args[0] = MGA_ARG2; args[1] = MGA_ARG2; args[2] = MGA_ALPHA;
266             break;
267          }
268       }
269       if (arg2[1] == arg2[2]) {
270          if ((arg2[1] | arg1[0]) != ARG_DISABLE) {
271             *reg |= arg2[1] | arg1[0];
272             args[0] = MGA_ARG1; args[1] = MGA_ARG2; args[2] = MGA_ARG2;
273             break;
274          } else
275          if ((arg2[1] | alpha[0]) != ARG_DISABLE) {
276             *reg |= arg2[1] | alpha[0];
277             args[0] = MGA_ALPHA; args[1] = MGA_ARG2; args[2] = MGA_ARG2;
278             break;
279          }
280       }
281       /* fallthrough */
282    default:
283       /* Find working combo of arg1, arg2 and alpha.
284        *
285        * Keep the Arg0 != alpha cases first since there's
286        * no way to get alpha out by itself (GL_REPLACE).
287        *
288        * Keep the Arg2 == alpha cases first because only alpha has the
289        * capabilities to function as Arg2 (GL_INTERPOLATE). Also good for 
290        * GL_ADD, GL_ADD_SIGNED, GL_SUBTRACT since we can't get alpha to the
291        * adder.
292        *
293        * Keep the Arg1 == alpha cases last for GL_MODULATE_ADD_ATI,
294        * GL_MODULATE_SIGNED_ADD_ATI. Again because we can't get alpha to the
295        * adder.
296        *
297        * GL_MODULATE_SUBTRACT_ATI needs special treatment since it requires
298        * that Arg1 == arg2. This requirement clashes with those of other modes.
299        */
300       if ((arg1[0] | arg2[1] | alpha[2]) != ARG_DISABLE) {
301          *reg |= arg1[0] | arg2[1] | alpha[2];
302          args[0] = MGA_ARG1; args[1] = MGA_ARG2; args[2] = MGA_ALPHA;
303       } else
304       if ((arg1[1] | arg2[0] | alpha[2]) != ARG_DISABLE &&
305           texUnit->Combine.ModeRGB != GL_MODULATE_SUBTRACT_ATI) {
306          *reg |= arg1[1] | arg2[0] | alpha[2];
307          args[0] = MGA_ARG2; args[1] = MGA_ARG1; args[2] = MGA_ALPHA;
308       } else
309       if ((arg1[1] | arg2[2] | alpha[0]) != ARG_DISABLE &&
310           texUnit->Combine.ModeRGB != GL_MODULATE_SUBTRACT_ATI) {
311          *reg |= arg1[1] | arg2[2] | alpha[0];
312          args[0] = MGA_ALPHA; args[1] = MGA_ARG1; args[2] = MGA_ARG2;
313       } else
314       if ((arg1[2] | arg2[1] | alpha[0]) != ARG_DISABLE) {
315          *reg |= arg1[2] | arg2[1] | alpha[0];
316          args[0] = MGA_ALPHA; args[1] = MGA_ARG2; args[2] = MGA_ARG1;
317       } else
318       if ((arg1[0] | arg2[2] | alpha[1]) != ARG_DISABLE) {
319          *reg |= arg1[0] | arg2[2] | alpha[1];
320          args[0] = MGA_ARG1; args[1] = MGA_ALPHA; args[2] = MGA_ARG2;
321       } else
322       if ((arg1[2] | arg2[0] | alpha[1]) != ARG_DISABLE) {
323          *reg |= arg1[2] | arg2[0] | alpha[1];
324          args[0] = MGA_ARG2; args[1] = MGA_ALPHA; args[2] = MGA_ARG1;
325       } else {
326          /* nothing suitable */
327          return GL_FALSE;
328       }
329    }
330
331    switch (texUnit->Combine.ModeRGB) {
332    case GL_REPLACE:
333       if (texUnit->Combine.ScaleShiftRGB) {
334          return GL_FALSE;
335       }
336
337       if (args[0] == MGA_ARG1) {
338          *reg |= TD0_color_sel_arg1;
339       } else if (args[0] == MGA_ARG2) {
340          *reg |= TD0_color_sel_arg2;
341       } else if (args[0] == MGA_ALPHA) {
342          /* Can't get alpha out by itself */
343          return GL_FALSE;
344       }
345       break;
346    case GL_MODULATE:
347       if (texUnit->Combine.ScaleShiftRGB == 1) {
348          *reg |= TD0_color_modbright_2x;
349       } else if (texUnit->Combine.ScaleShiftRGB == 2) {
350          *reg |= TD0_color_modbright_4x;
351       }
352
353       *reg |= TD0_color_sel_mul;
354
355       if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) {
356          if (args[0] == MGA_ARG1 || args[1] == MGA_ARG1) {
357             *reg |= TD0_color_arg2mul_alpha2;
358          } else if (args[0] == MGA_ARG2 || args[1] == MGA_ARG2) {
359             *reg |= TD0_color_arg1mul_alpha1;
360          }
361       }
362       break;
363    case GL_ADD_SIGNED:
364       *reg |= TD0_color_addbias_enable;
365       /* fallthrough */
366    case GL_ADD:
367       if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) {
368          /* Can't get alpha to the adder */
369          return GL_FALSE;
370       }
371       if (texUnit->Combine.ScaleShiftRGB == 1) {
372          *reg |= TD0_color_add2x_enable;
373       } else if (texUnit->Combine.ScaleShiftRGB == 2) {
374          return GL_FALSE;
375       }
376
377       *reg |= (TD0_color_add_add |
378                TD0_color_sel_add);
379       break;
380    case GL_INTERPOLATE:
381       if (args[2] != MGA_ALPHA) {
382          /* Only alpha can function as Arg2 */
383          return GL_FALSE;
384       }
385       if (texUnit->Combine.ScaleShiftRGB == 1) {
386          *reg |= TD0_color_add2x_enable;
387       } else if (texUnit->Combine.ScaleShiftRGB == 2) {
388          return GL_FALSE;
389       }
390
391       *reg |= (TD0_color_arg1mul_alpha1 |
392                TD0_color_blend_enable |
393                TD0_color_arg1add_mulout |
394                TD0_color_arg2add_mulout |
395                TD0_color_add_add |
396                TD0_color_sel_add);
397
398       /* Have to do this with xor since GL_ONE_MINUS_SRC_ALPHA may have
399        * already touched this bit.
400        */
401       *reg ^= TD0_color_alpha1inv_enable;
402
403       if (args[0] == MGA_ARG2) {
404          /* Swap arguments */
405          *reg ^= (TD0_color_arg1mul_alpha1 |
406                   TD0_color_arg2mul_alpha2 |
407                   TD0_color_alpha1inv_enable |
408                   TD0_color_alpha2inv_enable);
409       }
410
411       if (ctx->Texture._EnabledUnits != 0x03) {
412          /* Linear blending mode needs dualtex enabled */
413          *(reg+1) = (TD0_color_arg2_prevstage |
414                      TD0_color_sel_arg2 |
415                      TD0_alpha_arg2_prevstage |
416                      TD0_alpha_sel_arg2);
417          mmesa->force_dualtex = GL_TRUE;
418       }
419       break;
420    case GL_SUBTRACT:
421       if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) {
422          /* Can't get alpha to the adder */
423          return GL_FALSE;
424       }
425       if (texUnit->Combine.ScaleShiftRGB == 1) {
426          *reg |= TD0_color_add2x_enable;
427       } else if (texUnit->Combine.ScaleShiftRGB == 2) {
428          return GL_FALSE;
429       }
430
431       *reg |= (TD0_color_add_sub |
432                TD0_color_sel_add);
433
434       if (args[0] == MGA_ARG2) {
435          /* Swap arguments */
436          *reg ^= (TD0_color_arg1_inv_enable |
437                   TD0_color_arg2_inv_enable);
438       }
439       break;
440    case GL_MODULATE_SIGNED_ADD_ATI:
441       *reg |= TD0_color_addbias_enable;
442       /* fallthrough */
443    case GL_MODULATE_ADD_ATI:
444       if (args[1] == MGA_ALPHA) {
445          /* Can't get alpha to the adder */
446          return GL_FALSE;
447       }
448       if (texUnit->Combine.ScaleShiftRGB == 1) {
449          *reg |= TD0_color_add2x_enable;
450       } else if (texUnit->Combine.ScaleShiftRGB == 2) {
451          return GL_FALSE;
452       }
453
454       *reg |= (TD0_color_add_add |
455                TD0_color_sel_add);
456
457       if (args[1] == args[0] || args[1] == args[2]) {
458          *reg |= TD0_color_arg1add_mulout;
459          if (args[0] == MGA_ALPHA || args[2] == MGA_ALPHA)
460             *reg |= TD0_color_arg1mul_alpha1;
461
462          if (args[1] == MGA_ARG1) {
463             /* Swap adder arguments */
464             *reg ^= (TD0_color_arg1add_mulout |
465                      TD0_color_arg2add_mulout);
466             if (args[0] == MGA_ALPHA || args[2] == MGA_ALPHA) {
467                /* Swap multiplier arguments */
468                *reg ^= (TD0_color_arg1mul_alpha1 |
469                         TD0_color_arg2mul_alpha2);
470             }
471          }
472       } else {
473          *reg |= (TD0_color_arg2mul_alpha2 |
474                   TD0_color_arg1add_mulout);
475
476          if (args[1] == MGA_ARG1) {
477             /* Swap arguments */
478             *reg ^= (TD0_color_arg1mul_alpha1 |
479                      TD0_color_arg2mul_alpha2 |
480                      TD0_color_arg1add_mulout |
481                      TD0_color_arg2add_mulout);
482          }
483       }
484       break;
485    case GL_MODULATE_SUBTRACT_ATI:
486       if (args[1] != MGA_ARG2) {
487          /* Can't swap arguments */
488          return GL_FALSE;
489       }
490       if (texUnit->Combine.ScaleShiftRGB == 1) {
491          *reg |= TD0_color_add2x_enable;
492       } else if (texUnit->Combine.ScaleShiftRGB == 2) {
493          return GL_FALSE;
494       }
495
496       *reg |= (TD0_color_add_sub |
497                TD0_color_sel_add);
498
499       if (args[1] == args[0] || args[1] == args[2]) {
500          *reg |= TD0_color_arg1add_mulout;
501          if (args[0] == MGA_ALPHA || args[2] == MGA_ALPHA)
502             *reg |= TD0_color_arg1mul_alpha1;
503       } else {
504          *reg |= (TD0_color_arg2mul_alpha2 |
505                   TD0_color_arg1add_mulout);
506       }
507       break;
508    }
509
510
511    /* ALPHA */
512    for (i = 0; i < 2; i++) {
513       arg1[i] = 0;
514       arg2[i] = 0;
515    }
516
517    for (i = 0; i < numAlphaArgs; i++) {
518       switch (texUnit->Combine.SourceA[i]) {
519       case GL_TEXTURE:
520          arg1[i] |= 0;
521          arg2[i] |= ARG_DISABLE;
522          break;
523       case GL_TEXTURE0:
524          if (source == 0) {
525             arg1[i] |= 0;
526             arg2[i] |= ARG_DISABLE;
527          } else {
528             if (ctx->Texture._EnabledUnits != 0x03) {
529                /* disable texturing */
530                mmesa->setup.dwgctl &= DC_opcod_MASK;
531                mmesa->setup.dwgctl |= DC_opcod_trap;
532                mmesa->hw.alpha_sel = AC_alphasel_diffused;
533                /* return GL_TRUE since we don't need a fallback */
534                return GL_TRUE;
535             }
536             arg1[i] |= ARG_DISABLE;
537             arg2[i] |= TD0_alpha_arg2_prevtex;
538          }
539          break;
540       case GL_TEXTURE1:
541          if (source == 0) {
542             if (ctx->Texture._EnabledUnits != 0x03) {
543                /* disable texturing */
544                mmesa->setup.dwgctl &= DC_opcod_MASK;
545                mmesa->setup.dwgctl |= DC_opcod_trap;
546                mmesa->hw.alpha_sel = AC_alphasel_diffused;
547                /* return GL_TRUE since we don't need a fallback */
548                return GL_TRUE;
549             }
550             arg1[i] |= ARG_DISABLE;
551             /* G400 specs (TDUALSTAGE0) */
552             arg2[i] |= TD0_alpha_arg2_prevstage;
553          } else {
554             arg1[i] |= 0;
555             arg2[i] |= ARG_DISABLE;
556          }
557          break;
558       case GL_CONSTANT:
559          if (mmesa->fcol_used &&
560              mmesa->envcolor[source] != mmesa->envcolor[!source])
561             return GL_FALSE;
562
563          arg1[i] |= ARG_DISABLE;
564          arg2[i] |= TD0_alpha_arg2_fcol;
565
566          mmesa->setup.fcol = mmesa->envcolor[source];
567          mmesa->fcol_used = GL_TRUE;
568          break;
569       case GL_PRIMARY_COLOR:
570          arg1[i] |= ARG_DISABLE;
571          /* G400 specs (TDUALSTAGE1) */
572          if (unit == 0 || (mmesa->setup.tdualstage0 &
573                            ((TD0_color_sel_mul & TD0_color_sel_add) |
574                             (TD0_alpha_sel_mul & TD0_alpha_sel_add)))) {
575             arg2[i] |= TD0_alpha_arg2_diffuse;
576          } else {
577             arg2[i] |= ARG_DISABLE;
578          }
579          break;
580       case GL_PREVIOUS:
581          arg1[i] |= ARG_DISABLE;
582          if (unit == 0) {
583             arg2[i] |= TD0_alpha_arg2_diffuse;
584          } else {
585             arg2[i] |= TD0_alpha_arg2_prevstage;
586          }
587          break;
588       default:
589          return GL_FALSE;
590       }
591
592       switch (texUnit->Combine.OperandA[i]) {
593       case GL_SRC_ALPHA:
594          arg1[i] |= 0;
595          arg2[i] |= 0;
596          break;
597       case GL_ONE_MINUS_SRC_ALPHA:
598          arg1[i] |= TD0_alpha_arg1_inv_enable;
599          arg2[i] |= TD0_alpha_arg2_inv_enable;
600          break;
601       }
602    }
603
604    /* Find a working combo of arg1 and arg2 */
605    if ((arg1[0] | arg2[1]) != ARG_DISABLE) {
606       *reg |= arg1[0] | arg2[1];
607       args[0] = MGA_ARG1; args[1] = MGA_ARG2;
608    } else
609    if ((arg1[1] | arg2[0]) != ARG_DISABLE) {
610       *reg |= arg1[1] | arg2[0];
611       args[0] = MGA_ARG2; args[1] = MGA_ARG1;
612    } else {
613       /* nothing suitable */
614       return GL_FALSE;
615    }
616
617    switch (texUnit->Combine.ModeA) {
618    case GL_REPLACE:
619       if (texUnit->Combine.ScaleShiftA) {
620          return GL_FALSE;
621       }
622
623       if (args[0] == MGA_ARG1) {
624          *reg |= TD0_alpha_sel_arg1;
625       } else if (args[0] == MGA_ARG2) {
626          *reg |= TD0_alpha_sel_arg2;
627       }
628       break;
629    case GL_MODULATE:
630       if (texUnit->Combine.ScaleShiftA == 1) {
631          *reg |= TD0_alpha_modbright_2x;
632       } else if (texUnit->Combine.ScaleShiftA == 2) {
633          *reg |= TD0_alpha_modbright_4x;
634       }
635
636       *reg |= TD0_alpha_sel_mul;
637       break;
638    case GL_ADD_SIGNED:
639       *reg |= TD0_alpha_addbias_enable;
640       /* fallthrough */
641    case GL_ADD:
642       if (texUnit->Combine.ScaleShiftA == 1) {
643          *reg |= TD0_alpha_add2x_enable;
644       } else if (texUnit->Combine.ScaleShiftA == 2) {
645          return GL_FALSE;
646       }
647
648       *reg |= (TD0_alpha_add_enable |
649                TD0_alpha_sel_add);
650       break;
651    case GL_SUBTRACT:
652       if (texUnit->Combine.ScaleShiftA == 1) {
653          *reg |= TD0_alpha_add2x_enable;
654       } else if (texUnit->Combine.ScaleShiftA == 2) {
655          return GL_FALSE;
656       }
657
658       *reg |= (TD0_alpha_add_disable |
659                TD0_alpha_sel_add);
660
661       if (args[0] == MGA_ARG2) {
662          /* Swap arguments */
663          *reg ^= (TD0_alpha_arg1_inv_enable |
664                   TD0_alpha_arg2_inv_enable);
665       }
666       break;
667    }
668
669    return GL_TRUE;
670 }
671    
672