#include "glheader.h"
#include "mgacontext.h"
#include "mgatex.h"
#include "mgaregs.h"
#define ARG_DISABLE 0xffffffff
#define MGA_ARG1 0
#define MGA_ARG2 1
#define MGA_ALPHA 2
GLboolean mgaUpdateTextureEnvCombine( GLcontext *ctx, int unit )
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
const int source = mmesa->tmu_source[unit];
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
GLuint numColorArgs = 0, numAlphaArgs = 0;
GLuint arg1[3], arg2[3], alpha[3];
int args[3];
int i;
switch (texUnit->CombineModeRGB) {
case GL_REPLACE:
numColorArgs = 1;
break;
case GL_MODULATE:
case GL_ADD:
case GL_ADD_SIGNED:
case GL_SUBTRACT:
numColorArgs = 2;
break;
case GL_INTERPOLATE:
case GL_MODULATE_ADD_ATI:
case GL_MODULATE_SIGNED_ADD_ATI:
case GL_MODULATE_SUBTRACT_ATI:
numColorArgs = 3;
break;
default:
return GL_FALSE;
}
switch (texUnit->CombineModeA) {
case GL_REPLACE:
numAlphaArgs = 1;
break;
case GL_MODULATE:
case GL_ADD:
case GL_ADD_SIGNED:
case GL_SUBTRACT:
numAlphaArgs = 2;
break;
default:
return GL_FALSE;
}
*reg = 0;
for (i = 0; i < 3; i++) {
arg1[i] = 0;
arg2[i] = 0;
alpha[i] = 0;
}
for (i = 0;i < numColorArgs; i++) {
switch (texUnit->CombineSourceRGB[i]) {
case GL_TEXTURE:
arg1[i] |= 0;
arg2[i] |= ARG_DISABLE;
alpha[i] |= TD0_color_alpha_currtex;
break;
case GL_TEXTURE0:
if (source == 0) {
arg1[i] |= 0;
arg2[i] |= ARG_DISABLE;
alpha[i] |= TD0_color_alpha_currtex;
} else {
if (ctx->Texture._EnabledUnits != 0x03) {
mmesa->setup.dwgctl &= DC_opcod_MASK;
mmesa->setup.dwgctl |= DC_opcod_trap;
mmesa->hw.alpha_sel = AC_alphasel_diffused;
return GL_TRUE;
}
arg1[i] |= ARG_DISABLE;
arg2[i] |= ARG_DISABLE;
alpha[i] |= TD0_color_alpha_prevtex;
}
break;
case GL_TEXTURE1:
if (source == 0) {
if (ctx->Texture._EnabledUnits != 0x03) {
mmesa->setup.dwgctl &= DC_opcod_MASK;
mmesa->setup.dwgctl |= DC_opcod_trap;
mmesa->hw.alpha_sel = AC_alphasel_diffused;
return GL_TRUE;
}
arg1[i] |= ARG_DISABLE;
arg2[i] |= TD0_color_arg2_prevstage;
alpha[i] |= TD0_color_alpha_prevstage;
} else {
arg1[i] |= 0;
arg2[i] |= ARG_DISABLE;
alpha[i] |= TD0_color_alpha_currtex;
}
break;
case GL_CONSTANT:
if (mmesa->fcol_used &&
mmesa->envcolor[source] != mmesa->envcolor[!source])
return GL_FALSE;
arg1[i] |= ARG_DISABLE;
arg2[i] |= TD0_color_arg2_fcol;
alpha[i] |= TD0_color_alpha_fcol;
mmesa->setup.fcol = mmesa->envcolor[source];
mmesa->fcol_used = GL_TRUE;
break;
case GL_PRIMARY_COLOR:
arg1[i] |= ARG_DISABLE;
if (unit == 0 || (mmesa->setup.tdualstage0 &
((TD0_color_sel_mul & TD0_color_sel_add) |
(TD0_alpha_sel_mul & TD0_alpha_sel_add)))) {
arg2[i] |= TD0_color_arg2_diffuse;
alpha[i] |= TD0_color_alpha_diffuse;
} else {
arg2[i] |= ARG_DISABLE;
alpha[i] |= ARG_DISABLE;
}
break;
case GL_PREVIOUS:
arg1[i] |= ARG_DISABLE;
if (unit == 0) {
arg2[i] |= TD0_color_arg2_diffuse;
alpha[i] |= TD0_color_alpha_diffuse;
} else {
arg2[i] |= TD0_color_arg2_prevstage;
alpha[i] |= TD0_color_alpha_prevstage;
}
break;
default:
return GL_FALSE;
}
switch (texUnit->CombineOperandRGB[i]) {
case GL_SRC_COLOR:
arg1[i] |= 0;
arg2[i] |= 0;
if (texUnit->CombineSourceRGB[i] == GL_CONSTANT &&
RGBA_EQUAL( mmesa->envcolor[source] )) {
alpha[i] |= 0;
} else {
alpha[i] |= ARG_DISABLE;
}
break;
case GL_ONE_MINUS_SRC_COLOR:
arg1[i] |= TD0_color_arg1_inv_enable;
arg2[i] |= TD0_color_arg2_inv_enable;
if (texUnit->CombineSourceRGB[i] == GL_CONSTANT &&
RGBA_EQUAL( mmesa->envcolor[source] )) {
alpha[i] |= (TD0_color_alpha1inv_enable |
TD0_color_alpha2inv_enable);
} else {
alpha[i] |= ARG_DISABLE;
}
break;
case GL_SRC_ALPHA:
arg1[i] |= TD0_color_arg1_replicatealpha_enable;
arg2[i] |= TD0_color_arg2_replicatealpha_enable;
alpha[i] |= 0;
break;
case GL_ONE_MINUS_SRC_ALPHA:
arg1[i] |= (TD0_color_arg1_replicatealpha_enable |
TD0_color_arg1_inv_enable);
arg2[i] |= (TD0_color_arg2_replicatealpha_enable |
TD0_color_arg2_inv_enable);
alpha[i] |= (TD0_color_alpha1inv_enable |
TD0_color_alpha2inv_enable);
break;
}
}
switch (texUnit->CombineModeRGB) {
case GL_MODULATE_ADD_ATI:
case GL_MODULATE_SIGNED_ADD_ATI:
if (arg1[1] == arg1[0]) {
if ((arg1[1] | arg2[2]) != ARG_DISABLE) {
*reg |= arg1[1] | arg2[2];
args[0] = MGA_ARG1; args[1] = MGA_ARG1; args[2] = MGA_ARG2;
break;
} else
if ((arg1[1] | alpha[2]) != ARG_DISABLE) {
*reg |= arg1[1] | alpha[2];
args[0] = MGA_ARG1; args[1] = MGA_ARG1; args[2] = MGA_ALPHA;
break;
}
}
if (arg1[1] == arg1[2]) {
if ((arg1[1] | arg2[0]) != ARG_DISABLE) {
*reg |= arg1[1] | arg2[0];
args[0] = MGA_ARG2; args[1] = MGA_ARG1; args[2] = MGA_ARG1;
break;
} else
if ((arg1[1] | alpha[0]) != ARG_DISABLE) {
*reg |= arg1[1] | alpha[0];
args[0] = MGA_ALPHA; args[1] = MGA_ARG1; args[2] = MGA_ARG1;
break;
}
}
case GL_MODULATE_SUBTRACT_ATI:
if (arg2[1] == arg2[0]) {
if ((arg2[1] | arg1[2]) != ARG_DISABLE) {
*reg |= arg2[1] | arg1[2];
args[0] = MGA_ARG2; args[1] = MGA_ARG2; args[2] = MGA_ARG1;
break;
} else
if ((arg2[1] | alpha[2]) != ARG_DISABLE) {
*reg |= arg2[1] | alpha[2];
args[0] = MGA_ARG2; args[1] = MGA_ARG2; args[2] = MGA_ALPHA;
break;
}
}
if (arg2[1] == arg2[2]) {
if ((arg2[1] | arg1[0]) != ARG_DISABLE) {
*reg |= arg2[1] | arg1[0];
args[0] = MGA_ARG1; args[1] = MGA_ARG2; args[2] = MGA_ARG2;
break;
} else
if ((arg2[1] | alpha[0]) != ARG_DISABLE) {
*reg |= arg2[1] | alpha[0];
args[0] = MGA_ALPHA; args[1] = MGA_ARG2; args[2] = MGA_ARG2;
break;
}
}
default:
if ((arg1[0] | arg2[1] | alpha[2]) != ARG_DISABLE) {
*reg |= arg1[0] | arg2[1] | alpha[2];
args[0] = MGA_ARG1; args[1] = MGA_ARG2; args[2] = MGA_ALPHA;
} else
if ((arg1[1] | arg2[0] | alpha[2]) != ARG_DISABLE &&
texUnit->CombineModeRGB != GL_MODULATE_SUBTRACT_ATI) {
*reg |= arg1[1] | arg2[0] | alpha[2];
args[0] = MGA_ARG2; args[1] = MGA_ARG1; args[2] = MGA_ALPHA;
} else
if ((arg1[1] | arg2[2] | alpha[0]) != ARG_DISABLE &&
texUnit->CombineModeRGB != GL_MODULATE_SUBTRACT_ATI) {
*reg |= arg1[1] | arg2[2] | alpha[0];
args[0] = MGA_ALPHA; args[1] = MGA_ARG1; args[2] = MGA_ARG2;
} else
if ((arg1[2] | arg2[1] | alpha[0]) != ARG_DISABLE) {
*reg |= arg1[2] | arg2[1] | alpha[0];
args[0] = MGA_ALPHA; args[1] = MGA_ARG2; args[2] = MGA_ARG1;
} else
if ((arg1[0] | arg2[2] | alpha[1]) != ARG_DISABLE) {
*reg |= arg1[0] | arg2[2] | alpha[1];
args[0] = MGA_ARG1; args[1] = MGA_ALPHA; args[2] = MGA_ARG2;
} else
if ((arg1[2] | arg2[0] | alpha[1]) != ARG_DISABLE) {
*reg |= arg1[2] | arg2[0] | alpha[1];
args[0] = MGA_ARG2; args[1] = MGA_ALPHA; args[2] = MGA_ARG1;
} else {
return GL_FALSE;
}
}
switch (texUnit->CombineModeRGB) {
case GL_REPLACE:
if (texUnit->CombineScaleShiftRGB) {
return GL_FALSE;
}
if (args[0] == MGA_ARG1) {
*reg |= TD0_color_sel_arg1;
} else if (args[0] == MGA_ARG2) {
*reg |= TD0_color_sel_arg2;
} else if (args[0] == MGA_ALPHA) {
return GL_FALSE;
}
break;
case GL_MODULATE:
if (texUnit->CombineScaleShiftRGB == 1) {
*reg |= TD0_color_modbright_2x;
} else if (texUnit->CombineScaleShiftRGB == 2) {
*reg |= TD0_color_modbright_4x;
}
*reg |= TD0_color_sel_mul;
if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) {
if (args[0] == MGA_ARG1 || args[1] == MGA_ARG1) {
*reg |= TD0_color_arg2mul_alpha2;
} else if (args[0] == MGA_ARG2 || args[1] == MGA_ARG2) {
*reg |= TD0_color_arg1mul_alpha1;
}
}
break;
case GL_ADD_SIGNED:
*reg |= TD0_color_addbias_enable;
case GL_ADD:
if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) {
return GL_FALSE;
}
if (texUnit->CombineScaleShiftRGB == 1) {
*reg |= TD0_color_add2x_enable;
} else if (texUnit->CombineScaleShiftRGB == 2) {
return GL_FALSE;
}
*reg |= (TD0_color_add_add |
TD0_color_sel_add);
break;
case GL_INTERPOLATE:
if (args[2] != MGA_ALPHA) {
return GL_FALSE;
}
if (texUnit->CombineScaleShiftRGB == 1) {
*reg |= TD0_color_add2x_enable;
} else if (texUnit->CombineScaleShiftRGB == 2) {
return GL_FALSE;
}
*reg |= (TD0_color_arg1mul_alpha1 |
TD0_color_blend_enable |
TD0_color_arg1add_mulout |
TD0_color_arg2add_mulout |
TD0_color_add_add |
TD0_color_sel_add);
*reg ^= TD0_color_alpha1inv_enable;
if (args[0] == MGA_ARG2) {
*reg ^= (TD0_color_arg1mul_alpha1 |
TD0_color_arg2mul_alpha2 |
TD0_color_alpha1inv_enable |
TD0_color_alpha2inv_enable);
}
if (ctx->Texture._EnabledUnits != 0x03) {
*(reg+1) = (TD0_color_arg2_prevstage |
TD0_color_sel_arg2 |
TD0_alpha_arg2_prevstage |
TD0_alpha_sel_arg2);
mmesa->force_dualtex = GL_TRUE;
}
break;
case GL_SUBTRACT:
if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) {
return GL_FALSE;
}
if (texUnit->CombineScaleShiftRGB == 1) {
*reg |= TD0_color_add2x_enable;
} else if (texUnit->CombineScaleShiftRGB == 2) {
return GL_FALSE;
}
*reg |= (TD0_color_add_sub |
TD0_color_sel_add);
if (args[0] == MGA_ARG2) {
*reg ^= (TD0_color_arg1_inv_enable |
TD0_color_arg2_inv_enable);
}
break;
case GL_MODULATE_SIGNED_ADD_ATI:
*reg |= TD0_color_addbias_enable;
case GL_MODULATE_ADD_ATI:
if (args[1] == MGA_ALPHA) {
return GL_FALSE;
}
if (texUnit->CombineScaleShiftRGB == 1) {
*reg |= TD0_color_add2x_enable;
} else if (texUnit->CombineScaleShiftRGB == 2) {
return GL_FALSE;
}
*reg |= (TD0_color_add_add |
TD0_color_sel_add);
if (args[1] == args[0] || args[1] == args[2]) {
*reg |= TD0_color_arg1add_mulout;
if (args[0] == MGA_ALPHA || args[2] == MGA_ALPHA)
*reg |= TD0_color_arg1mul_alpha1;
if (args[1] == MGA_ARG1) {
*reg ^= (TD0_color_arg1add_mulout |
TD0_color_arg2add_mulout);
if (args[0] == MGA_ALPHA || args[2] == MGA_ALPHA) {
*reg ^= (TD0_color_arg1mul_alpha1 |
TD0_color_arg2mul_alpha2);
}
}
} else {
*reg |= (TD0_color_arg2mul_alpha2 |
TD0_color_arg1add_mulout);
if (args[1] == MGA_ARG1) {
*reg ^= (TD0_color_arg1mul_alpha1 |
TD0_color_arg2mul_alpha2 |
TD0_color_arg1add_mulout |
TD0_color_arg2add_mulout);
}
}
break;
case GL_MODULATE_SUBTRACT_ATI:
if (args[1] != MGA_ARG2) {
return GL_FALSE;
}
if (texUnit->CombineScaleShiftRGB == 1) {
*reg |= TD0_color_add2x_enable;
} else if (texUnit->CombineScaleShiftRGB == 2) {
return GL_FALSE;
}
*reg |= (TD0_color_add_sub |
TD0_color_sel_add);
if (args[1] == args[0] || args[1] == args[2]) {
*reg |= TD0_color_arg1add_mulout;
if (args[0] == MGA_ALPHA || args[2] == MGA_ALPHA)
*reg |= TD0_color_arg1mul_alpha1;
} else {
*reg |= (TD0_color_arg2mul_alpha2 |
TD0_color_arg1add_mulout);
}
break;
}
for (i = 0; i < 2; i++) {
arg1[i] = 0;
arg2[i] = 0;
}
for (i = 0; i < numAlphaArgs; i++) {
switch (texUnit->CombineSourceA[i]) {
case GL_TEXTURE:
arg1[i] |= 0;
arg2[i] |= ARG_DISABLE;
break;
case GL_TEXTURE0:
if (source == 0) {
arg1[i] |= 0;
arg2[i] |= ARG_DISABLE;
} else {
if (ctx->Texture._EnabledUnits != 0x03) {
mmesa->setup.dwgctl &= DC_opcod_MASK;
mmesa->setup.dwgctl |= DC_opcod_trap;
mmesa->hw.alpha_sel = AC_alphasel_diffused;
return GL_TRUE;
}
arg1[i] |= ARG_DISABLE;
arg2[i] |= TD0_alpha_arg2_prevtex;
}
break;
case GL_TEXTURE1:
if (source == 0) {
if (ctx->Texture._EnabledUnits != 0x03) {
mmesa->setup.dwgctl &= DC_opcod_MASK;
mmesa->setup.dwgctl |= DC_opcod_trap;
mmesa->hw.alpha_sel = AC_alphasel_diffused;
return GL_TRUE;
}
arg1[i] |= ARG_DISABLE;
arg2[i] |= TD0_alpha_arg2_prevstage;
} else {
arg1[i] |= 0;
arg2[i] |= ARG_DISABLE;
}
break;
case GL_CONSTANT:
if (mmesa->fcol_used &&
mmesa->envcolor[source] != mmesa->envcolor[!source])
return GL_FALSE;
arg1[i] |= ARG_DISABLE;
arg2[i] |= TD0_alpha_arg2_fcol;
mmesa->setup.fcol = mmesa->envcolor[source];
mmesa->fcol_used = GL_TRUE;
break;
case GL_PRIMARY_COLOR:
arg1[i] |= ARG_DISABLE;
if (unit == 0 || (mmesa->setup.tdualstage0 &
((TD0_color_sel_mul & TD0_color_sel_add) |
(TD0_alpha_sel_mul & TD0_alpha_sel_add)))) {
arg2[i] |= TD0_alpha_arg2_diffuse;
} else {
arg2[i] |= ARG_DISABLE;
}
break;
case GL_PREVIOUS:
arg1[i] |= ARG_DISABLE;
if (unit == 0) {
arg2[i] |= TD0_alpha_arg2_diffuse;
} else {
arg2[i] |= TD0_alpha_arg2_prevstage;
}
break;
default:
return GL_FALSE;
}
switch (texUnit->CombineOperandA[i]) {
case GL_SRC_ALPHA:
arg1[i] |= 0;
arg2[i] |= 0;
break;
case GL_ONE_MINUS_SRC_ALPHA:
arg1[i] |= TD0_alpha_arg1_inv_enable;
arg2[i] |= TD0_alpha_arg2_inv_enable;
break;
}
}
if ((arg1[0] | arg2[1]) != ARG_DISABLE) {
*reg |= arg1[0] | arg2[1];
args[0] = MGA_ARG1; args[1] = MGA_ARG2;
} else
if ((arg1[1] | arg2[0]) != ARG_DISABLE) {
*reg |= arg1[1] | arg2[0];
args[0] = MGA_ARG2; args[1] = MGA_ARG1;
} else {
return GL_FALSE;
}
switch (texUnit->CombineModeA) {
case GL_REPLACE:
if (texUnit->CombineScaleShiftA) {
return GL_FALSE;
}
if (args[0] == MGA_ARG1) {
*reg |= TD0_alpha_sel_arg1;
} else if (args[0] == MGA_ARG2) {
*reg |= TD0_alpha_sel_arg2;
}
break;
case GL_MODULATE:
if (texUnit->CombineScaleShiftA == 1) {
*reg |= TD0_alpha_modbright_2x;
} else if (texUnit->CombineScaleShiftA == 2) {
*reg |= TD0_alpha_modbright_4x;
}
*reg |= TD0_alpha_sel_mul;
break;
case GL_ADD_SIGNED:
*reg |= TD0_alpha_addbias_enable;
case GL_ADD:
if (texUnit->CombineScaleShiftA == 1) {
*reg |= TD0_alpha_add2x_enable;
} else if (texUnit->CombineScaleShiftA == 2) {
return GL_FALSE;
}
*reg |= (TD0_alpha_add_enable |
TD0_alpha_sel_add);
break;
case GL_SUBTRACT:
if (texUnit->CombineScaleShiftA == 1) {
*reg |= TD0_alpha_add2x_enable;
} else if (texUnit->CombineScaleShiftA == 2) {
return GL_FALSE;
}
*reg |= (TD0_alpha_add_disable |
TD0_alpha_sel_add);
if (args[0] == MGA_ARG2) {
*reg ^= (TD0_alpha_arg1_inv_enable |
TD0_alpha_arg2_inv_enable);
}
break;
}
return GL_TRUE;
}