2 * Copyright (c) 2003 Ville Syrjala
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
23 * Ville Syrjala <syrjala@sci.fi>
26 #include "main/glheader.h"
28 #include "mgacontext.h"
33 * GL_ARB_texture_env_combine
34 * GL_EXT_texture_env_combine
35 * GL_ARB_texture_env_crossbar
36 * GL_ATI_texture_env_combine3
39 #define ARG_DISABLE 0xffffffff
44 GLboolean mgaUpdateTextureEnvCombine( struct gl_context *ctx, int unit )
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];
55 switch (texUnit->Combine.ModeRGB) {
66 case GL_MODULATE_ADD_ATI:
67 case GL_MODULATE_SIGNED_ADD_ATI:
68 case GL_MODULATE_SUBTRACT_ATI:
75 switch (texUnit->Combine.ModeA) {
93 for (i = 0; i < 3; i++) {
99 for (i = 0;i < numColorArgs; i++) {
100 switch (texUnit->Combine.SourceRGB[i]) {
103 arg2[i] |= ARG_DISABLE;
104 alpha[i] |= TD0_color_alpha_currtex;
109 arg2[i] |= ARG_DISABLE;
110 alpha[i] |= TD0_color_alpha_currtex;
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 */
120 arg1[i] |= ARG_DISABLE;
121 arg2[i] |= ARG_DISABLE;
122 alpha[i] |= TD0_color_alpha_prevtex;
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 */
135 arg1[i] |= ARG_DISABLE;
136 /* G400 specs (TDUALSTAGE0) */
137 arg2[i] |= TD0_color_arg2_prevstage;
138 alpha[i] |= TD0_color_alpha_prevstage;
141 arg2[i] |= ARG_DISABLE;
142 alpha[i] |= TD0_color_alpha_currtex;
146 if (mmesa->fcol_used &&
147 mmesa->envcolor[source] != mmesa->envcolor[!source])
150 arg1[i] |= ARG_DISABLE;
151 arg2[i] |= TD0_color_arg2_fcol;
152 alpha[i] |= TD0_color_alpha_fcol;
154 mmesa->setup.fcol = mmesa->envcolor[source];
155 mmesa->fcol_used = GL_TRUE;
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;
166 arg2[i] |= ARG_DISABLE;
167 alpha[i] |= ARG_DISABLE;
171 arg1[i] |= ARG_DISABLE;
173 arg2[i] |= TD0_color_arg2_diffuse;
174 alpha[i] |= TD0_color_alpha_diffuse;
176 arg2[i] |= TD0_color_arg2_prevstage;
177 alpha[i] |= TD0_color_alpha_prevstage;
184 switch (texUnit->Combine.OperandRGB[i]) {
188 if (texUnit->Combine.SourceRGB[i] == GL_CONSTANT &&
189 RGBA_EQUAL( mmesa->envcolor[source] )) {
192 alpha[i] |= ARG_DISABLE;
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);
203 alpha[i] |= ARG_DISABLE;
207 arg1[i] |= TD0_color_arg1_replicatealpha_enable;
208 arg2[i] |= TD0_color_arg2_replicatealpha_enable;
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);
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.
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;
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;
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;
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;
255 case GL_MODULATE_SUBTRACT_ATI:
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;
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;
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;
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;
283 /* Find working combo of arg1, arg2 and alpha.
285 * Keep the Arg0 != alpha cases first since there's
286 * no way to get alpha out by itself (GL_REPLACE).
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
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
297 * GL_MODULATE_SUBTRACT_ATI needs special treatment since it requires
298 * that Arg1 == arg2. This requirement clashes with those of other modes.
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;
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;
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;
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;
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;
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;
326 /* nothing suitable */
331 switch (texUnit->Combine.ModeRGB) {
333 if (texUnit->Combine.ScaleShiftRGB) {
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 */
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;
353 *reg |= TD0_color_sel_mul;
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;
364 *reg |= TD0_color_addbias_enable;
367 if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) {
368 /* Can't get alpha to the adder */
371 if (texUnit->Combine.ScaleShiftRGB == 1) {
372 *reg |= TD0_color_add2x_enable;
373 } else if (texUnit->Combine.ScaleShiftRGB == 2) {
377 *reg |= (TD0_color_add_add |
381 if (args[2] != MGA_ALPHA) {
382 /* Only alpha can function as Arg2 */
385 if (texUnit->Combine.ScaleShiftRGB == 1) {
386 *reg |= TD0_color_add2x_enable;
387 } else if (texUnit->Combine.ScaleShiftRGB == 2) {
391 *reg |= (TD0_color_arg1mul_alpha1 |
392 TD0_color_blend_enable |
393 TD0_color_arg1add_mulout |
394 TD0_color_arg2add_mulout |
398 /* Have to do this with xor since GL_ONE_MINUS_SRC_ALPHA may have
399 * already touched this bit.
401 *reg ^= TD0_color_alpha1inv_enable;
403 if (args[0] == MGA_ARG2) {
405 *reg ^= (TD0_color_arg1mul_alpha1 |
406 TD0_color_arg2mul_alpha2 |
407 TD0_color_alpha1inv_enable |
408 TD0_color_alpha2inv_enable);
411 if (ctx->Texture._EnabledUnits != 0x03) {
412 /* Linear blending mode needs dualtex enabled */
413 *(reg+1) = (TD0_color_arg2_prevstage |
415 TD0_alpha_arg2_prevstage |
417 mmesa->force_dualtex = GL_TRUE;
421 if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) {
422 /* Can't get alpha to the adder */
425 if (texUnit->Combine.ScaleShiftRGB == 1) {
426 *reg |= TD0_color_add2x_enable;
427 } else if (texUnit->Combine.ScaleShiftRGB == 2) {
431 *reg |= (TD0_color_add_sub |
434 if (args[0] == MGA_ARG2) {
436 *reg ^= (TD0_color_arg1_inv_enable |
437 TD0_color_arg2_inv_enable);
440 case GL_MODULATE_SIGNED_ADD_ATI:
441 *reg |= TD0_color_addbias_enable;
443 case GL_MODULATE_ADD_ATI:
444 if (args[1] == MGA_ALPHA) {
445 /* Can't get alpha to the adder */
448 if (texUnit->Combine.ScaleShiftRGB == 1) {
449 *reg |= TD0_color_add2x_enable;
450 } else if (texUnit->Combine.ScaleShiftRGB == 2) {
454 *reg |= (TD0_color_add_add |
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;
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);
473 *reg |= (TD0_color_arg2mul_alpha2 |
474 TD0_color_arg1add_mulout);
476 if (args[1] == MGA_ARG1) {
478 *reg ^= (TD0_color_arg1mul_alpha1 |
479 TD0_color_arg2mul_alpha2 |
480 TD0_color_arg1add_mulout |
481 TD0_color_arg2add_mulout);
485 case GL_MODULATE_SUBTRACT_ATI:
486 if (args[1] != MGA_ARG2) {
487 /* Can't swap arguments */
490 if (texUnit->Combine.ScaleShiftRGB == 1) {
491 *reg |= TD0_color_add2x_enable;
492 } else if (texUnit->Combine.ScaleShiftRGB == 2) {
496 *reg |= (TD0_color_add_sub |
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;
504 *reg |= (TD0_color_arg2mul_alpha2 |
505 TD0_color_arg1add_mulout);
512 for (i = 0; i < 2; i++) {
517 for (i = 0; i < numAlphaArgs; i++) {
518 switch (texUnit->Combine.SourceA[i]) {
521 arg2[i] |= ARG_DISABLE;
526 arg2[i] |= ARG_DISABLE;
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 */
536 arg1[i] |= ARG_DISABLE;
537 arg2[i] |= TD0_alpha_arg2_prevtex;
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 */
550 arg1[i] |= ARG_DISABLE;
551 /* G400 specs (TDUALSTAGE0) */
552 arg2[i] |= TD0_alpha_arg2_prevstage;
555 arg2[i] |= ARG_DISABLE;
559 if (mmesa->fcol_used &&
560 mmesa->envcolor[source] != mmesa->envcolor[!source])
563 arg1[i] |= ARG_DISABLE;
564 arg2[i] |= TD0_alpha_arg2_fcol;
566 mmesa->setup.fcol = mmesa->envcolor[source];
567 mmesa->fcol_used = GL_TRUE;
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;
577 arg2[i] |= ARG_DISABLE;
581 arg1[i] |= ARG_DISABLE;
583 arg2[i] |= TD0_alpha_arg2_diffuse;
585 arg2[i] |= TD0_alpha_arg2_prevstage;
592 switch (texUnit->Combine.OperandA[i]) {
597 case GL_ONE_MINUS_SRC_ALPHA:
598 arg1[i] |= TD0_alpha_arg1_inv_enable;
599 arg2[i] |= TD0_alpha_arg2_inv_enable;
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;
609 if ((arg1[1] | arg2[0]) != ARG_DISABLE) {
610 *reg |= arg1[1] | arg2[0];
611 args[0] = MGA_ARG2; args[1] = MGA_ARG1;
613 /* nothing suitable */
617 switch (texUnit->Combine.ModeA) {
619 if (texUnit->Combine.ScaleShiftA) {
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;
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;
636 *reg |= TD0_alpha_sel_mul;
639 *reg |= TD0_alpha_addbias_enable;
642 if (texUnit->Combine.ScaleShiftA == 1) {
643 *reg |= TD0_alpha_add2x_enable;
644 } else if (texUnit->Combine.ScaleShiftA == 2) {
648 *reg |= (TD0_alpha_add_enable |
652 if (texUnit->Combine.ScaleShiftA == 1) {
653 *reg |= TD0_alpha_add2x_enable;
654 } else if (texUnit->Combine.ScaleShiftA == 2) {
658 *reg |= (TD0_alpha_add_disable |
661 if (args[0] == MGA_ARG2) {
663 *reg ^= (TD0_alpha_arg1_inv_enable |
664 TD0_alpha_arg2_inv_enable);