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
->CombineModeRGB
) {
66 case GL_MODULATE_ADD_ATI
:
67 case GL_MODULATE_SIGNED_ADD_ATI
:
68 case GL_MODULATE_SUBTRACT_ATI
:
75 switch (texUnit
->CombineModeA
) {
93 for (i
= 0; i
< 3; i
++) {
99 for (i
= 0;i
< numColorArgs
; i
++) {
100 switch (texUnit
->CombineSourceRGB
[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 arg1
[i
] |= ARG_DISABLE
;
147 arg2
[i
] |= TD0_color_arg2_fcol
;
148 alpha
[i
] |= TD0_color_alpha_fcol
;
150 case GL_PRIMARY_COLOR
:
151 arg1
[i
] |= ARG_DISABLE
;
152 /* G400 specs (TDUALSTAGE1) */
153 if (unit
== 0 || (mmesa
->setup
.tdualstage0
&
154 ((TD0_color_sel_mul
& TD0_color_sel_add
) |
155 (TD0_alpha_sel_mul
& TD0_alpha_sel_add
)))) {
156 arg2
[i
] |= TD0_color_arg2_diffuse
;
157 alpha
[i
] |= TD0_color_alpha_diffuse
;
159 arg2
[i
] |= ARG_DISABLE
;
160 alpha
[i
] |= ARG_DISABLE
;
164 arg1
[i
] |= ARG_DISABLE
;
166 arg2
[i
] |= TD0_color_arg2_diffuse
;
167 alpha
[i
] |= TD0_color_alpha_diffuse
;
169 arg2
[i
] |= TD0_color_arg2_prevstage
;
170 alpha
[i
] |= TD0_color_alpha_prevstage
;
177 switch (texUnit
->CombineOperandRGB
[i
]) {
181 alpha
[i
] |= ARG_DISABLE
;
183 case GL_ONE_MINUS_SRC_COLOR
:
184 arg1
[i
] |= TD0_color_arg1_inv_enable
;
185 arg2
[i
] |= TD0_color_arg2_inv_enable
;
186 alpha
[i
] |= ARG_DISABLE
;
189 arg1
[i
] |= TD0_color_arg1_replicatealpha_enable
;
190 arg2
[i
] |= TD0_color_arg2_replicatealpha_enable
;
193 case GL_ONE_MINUS_SRC_ALPHA
:
194 arg1
[i
] |= (TD0_color_arg1_replicatealpha_enable
|
195 TD0_color_arg1_inv_enable
);
196 arg2
[i
] |= (TD0_color_arg2_replicatealpha_enable
|
197 TD0_color_arg2_inv_enable
);
198 alpha
[i
] |= (TD0_color_alpha1inv_enable
|
199 TD0_color_alpha2inv_enable
);
204 switch (texUnit
->CombineModeRGB
) {
205 case GL_MODULATE_ADD_ATI
:
206 case GL_MODULATE_SIGNED_ADD_ATI
:
207 /* Special handling for ATI_texture_env_combine3.
208 * If Arg1 == Arg0 or Arg1 == Arg2 we can use arg1 or arg2 as input for
209 * both multiplier and adder.
212 if (arg1
[1] == arg1
[0]) {
213 if ((arg1
[1] | arg2
[2]) != ARG_DISABLE
) {
214 *reg
|= arg1
[1] | arg2
[2];
215 args
[0] = MGA_ARG1
; args
[1] = MGA_ARG1
; args
[2] = MGA_ARG2
;
218 if ((arg1
[1] | alpha
[2]) != ARG_DISABLE
) {
219 *reg
|= arg1
[1] | alpha
[2];
220 args
[0] = MGA_ARG1
; args
[1] = MGA_ARG1
; args
[2] = MGA_ALPHA
;
224 if (arg1
[1] == arg1
[2]) {
225 if ((arg1
[1] | arg2
[0]) != ARG_DISABLE
) {
226 *reg
|= arg1
[1] | arg2
[0];
227 args
[0] = MGA_ARG2
; args
[1] = MGA_ARG1
; args
[2] = MGA_ARG1
;
230 if ((arg1
[1] | alpha
[0]) != ARG_DISABLE
) {
231 *reg
|= arg1
[1] | alpha
[0];
232 args
[0] = MGA_ALPHA
; args
[1] = MGA_ARG1
; args
[2] = MGA_ARG1
;
237 case GL_MODULATE_SUBTRACT_ATI
:
239 if (arg2
[1] == arg2
[0]) {
240 if ((arg2
[1] | arg1
[2]) != ARG_DISABLE
) {
241 *reg
|= arg2
[1] | arg1
[2];
242 args
[0] = MGA_ARG2
; args
[1] = MGA_ARG2
; args
[2] = MGA_ARG1
;
245 if ((arg2
[1] | alpha
[2]) != ARG_DISABLE
) {
246 *reg
|= arg2
[1] | alpha
[2];
247 args
[0] = MGA_ARG2
; args
[1] = MGA_ARG2
; args
[2] = MGA_ALPHA
;
251 if (arg2
[1] == arg2
[2]) {
252 if ((arg2
[1] | arg1
[0]) != ARG_DISABLE
) {
253 *reg
|= arg2
[1] | arg1
[0];
254 args
[0] = MGA_ARG1
; args
[1] = MGA_ARG2
; args
[2] = MGA_ARG2
;
257 if ((arg2
[1] | alpha
[0]) != ARG_DISABLE
) {
258 *reg
|= arg2
[1] | alpha
[0];
259 args
[0] = MGA_ALPHA
; args
[1] = MGA_ARG2
; args
[2] = MGA_ARG2
;
265 /* Find working combo of arg1, arg2 and alpha.
267 * Keep the Arg0 != alpha cases first since there's
268 * no way to get alpha out by itself (GL_REPLACE).
270 * Keep the Arg2 == alpha cases first because only alpha has the
271 * capabilities to function as Arg2 (GL_INTERPOLATE). Also good for
272 * GL_ADD, GL_ADD_SIGNED, GL_SUBTRACT since we can't get alpha to the
275 * Keep the Arg1 == alpha cases last for GL_MODULATE_ADD_ATI,
276 * GL_MODULATE_SIGNED_ADD_ATI. Again because we can't get alpha to the
279 * GL_MODULATE_SUBTRACT_ATI needs special treatment since it requires
280 * that Arg1 == arg2. This requirement clashes with those of other modes.
282 if ((arg1
[0] | arg2
[1] | alpha
[2]) != ARG_DISABLE
) {
283 *reg
|= arg1
[0] | arg2
[1] | alpha
[2];
284 args
[0] = MGA_ARG1
; args
[1] = MGA_ARG2
; args
[2] = MGA_ALPHA
;
286 if ((arg1
[1] | arg2
[0] | alpha
[2]) != ARG_DISABLE
&&
287 texUnit
->CombineModeRGB
!= GL_MODULATE_SUBTRACT_ATI
) {
288 *reg
|= arg1
[1] | arg2
[0] | alpha
[2];
289 args
[0] = MGA_ARG2
; args
[1] = MGA_ARG1
; args
[2] = MGA_ALPHA
;
291 if ((arg1
[1] | arg2
[2] | alpha
[0]) != ARG_DISABLE
&&
292 texUnit
->CombineModeRGB
!= GL_MODULATE_SUBTRACT_ATI
) {
293 *reg
|= arg1
[1] | arg2
[2] | alpha
[0];
294 args
[0] = MGA_ALPHA
; args
[1] = MGA_ARG1
; args
[2] = MGA_ARG2
;
296 if ((arg1
[2] | arg2
[1] | alpha
[0]) != ARG_DISABLE
) {
297 *reg
|= arg1
[2] | arg2
[1] | alpha
[0];
298 args
[0] = MGA_ALPHA
; args
[1] = MGA_ARG2
; args
[2] = MGA_ARG1
;
300 if ((arg1
[0] | arg2
[2] | alpha
[1]) != ARG_DISABLE
) {
301 *reg
|= arg1
[0] | arg2
[2] | alpha
[1];
302 args
[0] = MGA_ARG1
; args
[1] = MGA_ALPHA
; args
[2] = MGA_ARG2
;
304 if ((arg1
[2] | arg2
[0] | alpha
[1]) != ARG_DISABLE
) {
305 *reg
|= arg1
[2] | arg2
[0] | alpha
[1];
306 args
[0] = MGA_ARG2
; args
[1] = MGA_ALPHA
; args
[2] = MGA_ARG1
;
308 /* nothing suitable */
313 switch (texUnit
->CombineModeRGB
) {
315 if (texUnit
->CombineScaleShiftRGB
) {
319 if (args
[0] == MGA_ARG1
) {
320 *reg
|= TD0_color_sel_arg1
;
321 } else if (args
[0] == MGA_ARG2
) {
322 *reg
|= TD0_color_sel_arg2
;
323 } else if (args
[0] == MGA_ALPHA
) {
324 /* Can't get alpha out by itself */
329 if (texUnit
->CombineScaleShiftRGB
== 1) {
330 *reg
|= TD0_color_modbright_2x
;
331 } else if (texUnit
->CombineScaleShiftRGB
== 2) {
332 *reg
|= TD0_color_modbright_4x
;
335 *reg
|= TD0_color_sel_mul
;
337 if (args
[0] == MGA_ALPHA
|| args
[1] == MGA_ALPHA
) {
338 if (args
[0] == MGA_ARG1
|| args
[1] == MGA_ARG1
) {
339 *reg
|= TD0_color_arg2mul_alpha2
;
340 } else if (args
[0] == MGA_ARG2
|| args
[1] == MGA_ARG2
) {
341 *reg
|= TD0_color_arg1mul_alpha1
;
346 *reg
|= TD0_color_addbias_enable
;
349 if (args
[0] == MGA_ALPHA
|| args
[1] == MGA_ALPHA
){
350 /* Can't get alpha to the adder */
353 if (texUnit
->CombineScaleShiftRGB
== 1) {
354 *reg
|= TD0_color_add2x_enable
;
355 } else if (texUnit
->CombineScaleShiftRGB
== 2) {
359 *reg
|= (TD0_color_add_add
|
363 if (args
[2] != MGA_ALPHA
) {
364 /* Only alpha can function as Arg2 */
367 if (texUnit
->CombineScaleShiftRGB
== 1) {
368 *reg
|= TD0_color_add2x_enable
;
369 } else if (texUnit
->CombineScaleShiftRGB
== 2) {
373 *reg
|= (TD0_color_arg1mul_alpha1
|
374 TD0_color_blend_enable
|
375 TD0_color_arg1add_mulout
|
376 TD0_color_arg2add_mulout
|
380 /* Have to do this with xor since GL_ONE_MINUS_SRC_ALPHA may have
381 * already touched this bit.
383 *reg
^= TD0_color_alpha1inv_enable
;
385 if (args
[0] == MGA_ARG2
) {
387 *reg
^= (TD0_color_arg1mul_alpha1
|
388 TD0_color_arg2mul_alpha2
|
389 TD0_color_alpha1inv_enable
|
390 TD0_color_alpha2inv_enable
);
393 if (ctx
->Texture
._EnabledUnits
!= 0x03) {
394 /* Linear blending mode needs dualtex enabled */
395 *(reg
+1) = (TD0_color_arg2_prevstage
|
397 TD0_alpha_arg2_prevstage
|
399 mmesa
->dualtex_env
= GL_TRUE
;
403 if (args
[0] == MGA_ALPHA
|| args
[1] == MGA_ALPHA
) {
404 /* Can't get alpha to the adder */
407 if (texUnit
->CombineScaleShiftRGB
== 1) {
408 *reg
|= TD0_color_add2x_enable
;
409 } else if (texUnit
->CombineScaleShiftRGB
== 2) {
413 *reg
|= (TD0_color_add_sub
|
416 if (args
[0] == MGA_ARG2
) {
418 *reg
^= (TD0_color_arg1_inv_enable
|
419 TD0_color_arg2_inv_enable
);
422 case GL_MODULATE_SIGNED_ADD_ATI
:
423 *reg
|= TD0_color_addbias_enable
;
425 case GL_MODULATE_ADD_ATI
:
426 if (args
[1] == MGA_ALPHA
) {
427 /* Can't get alpha to the adder */
430 if (texUnit
->CombineScaleShiftRGB
== 1) {
431 *reg
|= TD0_color_add2x_enable
;
432 } else if (texUnit
->CombineScaleShiftRGB
== 2) {
436 *reg
|= (TD0_color_add_add
|
439 if (args
[1] == args
[0] || args
[1] == args
[2]) {
440 *reg
|= TD0_color_arg1add_mulout
;
441 if (args
[0] == MGA_ALPHA
|| args
[2] == MGA_ALPHA
)
442 *reg
|= TD0_color_arg1mul_alpha1
;
444 if (args
[1] == MGA_ARG1
) {
445 /* Swap adder arguments */
446 *reg
^= (TD0_color_arg1add_mulout
|
447 TD0_color_arg2add_mulout
);
448 if (args
[0] == MGA_ALPHA
|| args
[2] == MGA_ALPHA
) {
449 /* Swap multiplier arguments */
450 *reg
^= (TD0_color_arg1mul_alpha1
|
451 TD0_color_arg2mul_alpha2
);
455 *reg
|= (TD0_color_arg2mul_alpha2
|
456 TD0_color_arg1add_mulout
);
458 if (args
[1] == MGA_ARG1
) {
460 *reg
^= (TD0_color_arg1mul_alpha1
|
461 TD0_color_arg2mul_alpha2
|
462 TD0_color_arg1add_mulout
|
463 TD0_color_arg2add_mulout
);
467 case GL_MODULATE_SUBTRACT_ATI
:
468 if (args
[1] != MGA_ARG2
) {
469 /* Can't swap arguments */
472 if (texUnit
->CombineScaleShiftRGB
== 1) {
473 *reg
|= TD0_color_add2x_enable
;
474 } else if (texUnit
->CombineScaleShiftRGB
== 2) {
478 *reg
|= (TD0_color_add_sub
|
481 if (args
[1] == args
[0] || args
[1] == args
[2]) {
482 *reg
|= TD0_color_arg1add_mulout
;
483 if (args
[0] == MGA_ALPHA
|| args
[2] == MGA_ALPHA
)
484 *reg
|= TD0_color_arg1mul_alpha1
;
486 *reg
|= (TD0_color_arg2mul_alpha2
|
487 TD0_color_arg1add_mulout
);
494 for (i
= 0; i
< 2; i
++) {
499 for (i
= 0; i
< numAlphaArgs
; i
++) {
500 switch (texUnit
->CombineSourceA
[i
]) {
503 arg2
[i
] |= ARG_DISABLE
;
508 arg2
[i
] |= ARG_DISABLE
;
510 if (ctx
->Texture
._EnabledUnits
!= 0x03) {
511 /* disable texturing */
512 mmesa
->setup
.dwgctl
&= DC_opcod_MASK
;
513 mmesa
->setup
.dwgctl
|= DC_opcod_trap
;
514 mmesa
->hw
.alpha_sel
= AC_alphasel_diffused
;
515 /* return GL_TRUE since we don't need a fallback */
518 arg1
[i
] |= ARG_DISABLE
;
519 arg2
[i
] |= TD0_alpha_arg2_prevtex
;
524 if (ctx
->Texture
._EnabledUnits
!= 0x03) {
525 /* disable texturing */
526 mmesa
->setup
.dwgctl
&= DC_opcod_MASK
;
527 mmesa
->setup
.dwgctl
|= DC_opcod_trap
;
528 mmesa
->hw
.alpha_sel
= AC_alphasel_diffused
;
529 /* return GL_TRUE since we don't need a fallback */
532 arg1
[i
] |= ARG_DISABLE
;
533 /* G400 specs (TDUALSTAGE0) */
534 arg2
[i
] |= TD0_alpha_arg2_prevstage
;
537 arg2
[i
] |= ARG_DISABLE
;
541 arg1
[i
] |= ARG_DISABLE
;
542 arg2
[i
] |= TD0_alpha_arg2_fcol
;
544 case GL_PRIMARY_COLOR
:
545 arg1
[i
] |= ARG_DISABLE
;
546 /* G400 specs (TDUALSTAGE1) */
547 if (unit
== 0 || (mmesa
->setup
.tdualstage0
&
548 ((TD0_color_sel_mul
& TD0_color_sel_add
) |
549 (TD0_alpha_sel_mul
& TD0_alpha_sel_add
)))) {
550 arg2
[i
] |= TD0_alpha_arg2_diffuse
;
552 arg2
[i
] |= ARG_DISABLE
;
556 arg1
[i
] |= ARG_DISABLE
;
558 arg2
[i
] |= TD0_alpha_arg2_diffuse
;
560 arg2
[i
] |= TD0_alpha_arg2_prevstage
;
567 switch (texUnit
->CombineOperandA
[i
]) {
572 case GL_ONE_MINUS_SRC_ALPHA
:
573 arg1
[i
] |= TD0_alpha_arg1_inv_enable
;
574 arg2
[i
] |= TD0_alpha_arg2_inv_enable
;
579 /* Find a working combo of arg1 and arg2 */
580 if ((arg1
[0] | arg2
[1]) != ARG_DISABLE
) {
581 *reg
|= arg1
[0] | arg2
[1];
582 args
[0] = MGA_ARG1
; args
[1] = MGA_ARG2
;
584 if ((arg1
[1] | arg2
[0]) != ARG_DISABLE
) {
585 *reg
|= arg1
[1] | arg2
[0];
586 args
[0] = MGA_ARG2
; args
[1] = MGA_ARG1
;
588 /* nothing suitable */
592 switch (texUnit
->CombineModeA
) {
594 if (texUnit
->CombineScaleShiftA
) {
598 if (args
[0] == MGA_ARG1
){
599 *reg
|= TD0_alpha_sel_arg1
;
600 } else if (args
[0] == MGA_ARG2
) {
601 *reg
|= TD0_alpha_sel_arg2
;
605 if (texUnit
->CombineScaleShiftA
== 1) {
606 *reg
|= TD0_alpha_modbright_2x
;
607 } else if (texUnit
->CombineScaleShiftA
== 2) {
608 *reg
|= TD0_alpha_modbright_4x
;
611 *reg
|= TD0_alpha_sel_mul
;
614 *reg
|= TD0_alpha_addbias_enable
;
617 if (texUnit
->CombineScaleShiftA
== 1) {
618 *reg
|= TD0_alpha_add2x_enable
;
619 } else if (texUnit
->CombineScaleShiftA
== 2) {
623 *reg
|= (TD0_alpha_add_enable
|
627 if (texUnit
->CombineScaleShiftA
== 1) {
628 *reg
|= TD0_alpha_add2x_enable
;
629 } else if (texUnit
->CombineScaleShiftA
== 2) {
633 *reg
|= (TD0_alpha_add_disable
|
636 if (args
[0] == MGA_ARG2
) {
638 *reg
^= (TD0_alpha_arg1_inv_enable
|
639 TD0_alpha_arg2_inv_enable
);