/* -*- mode: c; c-basic-offset: 3 -*- * * Copyright 2000 VA Linux Systems Inc., Fremont, California. * * All Rights Reserved. * * 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 (including the next * paragraph) 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 * VA LINUX SYSTEMS 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. */ /* * New fixes: * Daniel Borca , 19 Jul 2004 * * Original rewrite: * Gareth Hughes , 29 Sep - 1 Oct 2000 * * Authors: * Gareth Hughes * Brian Paul * */ #include "tdfx_state.h" #include "tdfx_texman.h" #include "tdfx_texstate.h" /* ============================================================= * Texture */ /* * These macros are used below when handling COMBINE_EXT. */ #define TEXENV_OPERAND_INVERTED(operand) \ (((operand) == GL_ONE_MINUS_SRC_ALPHA) \ || ((operand) == GL_ONE_MINUS_SRC_COLOR)) #define TEXENV_OPERAND_ALPHA(operand) \ (((operand) == GL_SRC_ALPHA) || ((operand) == GL_ONE_MINUS_SRC_ALPHA)) #define TEXENV_SETUP_ARG_A(param, source, operand, iteratedAlpha) \ switch (source) { \ case GL_TEXTURE: \ param = GR_CMBX_LOCAL_TEXTURE_ALPHA; \ break; \ case GL_CONSTANT_EXT: \ param = GR_CMBX_TMU_CALPHA; \ break; \ case GL_PRIMARY_COLOR_EXT: \ param = GR_CMBX_ITALPHA; \ break; \ case GL_PREVIOUS_EXT: \ param = iteratedAlpha; \ break; \ default: \ /* \ * This is here just to keep from getting \ * compiler warnings. \ */ \ param = GR_CMBX_ZERO; \ break; \ } #define TEXENV_SETUP_ARG_RGB(param, source, operand, iteratedColor, iteratedAlpha) \ if (!TEXENV_OPERAND_ALPHA(operand)) { \ switch (source) { \ case GL_TEXTURE: \ param = GR_CMBX_LOCAL_TEXTURE_RGB; \ break; \ case GL_CONSTANT_EXT: \ param = GR_CMBX_TMU_CCOLOR; \ break; \ case GL_PRIMARY_COLOR_EXT: \ param = GR_CMBX_ITRGB; \ break; \ case GL_PREVIOUS_EXT: \ param = iteratedColor; \ break; \ default: \ /* \ * This is here just to keep from getting \ * compiler warnings. \ */ \ param = GR_CMBX_ZERO; \ break; \ } \ } else { \ switch (source) { \ case GL_TEXTURE: \ param = GR_CMBX_LOCAL_TEXTURE_ALPHA; \ break; \ case GL_CONSTANT_EXT: \ param = GR_CMBX_TMU_CALPHA; \ break; \ case GL_PRIMARY_COLOR_EXT: \ param = GR_CMBX_ITALPHA; \ break; \ case GL_PREVIOUS_EXT: \ param = iteratedAlpha; \ break; \ default: \ /* \ * This is here just to keep from getting \ * compiler warnings. \ */ \ param = GR_CMBX_ZERO; \ break; \ } \ } #define TEXENV_SETUP_MODE_RGB(param, operand) \ switch (operand) { \ case GL_SRC_COLOR: \ case GL_SRC_ALPHA: \ param = GR_FUNC_MODE_X; \ break; \ case GL_ONE_MINUS_SRC_ALPHA: \ case GL_ONE_MINUS_SRC_COLOR: \ param = GR_FUNC_MODE_ONE_MINUS_X; \ break; \ default: \ param = GR_FUNC_MODE_ZERO; \ break; \ } #define TEXENV_SETUP_MODE_A(param, operand) \ switch (operand) { \ case GL_SRC_ALPHA: \ param = GR_FUNC_MODE_X; \ break; \ case GL_ONE_MINUS_SRC_ALPHA: \ param = GR_FUNC_MODE_ONE_MINUS_X; \ break; \ default: \ param = GR_FUNC_MODE_ZERO; \ break; \ } /* * Setup a texture environment on Voodoo5. * Return GL_TRUE for success, GL_FALSE for failure. * If we fail, we'll have to use software rendering. */ static GLboolean SetupTexEnvNapalm(struct gl_context *ctx, GLboolean useIteratedRGBA, const struct gl_texture_unit *texUnit, GLenum baseFormat, struct tdfx_texcombine_ext *env) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); GrTCCUColor_t incomingRGB, incomingAlpha; const GLenum envMode = texUnit->EnvMode; if (useIteratedRGBA) { incomingRGB = GR_CMBX_ITRGB; incomingAlpha = GR_CMBX_ITALPHA; } else { incomingRGB = GR_CMBX_OTHER_TEXTURE_RGB; incomingAlpha = GR_CMBX_OTHER_TEXTURE_ALPHA; } /* invariant: */ env->Color.Shift = 0; env->Color.Invert = FXFALSE; env->Alpha.Shift = 0; env->Alpha.Invert = FXFALSE; switch (envMode) { case GL_REPLACE: /* -- Setup RGB combiner */ if (baseFormat == GL_ALPHA) { /* Rv = Rf */ env->Color.SourceA = incomingRGB; } else { /* Rv = Rt */ env->Color.SourceA = GR_CMBX_LOCAL_TEXTURE_RGB; } env->Color.ModeA = GR_FUNC_MODE_X; env->Color.SourceB = GR_CMBX_ZERO; env->Color.ModeB = GR_FUNC_MODE_ZERO; env->Color.SourceC = GR_CMBX_ZERO; env->Color.InvertC = FXTRUE; env->Color.SourceD = GR_CMBX_ZERO; env->Color.InvertD = FXFALSE; /* -- Setup Alpha combiner */ if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) { /* Av = Af */ env->Alpha.SourceD = incomingAlpha; } else { /* Av = At */ env->Alpha.SourceD = GR_CMBX_LOCAL_TEXTURE_ALPHA; } env->Alpha.SourceA = GR_CMBX_ITALPHA; env->Alpha.ModeA = GR_FUNC_MODE_ZERO; env->Alpha.SourceB = GR_CMBX_ITALPHA; env->Alpha.ModeB = GR_FUNC_MODE_ZERO; env->Alpha.SourceC = GR_CMBX_ZERO; env->Alpha.InvertC = FXFALSE; env->Alpha.InvertD = FXFALSE; break; case GL_MODULATE: /* -- Setup RGB combiner */ if (baseFormat == GL_ALPHA) { /* Rv = Rf */ env->Color.SourceC = GR_CMBX_ZERO; env->Color.InvertC = FXTRUE; } else { /* Result = Frag * Tex */ env->Color.SourceC = GR_CMBX_LOCAL_TEXTURE_RGB; env->Color.InvertC = FXFALSE; } env->Color.SourceA = incomingRGB; env->Color.ModeA = GR_FUNC_MODE_X; env->Color.SourceB = GR_CMBX_ZERO; env->Color.ModeB = GR_FUNC_MODE_ZERO; env->Color.SourceD = GR_CMBX_ZERO; env->Color.InvertD = FXFALSE; /* -- Setup Alpha combiner */ if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) { /* Av = Af */ env->Alpha.SourceA = incomingAlpha; env->Alpha.SourceC = GR_CMBX_ZERO; env->Alpha.InvertC = FXTRUE; } else { /* Av = Af * At */ env->Alpha.SourceA = GR_CMBX_LOCAL_TEXTURE_ALPHA; env->Alpha.SourceC = incomingAlpha; env->Alpha.InvertC = FXFALSE; } env->Alpha.ModeA = GR_FUNC_MODE_X; env->Alpha.SourceB = GR_CMBX_ITALPHA; env->Alpha.ModeB = GR_FUNC_MODE_ZERO; env->Alpha.SourceD = GR_CMBX_ZERO; env->Alpha.InvertD = FXFALSE; break; case GL_DECAL: /* -- Setup RGB combiner */ if (baseFormat == GL_RGB) { /* Rv = Rt */ env->Color.SourceB = GR_CMBX_ZERO; env->Color.ModeB = GR_FUNC_MODE_X; env->Color.SourceC = GR_CMBX_ZERO; env->Color.InvertC = FXTRUE; env->Color.SourceD = GR_CMBX_ZERO; env->Color.InvertD = FXFALSE; } else { /* Rv = Rf * (1 - At) + Rt * At */ env->Color.SourceB = incomingRGB; env->Color.ModeB = GR_FUNC_MODE_NEGATIVE_X; env->Color.SourceC = GR_CMBX_LOCAL_TEXTURE_ALPHA; env->Color.InvertC = FXFALSE; env->Color.SourceD = GR_CMBX_B; env->Color.InvertD = FXFALSE; } env->Color.SourceA = GR_CMBX_LOCAL_TEXTURE_RGB; env->Color.ModeA = GR_FUNC_MODE_X; /* -- Setup Alpha combiner */ /* Av = Af */ env->Alpha.SourceA = incomingAlpha; env->Alpha.ModeA = GR_FUNC_MODE_X; env->Alpha.SourceB = GR_CMBX_ITALPHA; env->Alpha.ModeB = GR_FUNC_MODE_ZERO; env->Alpha.SourceC = GR_CMBX_ZERO; env->Alpha.InvertC = FXTRUE; env->Alpha.SourceD = GR_CMBX_ZERO; env->Alpha.InvertD = FXFALSE; break; case GL_BLEND: /* -- Setup RGB combiner */ if (baseFormat == GL_ALPHA) { /* Rv = Rf */ env->Color.SourceA = incomingRGB; env->Color.ModeA = GR_FUNC_MODE_X; env->Color.SourceB = GR_CMBX_ZERO; env->Color.ModeB = GR_FUNC_MODE_ZERO; env->Color.SourceC = GR_CMBX_ZERO; env->Color.InvertC = FXTRUE; env->Color.SourceD = GR_CMBX_ZERO; env->Color.InvertD = FXFALSE; } else { /* Rv = Rf * (1 - Rt) + Rc * Rt */ env->Color.SourceA = GR_CMBX_TMU_CCOLOR; env->Color.ModeA = GR_FUNC_MODE_X; env->Color.SourceB = incomingRGB; env->Color.ModeB = GR_FUNC_MODE_NEGATIVE_X; env->Color.SourceC = GR_CMBX_LOCAL_TEXTURE_RGB; env->Color.InvertC = FXFALSE; env->Color.SourceD = GR_CMBX_B; env->Color.InvertD = FXFALSE; } /* -- Setup Alpha combiner */ if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) { /* Av = Af */ env->Alpha.SourceA = incomingAlpha; env->Alpha.ModeA = GR_FUNC_MODE_X; env->Alpha.SourceB = GR_CMBX_ZERO; env->Alpha.ModeB = GR_FUNC_MODE_ZERO; env->Alpha.SourceC = GR_CMBX_ZERO; env->Alpha.InvertC = FXTRUE; env->Alpha.SourceD = GR_CMBX_ZERO; env->Alpha.InvertD = FXFALSE; } else if (baseFormat == GL_INTENSITY) { /* Av = Af * (1 - It) + Ac * It */ env->Alpha.SourceA = GR_CMBX_TMU_CALPHA; env->Alpha.ModeA = GR_FUNC_MODE_X; env->Alpha.SourceB = incomingAlpha; env->Alpha.ModeB = GR_FUNC_MODE_NEGATIVE_X; env->Alpha.SourceC = GR_CMBX_LOCAL_TEXTURE_ALPHA; env->Alpha.InvertC = FXFALSE; env->Alpha.SourceD = GR_CMBX_B; env->Alpha.InvertD = FXFALSE; } else { /* Av = Af * At */ env->Alpha.SourceA = GR_CMBX_LOCAL_TEXTURE_ALPHA; env->Alpha.ModeA = GR_FUNC_MODE_X; env->Alpha.SourceB = GR_CMBX_ITALPHA; env->Alpha.ModeB = GR_FUNC_MODE_ZERO; env->Alpha.SourceC = incomingAlpha; env->Alpha.InvertC = FXFALSE; env->Alpha.SourceD = GR_CMBX_ZERO; env->Alpha.InvertD = FXFALSE; } /* Also have to set up the tex env constant color */ env->EnvColor = PACK_RGBA32(texUnit->EnvColor[0] * 255.0F, texUnit->EnvColor[1] * 255.0F, texUnit->EnvColor[2] * 255.0F, texUnit->EnvColor[3] * 255.0F); break; case GL_ADD: /* -- Setup RGB combiner */ if (baseFormat == GL_ALPHA) { /* Rv = Rf */ env->Color.SourceB = GR_CMBX_ZERO; env->Color.ModeB = GR_FUNC_MODE_ZERO; } else { /* Rv = Rf + Tt */ env->Color.SourceB = GR_CMBX_LOCAL_TEXTURE_RGB; env->Color.ModeB = GR_FUNC_MODE_X; } env->Color.SourceA = incomingRGB; env->Color.ModeA = GR_FUNC_MODE_X; env->Color.SourceC = GR_CMBX_ZERO; env->Color.InvertC = FXTRUE; env->Color.SourceD = GR_CMBX_ZERO; env->Color.InvertD = FXFALSE; /* -- Setup Alpha combiner */ if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) { /* Av = Af */ env->Alpha.SourceA = incomingAlpha; env->Alpha.SourceB = GR_CMBX_ITALPHA; env->Alpha.ModeB = GR_FUNC_MODE_ZERO; env->Alpha.SourceC = GR_CMBX_ZERO; env->Alpha.InvertC = FXTRUE; } else if (baseFormat == GL_INTENSITY) { /* Av = Af + It */ env->Alpha.SourceA = incomingAlpha; env->Alpha.SourceB = GR_CMBX_LOCAL_TEXTURE_ALPHA; env->Alpha.ModeB = GR_FUNC_MODE_X; env->Alpha.SourceC = GR_CMBX_ZERO; env->Alpha.InvertC = FXTRUE; } else { /* Av = Af * At */ env->Alpha.SourceA = GR_CMBX_LOCAL_TEXTURE_ALPHA; env->Alpha.SourceB = GR_CMBX_ITALPHA; env->Alpha.ModeB = GR_FUNC_MODE_ZERO; env->Alpha.SourceC = incomingAlpha; env->Alpha.InvertC = FXFALSE; } env->Alpha.ModeA = GR_FUNC_MODE_X; env->Alpha.SourceD = GR_CMBX_ZERO; env->Alpha.InvertD = FXFALSE; break; case GL_COMBINE_EXT: { FxU32 A_RGB, B_RGB, C_RGB, D_RGB; FxU32 Amode_RGB, Bmode_RGB; FxBool Cinv_RGB, Dinv_RGB, Ginv_RGB; FxU32 Shift_RGB; FxU32 A_A, B_A, C_A, D_A; FxU32 Amode_A, Bmode_A; FxBool Cinv_A, Dinv_A, Ginv_A; FxU32 Shift_A; /* * * In the formulas below, we write: * o "1(x)" for the identity function applied to x, * so 1(x) = x. * o "0(x)" for the constant function 0, so * 0(x) = 0 for all values of x. * * Calculate the color combination. */ Shift_RGB = texUnit->Combine.ScaleShiftRGB; Shift_A = texUnit->Combine.ScaleShiftA; switch (texUnit->Combine.ModeRGB) { case GL_REPLACE: /* * The formula is: Arg0 * We implement this by the formula: * (Arg0 + 0(0))*(1-0) + 0 */ TEXENV_SETUP_ARG_RGB(A_RGB, texUnit->Combine.SourceRGB[0], texUnit->Combine.OperandRGB[0], incomingRGB, incomingAlpha); TEXENV_SETUP_MODE_RGB(Amode_RGB, texUnit->Combine.OperandRGB[0]); B_RGB = C_RGB = D_RGB = GR_CMBX_ZERO; Bmode_RGB = GR_FUNC_MODE_ZERO; Cinv_RGB = FXTRUE; Dinv_RGB = Ginv_RGB = FXFALSE; break; case GL_MODULATE: /* * The formula is: Arg0 * Arg1 * * We implement this by the formula * (Arg0 + 0(0)) * Arg1 + 0(0) */ TEXENV_SETUP_ARG_RGB(A_RGB, texUnit->Combine.SourceRGB[0], texUnit->Combine.OperandRGB[0], incomingRGB, incomingAlpha); TEXENV_SETUP_MODE_RGB(Amode_RGB, texUnit->Combine.OperandRGB[0]); B_RGB = GR_CMBX_ZERO; Bmode_RGB = GR_CMBX_ZERO; TEXENV_SETUP_ARG_RGB(C_RGB, texUnit->Combine.SourceRGB[1], texUnit->Combine.OperandRGB[1], incomingRGB, incomingAlpha); Cinv_RGB = TEXENV_OPERAND_INVERTED (texUnit->Combine.OperandRGB[1]); D_RGB = GR_CMBX_ZERO; Dinv_RGB = Ginv_RGB = FXFALSE; break; case GL_ADD: /* * The formula is Arg0 + Arg1 */ TEXENV_SETUP_ARG_RGB(A_RGB, texUnit->Combine.SourceRGB[0], texUnit->Combine.OperandRGB[0], incomingRGB, incomingAlpha); TEXENV_SETUP_MODE_RGB(Amode_RGB, texUnit->Combine.OperandRGB[0]); TEXENV_SETUP_ARG_RGB(B_RGB, texUnit->Combine.SourceRGB[1], texUnit->Combine.OperandRGB[1], incomingRGB, incomingAlpha); TEXENV_SETUP_MODE_RGB(Bmode_RGB, texUnit->Combine.OperandRGB[1]); C_RGB = D_RGB = GR_CMBX_ZERO; Cinv_RGB = FXTRUE; Dinv_RGB = Ginv_RGB = FXFALSE; break; case GL_ADD_SIGNED_EXT: /* * The formula is: Arg0 + Arg1 - 0.5. * We compute this by calculating: * (Arg0 - 1/2) + Arg1 if op0 is SRC_{COLOR,ALPHA} * Arg0 + (Arg1 - 1/2) if op1 is SRC_{COLOR,ALPHA} * If both op0 and op1 are ONE_MINUS_SRC_{COLOR,ALPHA} * we cannot implement the formula properly. */ TEXENV_SETUP_ARG_RGB(A_RGB, texUnit->Combine.SourceRGB[0], texUnit->Combine.OperandRGB[0], incomingRGB, incomingAlpha); TEXENV_SETUP_ARG_RGB(B_RGB, texUnit->Combine.SourceRGB[1], texUnit->Combine.OperandRGB[1], incomingRGB, incomingAlpha); if (!TEXENV_OPERAND_INVERTED(texUnit->Combine.OperandRGB[0])) { /* * A is not inverted. So, choose it. */ Amode_RGB = GR_FUNC_MODE_X_MINUS_HALF; if (!TEXENV_OPERAND_INVERTED (texUnit->Combine.OperandRGB[1])) { Bmode_RGB = GR_FUNC_MODE_X; } else { Bmode_RGB = GR_FUNC_MODE_ONE_MINUS_X; } } else { /* * A is inverted, so try to subtract 1/2 * from B. */ Amode_RGB = GR_FUNC_MODE_ONE_MINUS_X; if (!TEXENV_OPERAND_INVERTED (texUnit->Combine.OperandRGB[1])) { Bmode_RGB = GR_FUNC_MODE_X_MINUS_HALF; } else { /* * Both are inverted. This is the case * we cannot handle properly. We just * choose to not add the - 1/2. */ Bmode_RGB = GR_FUNC_MODE_ONE_MINUS_X; return GL_FALSE; } } C_RGB = D_RGB = GR_CMBX_ZERO; Cinv_RGB = FXTRUE; Dinv_RGB = Ginv_RGB = FXFALSE; break; case GL_INTERPOLATE_EXT: /* * The formula is: Arg0 * Arg2 + Arg1 * (1 - Arg2). * We compute this by the formula: * (Arg0 - Arg1) * Arg2 + Arg1 * == Arg0 * Arg2 - Arg1 * Arg2 + Arg1 * == Arg0 * Arg2 + Arg1 * (1 - Arg2) * However, if both Arg1 is ONE_MINUS_X, the HW does * not support it properly. */ TEXENV_SETUP_ARG_RGB(A_RGB, texUnit->Combine.SourceRGB[0], texUnit->Combine.OperandRGB[0], incomingRGB, incomingAlpha); TEXENV_SETUP_MODE_RGB(Amode_RGB, texUnit->Combine.OperandRGB[0]); TEXENV_SETUP_ARG_RGB(B_RGB, texUnit->Combine.SourceRGB[1], texUnit->Combine.OperandRGB[1], incomingRGB, incomingAlpha); if (TEXENV_OPERAND_INVERTED(texUnit->Combine.OperandRGB[1])) { /* * This case is wrong. */ Bmode_RGB = GR_FUNC_MODE_NEGATIVE_X; return GL_FALSE; } else { Bmode_RGB = GR_FUNC_MODE_NEGATIVE_X; } /* * The Source/Operand for the C value must * specify some kind of alpha value. */ TEXENV_SETUP_ARG_A(C_RGB, texUnit->Combine.SourceRGB[2], texUnit->Combine.OperandRGB[2], incomingAlpha); Cinv_RGB = FXFALSE; D_RGB = GR_CMBX_B; Dinv_RGB = Ginv_RGB = FXFALSE; break; default: /* * This is here mostly to keep from getting * a compiler warning about these not being set. * However, this should set all the texture values * to zero. */ A_RGB = B_RGB = C_RGB = D_RGB = GR_CMBX_ZERO; Amode_RGB = Bmode_RGB = GR_FUNC_MODE_X; Cinv_RGB = Dinv_RGB = Ginv_RGB = FXFALSE; break; } /* * Calculate the alpha combination. */ switch (texUnit->Combine.ModeA) { case GL_REPLACE: /* * The formula is: Arg0 * We implement this by the formula: * (Arg0 + 0(0))*(1-0) + 0 */ TEXENV_SETUP_ARG_A(A_A, texUnit->Combine.SourceA[0], texUnit->Combine.OperandA[0], incomingAlpha); TEXENV_SETUP_MODE_A(Amode_A, texUnit->Combine.OperandA[0]); B_A = GR_CMBX_ITALPHA; Bmode_A = GR_FUNC_MODE_ZERO; C_A = D_A = GR_CMBX_ZERO; Cinv_A = FXTRUE; Dinv_A = Ginv_A = FXFALSE; break; case GL_MODULATE: /* * The formula is: Arg0 * Arg1 * * We implement this by the formula * (Arg0 + 0(0)) * Arg1 + 0(0) */ TEXENV_SETUP_ARG_A(A_A, texUnit->Combine.SourceA[0], texUnit->Combine.OperandA[0], incomingAlpha); TEXENV_SETUP_MODE_A(Amode_A, texUnit->Combine.OperandA[0]); B_A = GR_CMBX_ZERO; Bmode_A = GR_CMBX_ZERO; TEXENV_SETUP_ARG_A(C_A, texUnit->Combine.SourceA[1], texUnit->Combine.OperandA[1], incomingAlpha); Cinv_A = TEXENV_OPERAND_INVERTED (texUnit->Combine.OperandA[1]); D_A = GR_CMBX_ZERO; Dinv_A = Ginv_A = FXFALSE; break; case GL_ADD: /* * The formula is Arg0 + Arg1 */ TEXENV_SETUP_ARG_A(A_A, texUnit->Combine.SourceA[0], texUnit->Combine.OperandA[0], incomingAlpha); TEXENV_SETUP_MODE_A(Amode_A, texUnit->Combine.OperandA[0]); TEXENV_SETUP_ARG_A(B_A, texUnit->Combine.SourceA[1], texUnit->Combine.OperandA[1], incomingAlpha); TEXENV_SETUP_MODE_A(Bmode_A, texUnit->Combine.OperandA[1]); C_A = D_A = GR_CMBX_ZERO; Cinv_A = FXTRUE; Dinv_A = Ginv_A = FXFALSE; break; case GL_ADD_SIGNED_EXT: /* * The formula is: Arg0 + Arg1 - 0.5. * We compute this by calculating: * (Arg0 - 1/2) + Arg1 if op0 is SRC_{COLOR,ALPHA} * Arg0 + (Arg1 - 1/2) if op1 is SRC_{COLOR,ALPHA} * If both op0 and op1 are ONE_MINUS_SRC_{COLOR,ALPHA} * we cannot implement the formula properly. */ TEXENV_SETUP_ARG_A(A_A, texUnit->Combine.SourceA[0], texUnit->Combine.OperandA[0], incomingAlpha); TEXENV_SETUP_ARG_A(B_A, texUnit->Combine.SourceA[1], texUnit->Combine.OperandA[1], incomingAlpha); if (!TEXENV_OPERAND_INVERTED(texUnit->Combine.OperandA[0])) { /* * A is not inverted. So, choose it. */ Amode_A = GR_FUNC_MODE_X_MINUS_HALF; if (!TEXENV_OPERAND_INVERTED (texUnit->Combine.OperandA[1])) { Bmode_A = GR_FUNC_MODE_X; } else { Bmode_A = GR_FUNC_MODE_ONE_MINUS_X; } } else { /* * A is inverted, so try to subtract 1/2 * from B. */ Amode_A = GR_FUNC_MODE_ONE_MINUS_X; if (!TEXENV_OPERAND_INVERTED (texUnit->Combine.OperandA[1])) { Bmode_A = GR_FUNC_MODE_X_MINUS_HALF; } else { /* * Both are inverted. This is the case * we cannot handle properly. We just * choose to not add the - 1/2. */ Bmode_A = GR_FUNC_MODE_ONE_MINUS_X; return GL_FALSE; } } C_A = D_A = GR_CMBX_ZERO; Cinv_A = FXTRUE; Dinv_A = Ginv_A = FXFALSE; break; case GL_INTERPOLATE_EXT: /* * The formula is: Arg0 * Arg2 + Arg1 * (1 - Arg2). * We compute this by the formula: * (Arg0 - Arg1) * Arg2 + Arg1 * == Arg0 * Arg2 - Arg1 * Arg2 + Arg1 * == Arg0 * Arg2 + Arg1 * (1 - Arg2) * However, if both Arg1 is ONE_MINUS_X, the HW does * not support it properly. */ TEXENV_SETUP_ARG_A(A_A, texUnit->Combine.SourceA[0], texUnit->Combine.OperandA[0], incomingAlpha); TEXENV_SETUP_MODE_A(Amode_A, texUnit->Combine.OperandA[0]); TEXENV_SETUP_ARG_A(B_A, texUnit->Combine.SourceA[1], texUnit->Combine.OperandA[1], incomingAlpha); if (!TEXENV_OPERAND_INVERTED(texUnit->Combine.OperandA[1])) { Bmode_A = GR_FUNC_MODE_NEGATIVE_X; } else { /* * This case is wrong. */ Bmode_A = GR_FUNC_MODE_NEGATIVE_X; return GL_FALSE; } /* * The Source/Operand for the C value must * specify some kind of alpha value. */ TEXENV_SETUP_ARG_A(C_A, texUnit->Combine.SourceA[2], texUnit->Combine.OperandA[2], incomingAlpha); Cinv_A = FXFALSE; D_A = GR_CMBX_B; Dinv_A = Ginv_A = FXFALSE; break; default: /* * This is here mostly to keep from getting * a compiler warning about these not being set. * However, this should set all the alpha values * to one. */ A_A = B_A = C_A = D_A = GR_CMBX_ZERO; Amode_A = Bmode_A = GR_FUNC_MODE_X; Cinv_A = Dinv_A = FXFALSE; Ginv_A = FXTRUE; break; } /* * Save the parameters. */ env->Color.SourceA = A_RGB; env->Color.ModeA = Amode_RGB; env->Color.SourceB = B_RGB; env->Color.ModeB = Bmode_RGB; env->Color.SourceC = C_RGB; env->Color.InvertC = Cinv_RGB; env->Color.SourceD = D_RGB; env->Color.InvertD = Dinv_RGB; env->Color.Shift = Shift_RGB; env->Color.Invert = Ginv_RGB; env->Alpha.SourceA = A_A; env->Alpha.ModeA = Amode_A; env->Alpha.SourceB = B_A; env->Alpha.ModeB = Bmode_A; env->Alpha.SourceC = C_A; env->Alpha.InvertC = Cinv_A; env->Alpha.SourceD = D_A; env->Alpha.InvertD = Dinv_A; env->Alpha.Shift = Shift_A; env->Alpha.Invert = Ginv_A; env->EnvColor = PACK_RGBA32(texUnit->EnvColor[0] * 255.0F, texUnit->EnvColor[1] * 255.0F, texUnit->EnvColor[2] * 255.0F, texUnit->EnvColor[3] * 255.0F); } break; default: _mesa_problem(ctx, "%s: Bad envMode", __FUNCTION__); } fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_ENV; fxMesa->ColorCombineExt.SourceA = GR_CMBX_TEXTURE_RGB; fxMesa->ColorCombineExt.ModeA = GR_FUNC_MODE_X, fxMesa->ColorCombineExt.SourceB = GR_CMBX_ZERO; fxMesa->ColorCombineExt.ModeB = GR_FUNC_MODE_X; fxMesa->ColorCombineExt.SourceC = GR_CMBX_ZERO; fxMesa->ColorCombineExt.InvertC = FXTRUE; fxMesa->ColorCombineExt.SourceD = GR_CMBX_ZERO; fxMesa->ColorCombineExt.InvertD = FXFALSE; fxMesa->ColorCombineExt.Shift = 0; fxMesa->ColorCombineExt.Invert = FXFALSE; fxMesa->dirty |= TDFX_UPLOAD_COLOR_COMBINE; fxMesa->AlphaCombineExt.SourceA = GR_CMBX_TEXTURE_ALPHA; fxMesa->AlphaCombineExt.ModeA = GR_FUNC_MODE_X; fxMesa->AlphaCombineExt.SourceB = GR_CMBX_ZERO; fxMesa->AlphaCombineExt.ModeB = GR_FUNC_MODE_X; fxMesa->AlphaCombineExt.SourceC = GR_CMBX_ZERO; fxMesa->AlphaCombineExt.InvertC = FXTRUE; fxMesa->AlphaCombineExt.SourceD = GR_CMBX_ZERO; fxMesa->AlphaCombineExt.InvertD = FXFALSE; fxMesa->AlphaCombineExt.Shift = 0; fxMesa->AlphaCombineExt.Invert = FXFALSE; fxMesa->dirty |= TDFX_UPLOAD_ALPHA_COMBINE; return GL_TRUE; /* success */ } /* * Setup the Voodoo3 texture environment for a single texture unit. * Return GL_TRUE for success, GL_FALSE for failure. * If failure, we'll use software rendering. */ static GLboolean SetupSingleTexEnvVoodoo3(struct gl_context *ctx, int unit, GLenum envMode, GLenum baseFormat) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); GrCombineLocal_t localc, locala; struct tdfx_combine alphaComb, colorComb; if (1 /*iteratedRGBA*/) localc = locala = GR_COMBINE_LOCAL_ITERATED; else localc = locala = GR_COMBINE_LOCAL_CONSTANT; switch (envMode) { case GL_DECAL: alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL; alphaComb.Factor = GR_COMBINE_FACTOR_NONE; alphaComb.Local = locala; alphaComb.Other = GR_COMBINE_OTHER_NONE; alphaComb.Invert = FXFALSE; colorComb.Function = GR_COMBINE_FUNCTION_BLEND; colorComb.Factor = GR_COMBINE_FACTOR_TEXTURE_ALPHA; colorComb.Local = localc; colorComb.Other = GR_COMBINE_OTHER_TEXTURE; colorComb.Invert = FXFALSE; break; case GL_MODULATE: alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL; alphaComb.Local = locala; alphaComb.Other = GR_COMBINE_OTHER_TEXTURE; alphaComb.Invert = FXFALSE; if (baseFormat == GL_ALPHA) { colorComb.Function = GR_COMBINE_FUNCTION_LOCAL; colorComb.Factor = GR_COMBINE_FACTOR_NONE; colorComb.Local = localc; colorComb.Other = GR_COMBINE_OTHER_NONE; colorComb.Invert = FXFALSE; } else { colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; colorComb.Factor = GR_COMBINE_FACTOR_LOCAL; colorComb.Local = localc; colorComb.Other = GR_COMBINE_OTHER_TEXTURE; colorComb.Invert = FXFALSE; } break; case GL_BLEND: /* * XXX we can't do real GL_BLEND mode. These settings assume that * the TexEnv color is black and incoming fragment color is white. */ if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) { /* Av = Af */ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL; alphaComb.Factor = GR_COMBINE_FACTOR_NONE; alphaComb.Local = locala; alphaComb.Other = GR_COMBINE_OTHER_NONE; alphaComb.Invert = FXFALSE; } else if (baseFormat == GL_INTENSITY) { /* Av = Af * (1 - It) + Ac * It */ alphaComb.Function = GR_COMBINE_FUNCTION_BLEND; alphaComb.Factor = GR_COMBINE_FACTOR_TEXTURE_ALPHA; alphaComb.Local = locala; alphaComb.Other = GR_COMBINE_OTHER_CONSTANT; alphaComb.Invert = FXFALSE; } else { /* Av = Af * At */ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL; alphaComb.Local = locala; alphaComb.Other = GR_COMBINE_OTHER_TEXTURE; alphaComb.Invert = FXFALSE; } if (baseFormat == GL_ALPHA) { colorComb.Function = GR_COMBINE_FUNCTION_LOCAL; colorComb.Factor = GR_COMBINE_FACTOR_NONE; colorComb.Local = localc; colorComb.Other = GR_COMBINE_OTHER_NONE; colorComb.Invert = FXFALSE; } else { colorComb.Function = GR_COMBINE_FUNCTION_BLEND; colorComb.Factor = GR_COMBINE_FACTOR_TEXTURE_RGB; colorComb.Local = localc; colorComb.Other = GR_COMBINE_OTHER_CONSTANT; colorComb.Invert = FXTRUE; } fxMesa->Color.MonoColor = PACK_RGBA32( ctx->Texture.Unit[unit].EnvColor[0] * 255.0f, ctx->Texture.Unit[unit].EnvColor[1] * 255.0f, ctx->Texture.Unit[unit].EnvColor[2] * 255.0f, ctx->Texture.Unit[unit].EnvColor[3] * 255.0f); fxMesa->dirty |= TDFX_UPLOAD_CONSTANT_COLOR; break; case GL_REPLACE: if ((baseFormat == GL_RGB) || (baseFormat == GL_LUMINANCE)) { alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL; alphaComb.Factor = GR_COMBINE_FACTOR_NONE; alphaComb.Local = locala; alphaComb.Other = GR_COMBINE_OTHER_NONE; alphaComb.Invert = FXFALSE; } else { alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; alphaComb.Factor = GR_COMBINE_FACTOR_ONE; alphaComb.Local = locala; alphaComb.Other = GR_COMBINE_OTHER_TEXTURE; alphaComb.Invert = FXFALSE; } if (baseFormat == GL_ALPHA) { colorComb.Function = GR_COMBINE_FUNCTION_LOCAL; colorComb.Factor = GR_COMBINE_FACTOR_NONE; colorComb.Local = localc; colorComb.Other = GR_COMBINE_OTHER_NONE; colorComb.Invert = FXFALSE; } else { colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; colorComb.Factor = GR_COMBINE_FACTOR_ONE; colorComb.Local = localc; colorComb.Other = GR_COMBINE_OTHER_TEXTURE; colorComb.Invert = FXFALSE; } break; case GL_ADD: if (baseFormat == GL_ALPHA || baseFormat == GL_LUMINANCE_ALPHA || baseFormat == GL_RGBA) { /* product of texel and fragment alpha */ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL; alphaComb.Local = locala; alphaComb.Other = GR_COMBINE_OTHER_TEXTURE; alphaComb.Invert = FXFALSE; } else if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) { /* fragment alpha is unchanged */ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL; alphaComb.Factor = GR_COMBINE_FACTOR_NONE; alphaComb.Local = locala; alphaComb.Other = GR_COMBINE_OTHER_NONE; alphaComb.Invert = FXFALSE; } else { ASSERT(baseFormat == GL_INTENSITY); /* sum of texel and fragment alpha */ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, alphaComb.Factor = GR_COMBINE_FACTOR_ONE; alphaComb.Local = locala; alphaComb.Other = GR_COMBINE_OTHER_TEXTURE; alphaComb.Invert = FXFALSE; } if (baseFormat == GL_ALPHA) { /* rgb unchanged */ colorComb.Function = GR_COMBINE_FUNCTION_LOCAL; colorComb.Factor = GR_COMBINE_FACTOR_NONE; colorComb.Local = localc; colorComb.Other = GR_COMBINE_OTHER_NONE; colorComb.Invert = FXFALSE; } else { /* sum of texel and fragment rgb */ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, colorComb.Factor = GR_COMBINE_FACTOR_ONE; colorComb.Local = localc; colorComb.Other = GR_COMBINE_OTHER_TEXTURE; colorComb.Invert = FXFALSE; } break; default: { (void) memcpy(&colorComb, &fxMesa->ColorCombine, sizeof(colorComb)); (void) memcpy(&alphaComb, &fxMesa->AlphaCombine, sizeof(alphaComb)); _mesa_problem(ctx, "bad texture env mode in %s", __FUNCTION__); } } if (colorComb.Function != fxMesa->ColorCombine.Function || colorComb.Factor != fxMesa->ColorCombine.Factor || colorComb.Local != fxMesa->ColorCombine.Local || colorComb.Other != fxMesa->ColorCombine.Other || colorComb.Invert != fxMesa->ColorCombine.Invert) { fxMesa->ColorCombine = colorComb; fxMesa->dirty |= TDFX_UPLOAD_COLOR_COMBINE; } if (alphaComb.Function != fxMesa->AlphaCombine.Function || alphaComb.Factor != fxMesa->AlphaCombine.Factor || alphaComb.Local != fxMesa->AlphaCombine.Local || alphaComb.Other != fxMesa->AlphaCombine.Other || alphaComb.Invert != fxMesa->AlphaCombine.Invert) { fxMesa->AlphaCombine = alphaComb; fxMesa->dirty |= TDFX_UPLOAD_ALPHA_COMBINE; } return GL_TRUE; } /* * Setup the Voodoo3 texture environment for dual texture units. * Return GL_TRUE for success, GL_FALSE for failure. * If failure, we'll use software rendering. */ static GLboolean SetupDoubleTexEnvVoodoo3(struct gl_context *ctx, int tmu0, GLenum envMode0, GLenum baseFormat0, GLenum envMode1, GLenum baseFormat1) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); const GrCombineLocal_t locala = GR_COMBINE_LOCAL_ITERATED; const GrCombineLocal_t localc = GR_COMBINE_LOCAL_ITERATED; const int tmu1 = 1 - tmu0; if (envMode0 == GL_MODULATE && envMode1 == GL_MODULATE) { GLboolean isalpha[TDFX_NUM_TMU]; isalpha[tmu0] = (baseFormat0 == GL_ALPHA); isalpha[tmu1] = (baseFormat1 == GL_ALPHA); if (isalpha[TDFX_TMU1]) { fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].InvertRGB = FXTRUE; fxMesa->TexCombine[1].InvertAlpha = FXFALSE; } else { fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].InvertRGB = FXFALSE; fxMesa->TexCombine[1].InvertAlpha = FXFALSE; } if (isalpha[TDFX_TMU0]) { fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_LOCAL; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; } else { fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_LOCAL; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_LOCAL; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; } fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_LOCAL; fxMesa->ColorCombine.Local = localc; fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE; fxMesa->ColorCombine.Invert = FXFALSE; fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_LOCAL; fxMesa->AlphaCombine.Local = locala; fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_TEXTURE; fxMesa->AlphaCombine.Invert = FXFALSE; } else if (envMode0 == GL_REPLACE && envMode1 == GL_BLEND) { /* Quake */ if (tmu0 == TDFX_TMU1) { fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].InvertRGB = FXTRUE; fxMesa->TexCombine[1].InvertAlpha = FXFALSE; fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_LOCAL; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_LOCAL; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; } else { fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].InvertRGB = FXFALSE; fxMesa->TexCombine[1].InvertAlpha = FXFALSE; fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE_MINUS_LOCAL; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE_MINUS_LOCAL; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; } fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_ONE; fxMesa->ColorCombine.Local = localc; fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE; fxMesa->ColorCombine.Invert = FXFALSE; fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL; fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE; fxMesa->AlphaCombine.Local = locala; fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE; fxMesa->AlphaCombine.Invert = FXFALSE; } else if (envMode0 == GL_REPLACE && envMode1 == GL_MODULATE) { /* Quake 2/3 */ if (tmu1 == TDFX_TMU1) { fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_ZERO; fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].InvertRGB = FXFALSE; fxMesa->TexCombine[1].InvertAlpha = FXTRUE; fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_LOCAL; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_LOCAL; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; } else { fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].InvertRGB = FXFALSE; fxMesa->TexCombine[1].InvertAlpha = FXFALSE; fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_LOCAL; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; } fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_ONE; fxMesa->ColorCombine.Local = localc; fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE; fxMesa->ColorCombine.Invert = FXFALSE; if (baseFormat0 == GL_RGB) { fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL; fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE; fxMesa->AlphaCombine.Local = locala; fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE; fxMesa->AlphaCombine.Invert = FXFALSE; } else { fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_ONE; fxMesa->AlphaCombine.Local = locala; fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE; fxMesa->AlphaCombine.Invert = FXFALSE; } } else if (envMode0 == GL_MODULATE && envMode1 == GL_ADD) { /* Quake 3 sky */ GLboolean isalpha[TDFX_NUM_TMU]; isalpha[tmu0] = (baseFormat0 == GL_ALPHA); isalpha[tmu1] = (baseFormat1 == GL_ALPHA); if (isalpha[TDFX_TMU1]) { fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].InvertRGB = FXTRUE; fxMesa->TexCombine[1].InvertAlpha = FXFALSE; } else { fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].InvertRGB = FXFALSE; fxMesa->TexCombine[1].InvertAlpha = FXFALSE; } if (isalpha[TDFX_TMU0]) { fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; } else { fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; } fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_LOCAL; fxMesa->ColorCombine.Local = localc; fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE; fxMesa->ColorCombine.Invert = FXFALSE; fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_LOCAL; fxMesa->AlphaCombine.Local = locala; fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_TEXTURE; fxMesa->AlphaCombine.Invert = FXFALSE; } else if (envMode0 == GL_REPLACE && envMode1 == GL_ADD) { /* Vulpine sky */ GLboolean isalpha[TDFX_NUM_TMU]; isalpha[tmu0] = (baseFormat0 == GL_ALPHA); isalpha[tmu1] = (baseFormat1 == GL_ALPHA); if (isalpha[TDFX_TMU1]) { fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].InvertRGB = FXTRUE; fxMesa->TexCombine[1].InvertAlpha = FXFALSE; } else { fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].InvertRGB = FXFALSE; fxMesa->TexCombine[1].InvertAlpha = FXFALSE; } if (isalpha[TDFX_TMU0]) { fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; } else { fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; } fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_ONE; fxMesa->ColorCombine.Local = localc; fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE; fxMesa->ColorCombine.Invert = FXFALSE; fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_ONE; fxMesa->AlphaCombine.Local = locala; fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_TEXTURE; fxMesa->AlphaCombine.Invert = FXFALSE; } else if (envMode1 == GL_REPLACE) { /* Homeworld2 */ fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_ZERO; fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].InvertRGB = FXFALSE; fxMesa->TexCombine[1].InvertAlpha = FXFALSE; fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; if ((baseFormat0 == GL_RGB) || (baseFormat0 == GL_LUMINANCE)) { fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL; fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE; fxMesa->AlphaCombine.Local = locala; fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE; fxMesa->AlphaCombine.Invert = FXFALSE; } else { fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_ONE; fxMesa->AlphaCombine.Local = locala; fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_TEXTURE; fxMesa->AlphaCombine.Invert = FXFALSE; } if (baseFormat0 == GL_ALPHA) { fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_LOCAL; fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_NONE; fxMesa->ColorCombine.Local = localc; fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_NONE; fxMesa->ColorCombine.Invert = FXFALSE; } else { fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER; fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_ONE; fxMesa->ColorCombine.Local = localc; fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE; fxMesa->ColorCombine.Invert = FXFALSE; } } else { _mesa_problem(ctx, "%s: Unexpected dual texture mode encountered", __FUNCTION__); return GL_FALSE; } fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_ENV; fxMesa->dirty |= TDFX_UPLOAD_COLOR_COMBINE; fxMesa->dirty |= TDFX_UPLOAD_ALPHA_COMBINE; return GL_TRUE; } /* * This function makes sure that the correct mipmap levels are loaded * in the right places in memory and then makes the Glide calls to * setup the texture source pointers. */ static void setupSingleTMU(tdfxContextPtr fxMesa, struct gl_texture_object *tObj) { struct tdfxSharedState *shared = (struct tdfxSharedState *) fxMesa->glCtx->Shared->DriverData; tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj); const struct gl_context *ctx = fxMesa->glCtx; /* Make sure we're not loaded incorrectly */ if (ti->isInTM && !shared->umaTexMemory) { /* if doing filtering between mipmap levels, alternate mipmap levels * must be in alternate TMUs. */ if (ti->LODblend) { if (ti->whichTMU != TDFX_TMU_SPLIT) tdfxTMMoveOutTM_NoLock(fxMesa, tObj); } else { if (ti->whichTMU == TDFX_TMU_SPLIT) tdfxTMMoveOutTM_NoLock(fxMesa, tObj); } } /* Make sure we're loaded correctly */ if (!ti->isInTM) { /* Have to download the texture */ if (shared->umaTexMemory) { tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU0); } else { /* Voodoo3 (split texture memory) */ if (ti->LODblend) { tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU_SPLIT); } else { #if 0 /* XXX putting textures into the second memory bank when the * first bank is full is not working at this time. */ if (fxMesa->haveTwoTMUs) { GLint memReq = fxMesa->Glide.grTexTextureMemRequired( GR_MIPMAPLEVELMASK_BOTH, &(ti->info)); if (shared->freeTexMem[TDFX_TMU0] > memReq) { tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU0); } else { tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU1); } } else #endif { tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU0); } } } } if (ti->LODblend && ti->whichTMU == TDFX_TMU_SPLIT) { /* mipmap levels split between texture banks */ GLint u; if (ti->info.format == GR_TEXFMT_P_8 && !ctx->Texture.SharedPalette) { fxMesa->TexPalette.Type = ti->paltype; fxMesa->TexPalette.Data = &(ti->palette); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE; } for (u = 0; u < 2; u++) { fxMesa->TexParams[u].sClamp = ti->sClamp; fxMesa->TexParams[u].tClamp = ti->tClamp; fxMesa->TexParams[u].minFilt = ti->minFilt; fxMesa->TexParams[u].magFilt = ti->magFilt; fxMesa->TexParams[u].mmMode = ti->mmMode; fxMesa->TexParams[u].LODblend = ti->LODblend; fxMesa->TexParams[u].LodBias = ctx->Texture.Unit[u].LodBias; } fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS; fxMesa->TexSource[0].StartAddress = ti->tm[TDFX_TMU0]->startAddr; fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_ODD; fxMesa->TexSource[0].Info = &(ti->info); fxMesa->TexSource[1].StartAddress = ti->tm[TDFX_TMU1]->startAddr; fxMesa->TexSource[1].EvenOdd = GR_MIPMAPLEVELMASK_EVEN; fxMesa->TexSource[1].Info = &(ti->info); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE; } else { FxU32 tmu; if (ti->whichTMU == TDFX_TMU_BOTH) tmu = TDFX_TMU0; else tmu = ti->whichTMU; if (shared->umaTexMemory) { assert(ti->whichTMU == TDFX_TMU0); assert(tmu == TDFX_TMU0); } if (ti->info.format == GR_TEXFMT_P_8 && !ctx->Texture.SharedPalette) { fxMesa->TexPalette.Type = ti->paltype; fxMesa->TexPalette.Data = &(ti->palette); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE; } /* KW: The alternative is to do the download to the other tmu. If * we get to this point, I think it means we are thrashing the * texture memory, so perhaps it's not a good idea. */ if (fxMesa->TexParams[tmu].sClamp != ti->sClamp || fxMesa->TexParams[tmu].tClamp != ti->tClamp || fxMesa->TexParams[tmu].minFilt != ti->minFilt || fxMesa->TexParams[tmu].magFilt != ti->magFilt || fxMesa->TexParams[tmu].mmMode != ti->mmMode || fxMesa->TexParams[tmu].LODblend != FXFALSE || fxMesa->TexParams[tmu].LodBias != ctx->Texture.Unit[tmu].LodBias) { fxMesa->TexParams[tmu].sClamp = ti->sClamp; fxMesa->TexParams[tmu].tClamp = ti->tClamp; fxMesa->TexParams[tmu].minFilt = ti->minFilt; fxMesa->TexParams[tmu].magFilt = ti->magFilt; fxMesa->TexParams[tmu].mmMode = ti->mmMode; fxMesa->TexParams[tmu].LODblend = FXFALSE; fxMesa->TexParams[tmu].LodBias = ctx->Texture.Unit[tmu].LodBias; fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS; } /* Glide texture source info */ fxMesa->TexSource[0].Info = NULL; fxMesa->TexSource[1].Info = NULL; if (ti->tm[tmu]) { fxMesa->TexSource[tmu].StartAddress = ti->tm[tmu]->startAddr; fxMesa->TexSource[tmu].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; fxMesa->TexSource[tmu].Info = &(ti->info); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE; } } fxMesa->sScale0 = ti->sScale; fxMesa->tScale0 = ti->tScale; } static void selectSingleTMUSrc(tdfxContextPtr fxMesa, GLint tmu, FxBool LODblend) { if (LODblend) { fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; if (fxMesa->haveTwoTMUs) { const struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; const struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; int tmu; if (shared->umaTexMemory) tmu = GR_TMU0; else tmu = GR_TMU1; fxMesa->TexCombine[tmu].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[tmu].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[tmu].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[tmu].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[tmu].InvertRGB = FXFALSE; fxMesa->TexCombine[tmu].InvertAlpha = FXFALSE; } fxMesa->tmuSrc = TDFX_TMU_SPLIT; } else { if (tmu != TDFX_TMU1) { fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; if (fxMesa->haveTwoTMUs) { fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_ZERO; fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].InvertRGB = FXFALSE; fxMesa->TexCombine[1].InvertAlpha = FXFALSE; } fxMesa->tmuSrc = TDFX_TMU0; } else { fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL; fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE; fxMesa->TexCombine[1].InvertRGB = FXFALSE; fxMesa->TexCombine[1].InvertAlpha = FXFALSE; /* GR_COMBINE_FUNCTION_SCALE_OTHER doesn't work ?!? */ fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND; fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE; fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND; fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE; fxMesa->TexCombine[0].InvertRGB = FXFALSE; fxMesa->TexCombine[0].InvertAlpha = FXFALSE; fxMesa->tmuSrc = TDFX_TMU1; } } fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_ENV; } #if 0 static void print_state(tdfxContextPtr fxMesa) { struct gl_context *ctx = fxMesa->glCtx; struct gl_texture_object *tObj0 = ctx->Texture.Unit[0]._Current; struct gl_texture_object *tObj1 = ctx->Texture.Unit[1]._Current; GLenum base0 = tObj0->Image[0][tObj0->BaseLevel] ? tObj0->Image[0][tObj0->BaseLevel]->Format : 99; GLenum base1 = tObj1->Image[0][tObj1->BaseLevel] ? tObj1->Image[0][tObj1->BaseLevel]->Format : 99; printf("Unit 0: Enabled: GL=%d Gr=%d\n", ctx->Texture.Unit[0]._ReallyEnabled, fxMesa->TexState.Enabled[0]); printf(" EnvMode: GL=0x%x Gr=0x%x\n", ctx->Texture.Unit[0].EnvMode, fxMesa->TexState.EnvMode[0]); printf(" BaseFmt: GL=0x%x Gr=0x%x\n", base0, fxMesa->TexState.TexFormat[0]); printf("Unit 1: Enabled: GL=%d Gr=%d\n", ctx->Texture.Unit[1]._ReallyEnabled, fxMesa->TexState.Enabled[1]); printf(" EnvMode: GL=0x%x Gr:0x%x\n", ctx->Texture.Unit[1].EnvMode, fxMesa->TexState.EnvMode[1]); printf(" BaseFmt: GL=0x%x Gr:0x%x\n", base1, fxMesa->TexState.TexFormat[1]); } #endif /* * When we're only using a single texture unit, we always use the 0th * Glide/hardware unit, regardless if it's GL_TEXTURE0_ARB or GL_TEXTURE1_ARB * that's enalbed. * Input: ctx - the context * unit - the OpenGL texture unit to use. */ static void setupTextureSingleTMU(struct gl_context * ctx, GLuint unit) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); tdfxTexInfo *ti; struct gl_texture_object *tObj; int tmu; GLenum envMode, baseFormat; tObj = ctx->Texture.Unit[unit]._Current; if (tObj->Image[0][tObj->BaseLevel]->Border > 0) { FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_BORDER, GL_TRUE); return; } setupSingleTMU(fxMesa, tObj); ti = TDFX_TEXTURE_DATA(tObj); if (ti->whichTMU == TDFX_TMU_BOTH) tmu = TDFX_TMU0; else tmu = ti->whichTMU; if (fxMesa->tmuSrc != tmu) { selectSingleTMUSrc(fxMesa, tmu, ti->LODblend); } if (ti->reloadImages) fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_IMAGES; /* Check if we really need to update the texenv state */ envMode = ctx->Texture.Unit[unit].EnvMode; baseFormat = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; if (TDFX_IS_NAPALM(fxMesa)) { /* see if we really need to update the unit */ if (1/*fxMesa->TexState.Enabled[unit] != ctx->Texture.Unit[unit]._ReallyEnabled || envMode != fxMesa->TexState.EnvMode[0] || envMode == GL_COMBINE_EXT || baseFormat != fxMesa->TexState.TexFormat[0]*/) { struct tdfx_texcombine_ext *otherEnv; if (!SetupTexEnvNapalm(ctx, GL_TRUE, &ctx->Texture.Unit[unit], baseFormat, &fxMesa->TexCombineExt[0])) { /* software fallback */ FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE); } /* disable other unit */ otherEnv = &fxMesa->TexCombineExt[1]; otherEnv->Color.SourceA = GR_CMBX_ZERO; otherEnv->Color.ModeA = GR_FUNC_MODE_ZERO; otherEnv->Color.SourceB = GR_CMBX_ZERO; otherEnv->Color.ModeB = GR_FUNC_MODE_ZERO; otherEnv->Color.SourceC = GR_CMBX_ZERO; otherEnv->Color.InvertC = FXFALSE; otherEnv->Color.SourceD = GR_CMBX_ZERO; otherEnv->Color.InvertD = FXFALSE; otherEnv->Color.Shift = 0; otherEnv->Color.Invert = FXFALSE; otherEnv->Alpha.SourceA = GR_CMBX_ITALPHA; otherEnv->Alpha.ModeA = GR_FUNC_MODE_ZERO; otherEnv->Alpha.SourceB = GR_CMBX_ITALPHA; otherEnv->Alpha.ModeB = GR_FUNC_MODE_ZERO; otherEnv->Alpha.SourceC = GR_CMBX_ZERO; otherEnv->Alpha.InvertC = FXFALSE; otherEnv->Alpha.SourceD = GR_CMBX_ZERO; otherEnv->Alpha.InvertD = FXFALSE; otherEnv->Alpha.Shift = 0; otherEnv->Alpha.Invert = FXFALSE; #if 0/*JJJ*/ fxMesa->TexState.Enabled[unit] = ctx->Texture.Unit[unit]._ReallyEnabled; fxMesa->TexState.EnvMode[0] = envMode; fxMesa->TexState.TexFormat[0] = baseFormat; fxMesa->TexState.EnvMode[1] = 0; fxMesa->TexState.TexFormat[1] = 0; #endif } } else { /* Voodoo3 */ /* see if we really need to update the unit */ if (1/*fxMesa->TexState.Enabled[unit] != ctx->Texture.Unit[unit]._ReallyEnabled || envMode != fxMesa->TexState.EnvMode[0] || envMode == GL_COMBINE_EXT || baseFormat != fxMesa->TexState.TexFormat[0]*/) { if (!SetupSingleTexEnvVoodoo3(ctx, unit, envMode, baseFormat)) { /* software fallback */ FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE); } #if 0/*JJJ*/ fxMesa->TexState.Enabled[unit] = ctx->Texture.Unit[unit]._ReallyEnabled; fxMesa->TexState.EnvMode[0] = envMode; fxMesa->TexState.TexFormat[0] = baseFormat; fxMesa->TexState.EnvMode[1] = 0; fxMesa->TexState.TexFormat[1] = 0; #endif } } } static void setupDoubleTMU(tdfxContextPtr fxMesa, struct gl_texture_object *tObj0, struct gl_texture_object *tObj1) { #define T0_NOT_IN_TMU 0x01 #define T1_NOT_IN_TMU 0x02 #define T0_IN_TMU0 0x04 #define T1_IN_TMU0 0x08 #define T0_IN_TMU1 0x10 #define T1_IN_TMU1 0x20 const struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; const struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; const struct gl_context *ctx = fxMesa->glCtx; tdfxTexInfo *ti0 = TDFX_TEXTURE_DATA(tObj0); tdfxTexInfo *ti1 = TDFX_TEXTURE_DATA(tObj1); GLuint tstate = 0; int tmu0 = 0, tmu1 = 1; if (shared->umaTexMemory) { if (!ti0->isInTM) { tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU0); assert(ti0->isInTM); } if (!ti1->isInTM) { tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU0); assert(ti1->isInTM); } } else { /* We shouldn't need to do this. There is something wrong with multitexturing when the TMUs are swapped. So, we're forcing them to always be loaded correctly. !!! */ if (ti0->whichTMU == TDFX_TMU1) tdfxTMMoveOutTM_NoLock(fxMesa, tObj0); if (ti1->whichTMU == TDFX_TMU0) tdfxTMMoveOutTM_NoLock(fxMesa, tObj1); if (ti0->isInTM) { switch (ti0->whichTMU) { case TDFX_TMU0: tstate |= T0_IN_TMU0; break; case TDFX_TMU1: tstate |= T0_IN_TMU1; break; case TDFX_TMU_BOTH: tstate |= T0_IN_TMU0 | T0_IN_TMU1; break; case TDFX_TMU_SPLIT: tstate |= T0_NOT_IN_TMU; break; } } else tstate |= T0_NOT_IN_TMU; if (ti1->isInTM) { switch (ti1->whichTMU) { case TDFX_TMU0: tstate |= T1_IN_TMU0; break; case TDFX_TMU1: tstate |= T1_IN_TMU1; break; case TDFX_TMU_BOTH: tstate |= T1_IN_TMU0 | T1_IN_TMU1; break; case TDFX_TMU_SPLIT: tstate |= T1_NOT_IN_TMU; break; } } else tstate |= T1_NOT_IN_TMU; /* Move texture maps into TMUs */ if (!(((tstate & T0_IN_TMU0) && (tstate & T1_IN_TMU1)) || ((tstate & T0_IN_TMU1) && (tstate & T1_IN_TMU0)))) { if (tObj0 == tObj1) { tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU_BOTH); } else { /* Find the minimal way to correct the situation */ if ((tstate & T0_IN_TMU0) || (tstate & T1_IN_TMU1)) { /* We have one in the standard order, setup the other */ if (tstate & T0_IN_TMU0) { /* T0 is in TMU0, put T1 in TMU1 */ tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU1); } else { tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU0); } /* tmu0 and tmu1 are setup */ } else if ((tstate & T0_IN_TMU1) || (tstate & T1_IN_TMU0)) { /* we have one in the reverse order, setup the other */ if (tstate & T1_IN_TMU0) { /* T1 is in TMU0, put T0 in TMU1 */ tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU1); } else { tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU0); } tmu0 = 1; tmu1 = 0; } else { /* Nothing is loaded */ tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU0); tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU1); /* tmu0 and tmu1 are setup */ } } } } ti0->lastTimeUsed = fxMesa->texBindNumber; ti1->lastTimeUsed = fxMesa->texBindNumber; if (!ctx->Texture.SharedPalette) { if (ti0->info.format == GR_TEXFMT_P_8) { fxMesa->TexPalette.Type = ti0->paltype; fxMesa->TexPalette.Data = &(ti0->palette); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE; } else if (ti1->info.format == GR_TEXFMT_P_8) { fxMesa->TexPalette.Type = ti1->paltype; fxMesa->TexPalette.Data = &(ti1->palette); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE; } else { fxMesa->TexPalette.Data = NULL; } } /* * Setup Unit 0 */ assert(ti0->isInTM); assert(ti0->tm[tmu0]); fxMesa->TexSource[tmu0].StartAddress = ti0->tm[tmu0]->startAddr; fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; fxMesa->TexSource[tmu0].Info = &(ti0->info); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE; if (fxMesa->TexParams[tmu0].sClamp != ti0->sClamp || fxMesa->TexParams[tmu0].tClamp != ti0->tClamp || fxMesa->TexParams[tmu0].minFilt != ti0->minFilt || fxMesa->TexParams[tmu0].magFilt != ti0->magFilt || fxMesa->TexParams[tmu0].mmMode != ti0->mmMode || fxMesa->TexParams[tmu0].LODblend != FXFALSE || fxMesa->TexParams[tmu0].LodBias != ctx->Texture.Unit[tmu0].LodBias) { fxMesa->TexParams[tmu0].sClamp = ti0->sClamp; fxMesa->TexParams[tmu0].tClamp = ti0->tClamp; fxMesa->TexParams[tmu0].minFilt = ti0->minFilt; fxMesa->TexParams[tmu0].magFilt = ti0->magFilt; fxMesa->TexParams[tmu0].mmMode = ti0->mmMode; fxMesa->TexParams[tmu0].LODblend = FXFALSE; fxMesa->TexParams[tmu0].LodBias = ctx->Texture.Unit[tmu0].LodBias; fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS; } /* * Setup Unit 1 */ if (shared->umaTexMemory) { ASSERT(ti1->isInTM); ASSERT(ti1->tm[0]); fxMesa->TexSource[tmu1].StartAddress = ti1->tm[0]->startAddr; fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; fxMesa->TexSource[tmu1].Info = &(ti1->info); } else { ASSERT(ti1->isInTM); ASSERT(ti1->tm[tmu1]); fxMesa->TexSource[tmu1].StartAddress = ti1->tm[tmu1]->startAddr; fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; fxMesa->TexSource[tmu1].Info = &(ti1->info); } if (fxMesa->TexParams[tmu1].sClamp != ti1->sClamp || fxMesa->TexParams[tmu1].tClamp != ti1->tClamp || fxMesa->TexParams[tmu1].minFilt != ti1->minFilt || fxMesa->TexParams[tmu1].magFilt != ti1->magFilt || fxMesa->TexParams[tmu1].mmMode != ti1->mmMode || fxMesa->TexParams[tmu1].LODblend != FXFALSE || fxMesa->TexParams[tmu1].LodBias != ctx->Texture.Unit[tmu1].LodBias) { fxMesa->TexParams[tmu1].sClamp = ti1->sClamp; fxMesa->TexParams[tmu1].tClamp = ti1->tClamp; fxMesa->TexParams[tmu1].minFilt = ti1->minFilt; fxMesa->TexParams[tmu1].magFilt = ti1->magFilt; fxMesa->TexParams[tmu1].mmMode = ti1->mmMode; fxMesa->TexParams[tmu1].LODblend = FXFALSE; fxMesa->TexParams[tmu1].LodBias = ctx->Texture.Unit[tmu1].LodBias; fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS; } fxMesa->sScale0 = ti0->sScale; fxMesa->tScale0 = ti0->tScale; fxMesa->sScale1 = ti1->sScale; fxMesa->tScale1 = ti1->tScale; #undef T0_NOT_IN_TMU #undef T1_NOT_IN_TMU #undef T0_IN_TMU0 #undef T1_IN_TMU0 #undef T0_IN_TMU1 #undef T1_IN_TMU1 } static void setupTextureDoubleTMU(struct gl_context * ctx) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); struct gl_texture_object *tObj0 = ctx->Texture.Unit[1]._Current; struct gl_texture_object *tObj1 = ctx->Texture.Unit[0]._Current; tdfxTexInfo *ti0 = TDFX_TEXTURE_DATA(tObj0); tdfxTexInfo *ti1 = TDFX_TEXTURE_DATA(tObj1); struct gl_texture_image *baseImage0 = tObj0->Image[0][tObj0->BaseLevel]; struct gl_texture_image *baseImage1 = tObj1->Image[0][tObj1->BaseLevel]; #if 0/*JJJ*/ const GLenum envMode0 = ctx->Texture.Unit[0].EnvMode; const GLenum envMode1 = ctx->Texture.Unit[1].EnvMode; #endif if (baseImage0->Border > 0 || baseImage1->Border > 0) { FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_BORDER, GL_TRUE); return; } setupDoubleTMU(fxMesa, tObj0, tObj1); if (ti0->reloadImages || ti1->reloadImages) fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_IMAGES; fxMesa->tmuSrc = TDFX_TMU_BOTH; if (TDFX_IS_NAPALM(fxMesa)) { /* Remember, Glide has its texture units numbered in backward * order compared to OpenGL. */ GLboolean hw1 = GL_TRUE, hw2 = GL_TRUE; /* check if we really need to update glide unit 1 */ if (1/*fxMesa->TexState.Enabled[0] != ctx->Texture.Unit[0]._ReallyEnabled || envMode0 != fxMesa->TexState.EnvMode[1] || envMode0 == GL_COMBINE_EXT || baseImage0->Format != fxMesa->TexState.TexFormat[1] || (fxMesa->Fallback & TDFX_FALLBACK_TEXTURE_ENV)*/) { hw1 = SetupTexEnvNapalm(ctx, GL_TRUE, &ctx->Texture.Unit[0], baseImage0->_BaseFormat, &fxMesa->TexCombineExt[1]); #if 0/*JJJ*/ fxMesa->TexState.EnvMode[1] = envMode0; fxMesa->TexState.TexFormat[1] = baseImage0->_BaseFormat; fxMesa->TexState.Enabled[0] = ctx->Texture.Unit[0]._ReallyEnabled; #endif } /* check if we really need to update glide unit 0 */ if (1/*fxMesa->TexState.Enabled[1] != ctx->Texture.Unit[1]._ReallyEnabled || envMode1 != fxMesa->TexState.EnvMode[0] || envMode1 == GL_COMBINE_EXT || baseImage1->_BaseFormat != fxMesa->TexState.TexFormat[0] || (fxMesa->Fallback & TDFX_FALLBACK_TEXTURE_ENV)*/) { hw2 = SetupTexEnvNapalm(ctx, GL_FALSE, &ctx->Texture.Unit[1], baseImage1->_BaseFormat, &fxMesa->TexCombineExt[0]); #if 0/*JJJ*/ fxMesa->TexState.EnvMode[0] = envMode1; fxMesa->TexState.TexFormat[0] = baseImage1->_BaseFormat; fxMesa->TexState.Enabled[1] = ctx->Texture.Unit[1]._ReallyEnabled; #endif } if (!hw1 || !hw2) { FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE); } } else { int unit0, unit1; if ((ti0->whichTMU == TDFX_TMU1) || (ti1->whichTMU == TDFX_TMU0)) unit0 = 1; else unit0 = 0; unit1 = 1 - unit0; if (1/*fxMesa->TexState.Enabled[0] != ctx->Texture.Unit[0]._ReallyEnabled || fxMesa->TexState.Enabled[1] != ctx->Texture.Unit[1]._ReallyEnabled || envMode0 != fxMesa->TexState.EnvMode[unit0] || envMode0 == GL_COMBINE_EXT || envMode1 != fxMesa->TexState.EnvMode[unit1] || envMode1 == GL_COMBINE_EXT || baseImage0->_BaseFormat != fxMesa->TexState.TexFormat[unit0] || baseImage1->_BaseFormat != fxMesa->TexState.TexFormat[unit1] || (fxMesa->Fallback & TDFX_FALLBACK_TEXTURE_ENV)*/) { if (!SetupDoubleTexEnvVoodoo3(ctx, unit0, ctx->Texture.Unit[0].EnvMode, baseImage0->_BaseFormat, ctx->Texture.Unit[1].EnvMode, baseImage1->_BaseFormat)) { FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE); } #if 0/*JJJ*/ fxMesa->TexState.EnvMode[unit0] = envMode0; fxMesa->TexState.TexFormat[unit0] = baseImage0->_BaseFormat; fxMesa->TexState.EnvMode[unit1] = envMode1; fxMesa->TexState.TexFormat[unit1] = baseImage1->_BaseFormat; fxMesa->TexState.Enabled[0] = ctx->Texture.Unit[0]._ReallyEnabled; fxMesa->TexState.Enabled[1] = ctx->Texture.Unit[1]._ReallyEnabled; #endif } } } void tdfxUpdateTextureState( struct gl_context *ctx ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_BORDER, GL_FALSE); FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_FALSE); if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT) && ctx->Texture.Unit[1]._ReallyEnabled == 0) { LOCK_HARDWARE( fxMesa ); /* XXX remove locking eventually */ setupTextureSingleTMU(ctx, 0); UNLOCK_HARDWARE( fxMesa ); } else if (ctx->Texture.Unit[0]._ReallyEnabled == 0 && ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) { LOCK_HARDWARE( fxMesa ); setupTextureSingleTMU(ctx, 1); UNLOCK_HARDWARE( fxMesa ); } else if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT) && ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) { LOCK_HARDWARE( fxMesa ); setupTextureDoubleTMU(ctx); UNLOCK_HARDWARE( fxMesa ); } else { /* disable hardware texturing */ if (TDFX_IS_NAPALM(fxMesa)) { fxMesa->ColorCombineExt.SourceA = GR_CMBX_ITRGB; fxMesa->ColorCombineExt.ModeA = GR_FUNC_MODE_X; fxMesa->ColorCombineExt.SourceB = GR_CMBX_ZERO; fxMesa->ColorCombineExt.ModeB = GR_FUNC_MODE_ZERO; fxMesa->ColorCombineExt.SourceC = GR_CMBX_ZERO; fxMesa->ColorCombineExt.InvertC = FXTRUE; fxMesa->ColorCombineExt.SourceD = GR_CMBX_ZERO; fxMesa->ColorCombineExt.InvertD = FXFALSE; fxMesa->ColorCombineExt.Shift = 0; fxMesa->ColorCombineExt.Invert = FXFALSE; fxMesa->AlphaCombineExt.SourceA = GR_CMBX_ITALPHA; fxMesa->AlphaCombineExt.ModeA = GR_FUNC_MODE_X; fxMesa->AlphaCombineExt.SourceB = GR_CMBX_ZERO; fxMesa->AlphaCombineExt.ModeB = GR_FUNC_MODE_ZERO; fxMesa->AlphaCombineExt.SourceC = GR_CMBX_ZERO; fxMesa->AlphaCombineExt.InvertC = FXTRUE; fxMesa->AlphaCombineExt.SourceD = GR_CMBX_ZERO; fxMesa->AlphaCombineExt.InvertD = FXFALSE; fxMesa->AlphaCombineExt.Shift = 0; fxMesa->AlphaCombineExt.Invert = FXFALSE; } else { /* Voodoo 3*/ fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_LOCAL; fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_NONE; fxMesa->ColorCombine.Local = GR_COMBINE_LOCAL_ITERATED; fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_NONE; fxMesa->ColorCombine.Invert = FXFALSE; fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL; fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE; fxMesa->AlphaCombine.Local = GR_COMBINE_LOCAL_ITERATED; fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE; fxMesa->AlphaCombine.Invert = FXFALSE; } fxMesa->TexState.Enabled[0] = 0; fxMesa->TexState.Enabled[1] = 0; fxMesa->TexState.EnvMode[0] = 0; fxMesa->TexState.EnvMode[1] = 0; fxMesa->dirty |= TDFX_UPLOAD_COLOR_COMBINE; fxMesa->dirty |= TDFX_UPLOAD_ALPHA_COMBINE; if (ctx->Texture.Unit[0]._ReallyEnabled != 0 || ctx->Texture.Unit[1]._ReallyEnabled != 0) { /* software texture (cube map, rect tex, etc */ FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE); } } } /* * This is a special case of texture state update. * It's used when we've simply bound a new texture to a texture * unit and the new texture has the exact same attributes as the * previously bound texture. * This is very common in Quake3. */ void tdfxUpdateTextureBinding( struct gl_context *ctx ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); struct gl_texture_object *tObj0 = ctx->Texture.Unit[0]._Current; struct gl_texture_object *tObj1 = ctx->Texture.Unit[1]._Current; tdfxTexInfo *ti0 = TDFX_TEXTURE_DATA(tObj0); tdfxTexInfo *ti1 = TDFX_TEXTURE_DATA(tObj1); const struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared; const struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData; if (ti0) { fxMesa->sScale0 = ti0->sScale; fxMesa->tScale0 = ti0->tScale; if (ti0->info.format == GR_TEXFMT_P_8) { fxMesa->TexPalette.Type = ti0->paltype; fxMesa->TexPalette.Data = &(ti0->palette); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE; } else if (ti1 && ti1->info.format == GR_TEXFMT_P_8) { fxMesa->TexPalette.Type = ti1->paltype; fxMesa->TexPalette.Data = &(ti1->palette); fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE; } } if (ti1) { fxMesa->sScale1 = ti1->sScale; fxMesa->tScale1 = ti1->tScale; } if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT) && ctx->Texture.Unit[0]._ReallyEnabled == 0) { /* Only unit 0 2D enabled */ if (shared->umaTexMemory) { assert(ti0); fxMesa->TexSource[0].StartAddress = ti0->tm[0]->startAddr; fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; fxMesa->TexSource[0].Info = &(ti0->info); } else { assert(ti0); if (ti0->LODblend && ti0->whichTMU == TDFX_TMU_SPLIT) { fxMesa->TexSource[0].StartAddress = ti0->tm[TDFX_TMU0]->startAddr; fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_ODD; fxMesa->TexSource[0].Info = &(ti0->info); fxMesa->TexSource[1].StartAddress = ti0->tm[TDFX_TMU1]->startAddr; fxMesa->TexSource[1].EvenOdd = GR_MIPMAPLEVELMASK_EVEN; fxMesa->TexSource[1].Info = &(ti0->info); } else { FxU32 tmu; if (ti0->whichTMU == TDFX_TMU_BOTH) tmu = TDFX_TMU0; else tmu = ti0->whichTMU; fxMesa->TexSource[0].Info = NULL; fxMesa->TexSource[1].Info = NULL; if (ti0->tm[tmu]) { fxMesa->TexSource[tmu].StartAddress = ti0->tm[tmu]->startAddr; fxMesa->TexSource[tmu].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; fxMesa->TexSource[tmu].Info = &(ti0->info); } } } } else if (ctx->Texture.Unit[0]._ReallyEnabled == 0 && ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) { /* Only unit 1 2D enabled */ if (shared->umaTexMemory) { fxMesa->TexSource[0].StartAddress = ti1->tm[0]->startAddr; fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; fxMesa->TexSource[0].Info = &(ti1->info); } } else if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT) && ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) { /* Both 2D enabled */ if (shared->umaTexMemory) { const FxU32 tmu0 = 0, tmu1 = 1; assert(ti0); fxMesa->TexSource[tmu0].StartAddress = ti0->tm[0]->startAddr; fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; fxMesa->TexSource[tmu0].Info = &(ti0->info); assert(ti1); fxMesa->TexSource[tmu1].StartAddress = ti1->tm[0]->startAddr; fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; fxMesa->TexSource[tmu1].Info = &(ti1->info); } else { const FxU32 tmu0 = 0, tmu1 = 1; assert(ti0); fxMesa->TexSource[tmu0].StartAddress = ti0->tm[tmu0]->startAddr; fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; fxMesa->TexSource[tmu0].Info = &(ti0->info); assert(ti1); fxMesa->TexSource[tmu1].StartAddress = ti1->tm[tmu1]->startAddr; fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH; fxMesa->TexSource[tmu1].Info = &(ti1->info); } } fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE; }