| /* |
| * Copyright (c) 2003 Ville Syrjala |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in |
| * all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| * DEALINGS IN THE SOFTWARE. |
| * |
| * Authors: |
| * Ville Syrjala <syrjala@sci.fi> |
| */ |
| |
| #include "glheader.h" |
| |
| #include "mgacontext.h" |
| #include "mgatex.h" |
| #include "mgaregs.h" |
| |
| /* |
| * GL_ARB_texture_env_combine |
| * GL_EXT_texture_env_combine |
| * GL_ARB_texture_env_crossbar |
| * GL_ATI_texture_env_combine3 |
| */ |
| |
| #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->Combine.ModeRGB) { |
| 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->Combine.ModeA) { |
| 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; |
| } |
| |
| /* Start fresh :) */ |
| *reg = 0; |
| |
| /* COLOR */ |
| for (i = 0; i < 3; i++) { |
| arg1[i] = 0; |
| arg2[i] = 0; |
| alpha[i] = 0; |
| } |
| |
| for (i = 0;i < numColorArgs; i++) { |
| switch (texUnit->Combine.SourceRGB[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) { |
| /* disable texturing */ |
| mmesa->setup.dwgctl &= DC_opcod_MASK; |
| mmesa->setup.dwgctl |= DC_opcod_trap; |
| mmesa->hw.alpha_sel = AC_alphasel_diffused; |
| /* return GL_TRUE since we don't need a fallback */ |
| 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) { |
| /* disable texturing */ |
| mmesa->setup.dwgctl &= DC_opcod_MASK; |
| mmesa->setup.dwgctl |= DC_opcod_trap; |
| mmesa->hw.alpha_sel = AC_alphasel_diffused; |
| /* return GL_TRUE since we don't need a fallback */ |
| return GL_TRUE; |
| } |
| arg1[i] |= ARG_DISABLE; |
| /* G400 specs (TDUALSTAGE0) */ |
| 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; |
| /* G400 specs (TDUALSTAGE1) */ |
| 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->Combine.OperandRGB[i]) { |
| case GL_SRC_COLOR: |
| arg1[i] |= 0; |
| arg2[i] |= 0; |
| if (texUnit->Combine.SourceRGB[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->Combine.SourceRGB[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->Combine.ModeRGB) { |
| case GL_MODULATE_ADD_ATI: |
| case GL_MODULATE_SIGNED_ADD_ATI: |
| /* Special handling for ATI_texture_env_combine3. |
| * If Arg1 == Arg0 or Arg1 == Arg2 we can use arg1 or arg2 as input for |
| * both multiplier and adder. |
| */ |
| /* Arg1 == arg1 */ |
| 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; |
| } |
| } |
| /* fallthrough */ |
| case GL_MODULATE_SUBTRACT_ATI: |
| /* Arg1 == arg2 */ |
| 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; |
| } |
| } |
| /* fallthrough */ |
| default: |
| /* Find working combo of arg1, arg2 and alpha. |
| * |
| * Keep the Arg0 != alpha cases first since there's |
| * no way to get alpha out by itself (GL_REPLACE). |
| * |
| * Keep the Arg2 == alpha cases first because only alpha has the |
| * capabilities to function as Arg2 (GL_INTERPOLATE). Also good for |
| * GL_ADD, GL_ADD_SIGNED, GL_SUBTRACT since we can't get alpha to the |
| * adder. |
| * |
| * Keep the Arg1 == alpha cases last for GL_MODULATE_ADD_ATI, |
| * GL_MODULATE_SIGNED_ADD_ATI. Again because we can't get alpha to the |
| * adder. |
| * |
| * GL_MODULATE_SUBTRACT_ATI needs special treatment since it requires |
| * that Arg1 == arg2. This requirement clashes with those of other modes. |
| */ |
| 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->Combine.ModeRGB != 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->Combine.ModeRGB != 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 { |
| /* nothing suitable */ |
| return GL_FALSE; |
| } |
| } |
| |
| switch (texUnit->Combine.ModeRGB) { |
| case GL_REPLACE: |
| if (texUnit->Combine.ScaleShiftRGB) { |
| 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) { |
| /* Can't get alpha out by itself */ |
| return GL_FALSE; |
| } |
| break; |
| case GL_MODULATE: |
| if (texUnit->Combine.ScaleShiftRGB == 1) { |
| *reg |= TD0_color_modbright_2x; |
| } else if (texUnit->Combine.ScaleShiftRGB == 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; |
| /* fallthrough */ |
| case GL_ADD: |
| if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) { |
| /* Can't get alpha to the adder */ |
| return GL_FALSE; |
| } |
| if (texUnit->Combine.ScaleShiftRGB == 1) { |
| *reg |= TD0_color_add2x_enable; |
| } else if (texUnit->Combine.ScaleShiftRGB == 2) { |
| return GL_FALSE; |
| } |
| |
| *reg |= (TD0_color_add_add | |
| TD0_color_sel_add); |
| break; |
| case GL_INTERPOLATE: |
| if (args[2] != MGA_ALPHA) { |
| /* Only alpha can function as Arg2 */ |
| return GL_FALSE; |
| } |
| if (texUnit->Combine.ScaleShiftRGB == 1) { |
| *reg |= TD0_color_add2x_enable; |
| } else if (texUnit->Combine.ScaleShiftRGB == 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); |
| |
| /* Have to do this with xor since GL_ONE_MINUS_SRC_ALPHA may have |
| * already touched this bit. |
| */ |
| *reg ^= TD0_color_alpha1inv_enable; |
| |
| if (args[0] == MGA_ARG2) { |
| /* Swap arguments */ |
| *reg ^= (TD0_color_arg1mul_alpha1 | |
| TD0_color_arg2mul_alpha2 | |
| TD0_color_alpha1inv_enable | |
| TD0_color_alpha2inv_enable); |
| } |
| |
| if (ctx->Texture._EnabledUnits != 0x03) { |
| /* Linear blending mode needs dualtex enabled */ |
| *(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) { |
| /* Can't get alpha to the adder */ |
| return GL_FALSE; |
| } |
| if (texUnit->Combine.ScaleShiftRGB == 1) { |
| *reg |= TD0_color_add2x_enable; |
| } else if (texUnit->Combine.ScaleShiftRGB == 2) { |
| return GL_FALSE; |
| } |
| |
| *reg |= (TD0_color_add_sub | |
| TD0_color_sel_add); |
| |
| if (args[0] == MGA_ARG2) { |
| /* Swap arguments */ |
| *reg ^= (TD0_color_arg1_inv_enable | |
| TD0_color_arg2_inv_enable); |
| } |
| break; |
| case GL_MODULATE_SIGNED_ADD_ATI: |
| *reg |= TD0_color_addbias_enable; |
| /* fallthrough */ |
| case GL_MODULATE_ADD_ATI: |
| if (args[1] == MGA_ALPHA) { |
| /* Can't get alpha to the adder */ |
| return GL_FALSE; |
| } |
| if (texUnit->Combine.ScaleShiftRGB == 1) { |
| *reg |= TD0_color_add2x_enable; |
| } else if (texUnit->Combine.ScaleShiftRGB == 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) { |
| /* Swap adder arguments */ |
| *reg ^= (TD0_color_arg1add_mulout | |
| TD0_color_arg2add_mulout); |
| if (args[0] == MGA_ALPHA || args[2] == MGA_ALPHA) { |
| /* Swap multiplier arguments */ |
| *reg ^= (TD0_color_arg1mul_alpha1 | |
| TD0_color_arg2mul_alpha2); |
| } |
| } |
| } else { |
| *reg |= (TD0_color_arg2mul_alpha2 | |
| TD0_color_arg1add_mulout); |
| |
| if (args[1] == MGA_ARG1) { |
| /* Swap arguments */ |
| *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) { |
| /* Can't swap arguments */ |
| return GL_FALSE; |
| } |
| if (texUnit->Combine.ScaleShiftRGB == 1) { |
| *reg |= TD0_color_add2x_enable; |
| } else if (texUnit->Combine.ScaleShiftRGB == 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; |
| } |
| |
| |
| /* ALPHA */ |
| for (i = 0; i < 2; i++) { |
| arg1[i] = 0; |
| arg2[i] = 0; |
| } |
| |
| for (i = 0; i < numAlphaArgs; i++) { |
| switch (texUnit->Combine.SourceA[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) { |
| /* disable texturing */ |
| mmesa->setup.dwgctl &= DC_opcod_MASK; |
| mmesa->setup.dwgctl |= DC_opcod_trap; |
| mmesa->hw.alpha_sel = AC_alphasel_diffused; |
| /* return GL_TRUE since we don't need a fallback */ |
| 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) { |
| /* disable texturing */ |
| mmesa->setup.dwgctl &= DC_opcod_MASK; |
| mmesa->setup.dwgctl |= DC_opcod_trap; |
| mmesa->hw.alpha_sel = AC_alphasel_diffused; |
| /* return GL_TRUE since we don't need a fallback */ |
| return GL_TRUE; |
| } |
| arg1[i] |= ARG_DISABLE; |
| /* G400 specs (TDUALSTAGE0) */ |
| 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; |
| /* G400 specs (TDUALSTAGE1) */ |
| 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->Combine.OperandA[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; |
| } |
| } |
| |
| /* Find a working combo of arg1 and arg2 */ |
| 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 { |
| /* nothing suitable */ |
| return GL_FALSE; |
| } |
| |
| switch (texUnit->Combine.ModeA) { |
| case GL_REPLACE: |
| if (texUnit->Combine.ScaleShiftA) { |
| 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->Combine.ScaleShiftA == 1) { |
| *reg |= TD0_alpha_modbright_2x; |
| } else if (texUnit->Combine.ScaleShiftA == 2) { |
| *reg |= TD0_alpha_modbright_4x; |
| } |
| |
| *reg |= TD0_alpha_sel_mul; |
| break; |
| case GL_ADD_SIGNED: |
| *reg |= TD0_alpha_addbias_enable; |
| /* fallthrough */ |
| case GL_ADD: |
| if (texUnit->Combine.ScaleShiftA == 1) { |
| *reg |= TD0_alpha_add2x_enable; |
| } else if (texUnit->Combine.ScaleShiftA == 2) { |
| return GL_FALSE; |
| } |
| |
| *reg |= (TD0_alpha_add_enable | |
| TD0_alpha_sel_add); |
| break; |
| case GL_SUBTRACT: |
| if (texUnit->Combine.ScaleShiftA == 1) { |
| *reg |= TD0_alpha_add2x_enable; |
| } else if (texUnit->Combine.ScaleShiftA == 2) { |
| return GL_FALSE; |
| } |
| |
| *reg |= (TD0_alpha_add_disable | |
| TD0_alpha_sel_add); |
| |
| if (args[0] == MGA_ARG2) { |
| /* Swap arguments */ |
| *reg ^= (TD0_alpha_arg1_inv_enable | |
| TD0_alpha_arg2_inv_enable); |
| } |
| break; |
| } |
| |
| return GL_TRUE; |
| } |
| |
| |