blob: fda9ce56849a330332a9f0b29258dac30ebb74c6 [file] [log] [blame]
/* -*- 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.
*/
/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_texstate.c,v 1.2 2002/02/22 21:45:04 dawes Exp $ */
/*
* New fixes:
* Daniel Borca <dborca@users.sourceforge.net>, 19 Jul 2004
*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Brian Paul <brianp@valinux.com>
*
*/
#include "tdfx_state.h"
#include "tdfx_tex.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(GLcontext *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(GLcontext *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(GLcontext *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 GLcontext *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)
{
GLcontext *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(GLcontext * 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 GLcontext *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(GLcontext * 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( GLcontext *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( GLcontext *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) {
fxMesa->TexSource[0].StartAddress = ti0->tm[0]->startAddr;
fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
fxMesa->TexSource[0].Info = &(ti0->info);
}
else {
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;
fxMesa->TexSource[tmu0].StartAddress = ti0->tm[0]->startAddr;
fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
fxMesa->TexSource[tmu0].Info = &(ti0->info);
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;
fxMesa->TexSource[tmu0].StartAddress = ti0->tm[tmu0]->startAddr;
fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
fxMesa->TexSource[tmu0].Info = &(ti0->info);
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;
}