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>
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( GLcontext
*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
);