summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/glide/fxsetup.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/glide/fxsetup.c')
-rw-r--r--src/mesa/drivers/glide/fxsetup.c2219
1 files changed, 2219 insertions, 0 deletions
diff --git a/src/mesa/drivers/glide/fxsetup.c b/src/mesa/drivers/glide/fxsetup.c
new file mode 100644
index 00000000000..240e5e0b597
--- /dev/null
+++ b/src/mesa/drivers/glide/fxsetup.c
@@ -0,0 +1,2219 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * Copyright (C) 1999-2001 Brian Paul 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 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
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* Authors:
+ * David Bucciarelli
+ * Brian Paul
+ * Daryll Strauss
+ * Keith Whitwell
+ * Daniel Borca
+ * Hiroshi Morii
+ */
+
+/* fxsetup.c - 3Dfx VooDoo rendering mode setup functions */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+#include "enums.h"
+#include "tnl.h"
+#include "tnl/t_context.h"
+#include "swrast.h"
+#include "texstore.h"
+
+
+static void
+fxTexValidate(GLcontext * ctx, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+ GLint minl, maxl;
+
+ if (ti->validated) {
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxTexValidate(NOP)\n");
+ }
+ return;
+ }
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxTexValidate(%p (%d))\n", (void *)tObj, tObj->Name);
+ }
+
+ ti->tObj = tObj;
+ minl = ti->minLevel = tObj->BaseLevel;
+ maxl = ti->maxLevel = MIN2(tObj->MaxLevel, tObj->Image[0][0]->MaxLog2);
+
+#if FX_RESCALE_BIG_TEXURES_HACK
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ /* [dBorca]
+ * Fake textures larger than HW supports:
+ * 1) we have mipmaps. Then we just push up to the first supported
+ * LOD. A possible drawback is that Mesa will ignore the skipped
+ * LODs on further texture handling.
+ * Will this interfere with GL_TEXTURE_[MIN|BASE]_LEVEL? How?
+ * 2) we don't have mipmaps. We need to rescale the big LOD in place.
+ * The above approach is somehow dumb! we might have rescaled
+ * once in TexImage2D to accomodate aspect ratio, and now we
+ * are rescaling again. The thing is, in TexImage2D we don't
+ * know whether we'll hit 1) or 2) by the time of validation.
+ */
+ if ((tObj->MinFilter == GL_NEAREST) || (tObj->MinFilter == GL_LINEAR)) {
+ /* no mipmaps! */
+ struct gl_texture_image *texImage = tObj->Image[0][minl];
+ tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+ GLint _w, _h, maxSize = 1 << fxMesa->textureMaxLod;
+ if ((mml->width > maxSize) || (mml->height > maxSize)) {
+ /* need to rescale */
+ GLint texelBytes = texImage->TexFormat->TexelBytes;
+ GLvoid *texImage_Data = texImage->Data;
+ _w = MIN2(texImage->Width, maxSize);
+ _h = MIN2(texImage->Height, maxSize);
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ fprintf(stderr, "fxTexValidate: rescaling %d x %d -> %d x %d\n",
+ texImage->Width, texImage->Height, _w, _h);
+ }
+ /* we should leave these as is and... (!) */
+ texImage->Width = _w;
+ texImage->Height = _h;
+ fxTexGetInfo(_w, _h, NULL, NULL, NULL, NULL,
+ &(mml->wScale), &(mml->hScale));
+ _w *= mml->wScale;
+ _h *= mml->hScale;
+ texImage->Data = _mesa_malloc(_w * _h * texelBytes);
+ _mesa_rescale_teximage2d(texelBytes,
+ mml->width,
+ _w * texelBytes, /* dst stride */
+ mml->width, mml->height, /* src */
+ _w, _h, /* dst */
+ texImage_Data /*src*/, texImage->Data /*dst*/ );
+ _mesa_free(texImage_Data);
+ mml->width = _w;
+ mml->height = _h;
+ /* (!) ... and set mml->wScale = _w / texImage->Width */
+ }
+ } else {
+ /* mipmapping */
+ if (maxl - minl > fxMesa->textureMaxLod) {
+ /* skip a certain number of LODs */
+ minl += maxl - fxMesa->textureMaxLod;
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ fprintf(stderr, "fxTexValidate: skipping %d LODs\n", minl - ti->minLevel);
+ }
+ ti->minLevel = tObj->BaseLevel = minl;
+ }
+ }
+}
+#endif
+
+ fxTexGetInfo(tObj->Image[0][minl]->Width, tObj->Image[0][minl]->Height,
+ &(FX_largeLodLog2(ti->info)), &(FX_aspectRatioLog2(ti->info)),
+ &(ti->sScale), &(ti->tScale),
+ NULL, NULL);
+
+ if ((tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR))
+ fxTexGetInfo(tObj->Image[0][maxl]->Width, tObj->Image[0][maxl]->Height,
+ &(FX_smallLodLog2(ti->info)), NULL,
+ NULL, NULL, NULL, NULL);
+ else
+ FX_smallLodLog2(ti->info) = FX_largeLodLog2(ti->info);
+
+ /* [dBorca] this is necessary because of fxDDCompressedTexImage2D */
+ if (ti->padded) {
+ struct gl_texture_image *texImage = tObj->Image[0][minl];
+ tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+ if (mml->wScale != 1 || mml->hScale != 1) {
+ ti->sScale /= mml->wScale;
+ ti->tScale /= mml->hScale;
+ }
+ }
+
+ ti->baseLevelInternalFormat = tObj->Image[0][minl]->Format;
+
+ ti->validated = GL_TRUE;
+
+ ti->info.data = NULL;
+}
+
+static void
+fxPrintUnitsMode(const char *msg, GLuint mode)
+{
+ fprintf(stderr,
+ "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ msg,
+ mode,
+ (mode & FX_UM_E0_REPLACE) ? "E0_REPLACE, " : "",
+ (mode & FX_UM_E0_MODULATE) ? "E0_MODULATE, " : "",
+ (mode & FX_UM_E0_DECAL) ? "E0_DECAL, " : "",
+ (mode & FX_UM_E0_BLEND) ? "E0_BLEND, " : "",
+ (mode & FX_UM_E1_REPLACE) ? "E1_REPLACE, " : "",
+ (mode & FX_UM_E1_MODULATE) ? "E1_MODULATE, " : "",
+ (mode & FX_UM_E1_DECAL) ? "E1_DECAL, " : "",
+ (mode & FX_UM_E1_BLEND) ? "E1_BLEND, " : "",
+ (mode & FX_UM_E0_ALPHA) ? "E0_ALPHA, " : "",
+ (mode & FX_UM_E0_LUMINANCE) ? "E0_LUMINANCE, " : "",
+ (mode & FX_UM_E0_LUMINANCE_ALPHA) ? "E0_LUMINANCE_ALPHA, " : "",
+ (mode & FX_UM_E0_INTENSITY) ? "E0_INTENSITY, " : "",
+ (mode & FX_UM_E0_RGB) ? "E0_RGB, " : "",
+ (mode & FX_UM_E0_RGBA) ? "E0_RGBA, " : "",
+ (mode & FX_UM_E1_ALPHA) ? "E1_ALPHA, " : "",
+ (mode & FX_UM_E1_LUMINANCE) ? "E1_LUMINANCE, " : "",
+ (mode & FX_UM_E1_LUMINANCE_ALPHA) ? "E1_LUMINANCE_ALPHA, " : "",
+ (mode & FX_UM_E1_INTENSITY) ? "E1_INTENSITY, " : "",
+ (mode & FX_UM_E1_RGB) ? "E1_RGB, " : "",
+ (mode & FX_UM_E1_RGBA) ? "E1_RGBA, " : "",
+ (mode & FX_UM_COLOR_ITERATED) ? "COLOR_ITERATED, " : "",
+ (mode & FX_UM_COLOR_CONSTANT) ? "COLOR_CONSTANT, " : "",
+ (mode & FX_UM_ALPHA_ITERATED) ? "ALPHA_ITERATED, " : "",
+ (mode & FX_UM_ALPHA_CONSTANT) ? "ALPHA_CONSTANT, " : "");
+}
+
+static GLuint
+fxGetTexSetConfiguration(GLcontext * ctx,
+ struct gl_texture_object *tObj0,
+ struct gl_texture_object *tObj1)
+{
+ GLuint unitsmode = 0;
+ GLuint envmode = 0;
+ GLuint ifmt = 0;
+
+ if ((ctx->Light.ShadeModel == GL_SMOOTH) || 1 ||
+ (ctx->Point.SmoothFlag) ||
+ (ctx->Line.SmoothFlag) ||
+ (ctx->Polygon.SmoothFlag)) unitsmode |= FX_UM_ALPHA_ITERATED;
+ else
+ unitsmode |= FX_UM_ALPHA_CONSTANT;
+
+ if (ctx->Light.ShadeModel == GL_SMOOTH || 1)
+ unitsmode |= FX_UM_COLOR_ITERATED;
+ else
+ unitsmode |= FX_UM_COLOR_CONSTANT;
+
+
+
+ /*
+ OpenGL Feeds Texture 0 into Texture 1
+ Glide Feeds Texture 1 into Texture 0
+ */
+ if (tObj0) {
+ tfxTexInfo *ti0 = fxTMGetTexInfo(tObj0);
+
+ switch (ti0->baseLevelInternalFormat) {
+ case GL_ALPHA:
+ ifmt |= FX_UM_E0_ALPHA;
+ break;
+ case GL_LUMINANCE:
+ ifmt |= FX_UM_E0_LUMINANCE;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ ifmt |= FX_UM_E0_LUMINANCE_ALPHA;
+ break;
+ case GL_INTENSITY:
+ ifmt |= FX_UM_E0_INTENSITY;
+ break;
+ case GL_RGB:
+ ifmt |= FX_UM_E0_RGB;
+ break;
+ case GL_RGBA:
+ ifmt |= FX_UM_E0_RGBA;
+ break;
+ }
+
+ switch (ctx->Texture.Unit[0].EnvMode) {
+ case GL_DECAL:
+ envmode |= FX_UM_E0_DECAL;
+ break;
+ case GL_MODULATE:
+ envmode |= FX_UM_E0_MODULATE;
+ break;
+ case GL_REPLACE:
+ envmode |= FX_UM_E0_REPLACE;
+ break;
+ case GL_BLEND:
+ envmode |= FX_UM_E0_BLEND;
+ break;
+ case GL_ADD:
+ envmode |= FX_UM_E0_ADD;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+
+ if (tObj1) {
+ tfxTexInfo *ti1 = fxTMGetTexInfo(tObj1);
+
+ switch (ti1->baseLevelInternalFormat) {
+ case GL_ALPHA:
+ ifmt |= FX_UM_E1_ALPHA;
+ break;
+ case GL_LUMINANCE:
+ ifmt |= FX_UM_E1_LUMINANCE;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ ifmt |= FX_UM_E1_LUMINANCE_ALPHA;
+ break;
+ case GL_INTENSITY:
+ ifmt |= FX_UM_E1_INTENSITY;
+ break;
+ case GL_RGB:
+ ifmt |= FX_UM_E1_RGB;
+ break;
+ case GL_RGBA:
+ ifmt |= FX_UM_E1_RGBA;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+
+ switch (ctx->Texture.Unit[1].EnvMode) {
+ case GL_DECAL:
+ envmode |= FX_UM_E1_DECAL;
+ break;
+ case GL_MODULATE:
+ envmode |= FX_UM_E1_MODULATE;
+ break;
+ case GL_REPLACE:
+ envmode |= FX_UM_E1_REPLACE;
+ break;
+ case GL_BLEND:
+ envmode |= FX_UM_E1_BLEND;
+ break;
+ case GL_ADD:
+ envmode |= FX_UM_E1_ADD;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+
+ unitsmode |= (ifmt | envmode);
+
+ if (TDFX_DEBUG & (VERBOSE_DRIVER | VERBOSE_TEXTURE))
+ fxPrintUnitsMode("fxGetTexSetConfiguration", unitsmode);
+
+ return unitsmode;
+}
+
+/************************************************************************/
+/************************* Rendering Mode SetUp *************************/
+/************************************************************************/
+
+/************************* Single Texture Set ***************************/
+
+static void
+fxSetupSingleTMU_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+ int tmu;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupSingleTMU_NoLock(%p (%d))\n", (void *)tObj, tObj->Name);
+ }
+
+ ti->lastTimeUsed = fxMesa->texBindNumber;
+
+ /* Make sure we're not loaded incorrectly */
+ if (ti->isInTM) {
+ if (ti->LODblend) {
+ if (ti->whichTMU != FX_TMU_SPLIT)
+ fxTMMoveOutTM(fxMesa, tObj);
+ }
+ else {
+ if (ti->whichTMU == FX_TMU_SPLIT)
+ fxTMMoveOutTM(fxMesa, tObj);
+ }
+ }
+
+ /* Make sure we're loaded correctly */
+ if (!ti->isInTM) {
+ if (ti->LODblend)
+ fxTMMoveInTM_NoLock(fxMesa, tObj, FX_TMU_SPLIT);
+ else {
+ if (fxMesa->haveTwoTMUs) {
+ if (fxTMCheckStartAddr(fxMesa, FX_TMU0, ti)) {
+ fxTMMoveInTM_NoLock(fxMesa, tObj, FX_TMU0);
+ }
+ else {
+ fxTMMoveInTM_NoLock(fxMesa, tObj, FX_TMU1);
+ }
+ }
+ else
+ fxTMMoveInTM_NoLock(fxMesa, tObj, FX_TMU0);
+ }
+ }
+
+ if (ti->LODblend && ti->whichTMU == FX_TMU_SPLIT) {
+ /* broadcast */
+ if ((ti->info.format == GR_TEXFMT_P_8)
+ && (!fxMesa->haveGlobalPaletteTexture)) {
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupSingleTMU_NoLock: uploading texture palette\n");
+ }
+ grTexDownloadTable(ti->paltype, &(ti->palette));
+ }
+
+ grTexClampMode(GR_TMU0, ti->sClamp, ti->tClamp);
+ grTexClampMode(GR_TMU1, ti->sClamp, ti->tClamp);
+ grTexFilterMode(GR_TMU0, ti->minFilt, ti->maxFilt);
+ grTexFilterMode(GR_TMU1, ti->minFilt, ti->maxFilt);
+ grTexMipMapMode(GR_TMU0, ti->mmMode, ti->LODblend);
+ grTexMipMapMode(GR_TMU1, ti->mmMode, ti->LODblend);
+
+ grTexSource(GR_TMU0, ti->tm[FX_TMU0]->startAddr,
+ GR_MIPMAPLEVELMASK_ODD, &(ti->info));
+ grTexSource(GR_TMU1, ti->tm[FX_TMU1]->startAddr,
+ GR_MIPMAPLEVELMASK_EVEN, &(ti->info));
+ }
+ else {
+ if (ti->whichTMU == FX_TMU_BOTH)
+ tmu = FX_TMU0;
+ else
+ tmu = ti->whichTMU;
+
+ /* pointcast */
+ if ((ti->info.format == GR_TEXFMT_P_8)
+ && (!fxMesa->haveGlobalPaletteTexture)) {
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupSingleTMU_NoLock: uploading texture palette\n");
+ }
+ fxMesa->Glide.grTexDownloadTableExt(tmu, ti->paltype, &(ti->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 (ti->LODblend && (TDFX_DEBUG & VERBOSE_DRIVER)) {
+ fprintf(stderr, "fxSetupSingleTMU_NoLock: not blending texture - only one tmu\n");
+ }
+
+ grTexClampMode(tmu, ti->sClamp, ti->tClamp);
+ grTexFilterMode(tmu, ti->minFilt, ti->maxFilt);
+ grTexMipMapMode(tmu, ti->mmMode, FXFALSE);
+
+ grTexSource(tmu, ti->tm[tmu]->startAddr, GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
+ }
+}
+
+static void
+fxSelectSingleTMUSrc_NoLock(fxMesaContext fxMesa, GLint tmu, FxBool LODblend)
+{
+ struct tdfx_texcombine tex0, tex1;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSelectSingleTMUSrc_NoLock(%d, %d)\n", tmu, LODblend);
+ }
+
+ tex0.InvertRGB = FXFALSE;
+ tex0.InvertAlpha = FXFALSE;
+ tex1.InvertRGB = FXFALSE;
+ tex1.InvertAlpha = FXFALSE;
+
+ if (LODblend) {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION;
+
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ fxMesa->tmuSrc = FX_TMU_SPLIT;
+ }
+ else {
+ if (tmu != FX_TMU1) {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ fxMesa->tmuSrc = FX_TMU0;
+ }
+ else {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ /* correct values to set TMU0 in passthrough mode */
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE;
+
+ fxMesa->tmuSrc = FX_TMU1;
+ }
+ }
+
+ grTexCombine(GR_TMU0,
+ tex0.FunctionRGB,
+ tex0.FactorRGB,
+ tex0.FunctionAlpha,
+ tex0.FactorAlpha,
+ tex0.InvertRGB,
+ tex0.InvertAlpha);
+ if (fxMesa->haveTwoTMUs) {
+ grTexCombine(GR_TMU1,
+ tex1.FunctionRGB,
+ tex1.FactorRGB,
+ tex1.FunctionAlpha,
+ tex1.FactorAlpha,
+ tex1.InvertRGB,
+ tex1.InvertAlpha);
+ }
+}
+
+static void
+fxSetupTextureSingleTMU_NoLock(GLcontext * ctx, GLuint textureset)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ struct tdfx_combine alphaComb, colorComb;
+ GrCombineLocal_t localc, locala;
+ GLuint unitsmode;
+ GLint ifmt;
+ tfxTexInfo *ti;
+ struct gl_texture_object *tObj = ctx->Texture.Unit[textureset]._Current;
+ int tmu;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTextureSingleTMU_NoLock(%d)\n", textureset);
+ }
+
+ ti = fxTMGetTexInfo(tObj);
+
+ fxTexValidate(ctx, tObj);
+
+ fxSetupSingleTMU_NoLock(fxMesa, tObj);
+
+ if (ti->whichTMU == FX_TMU_BOTH)
+ tmu = FX_TMU0;
+ else
+ tmu = ti->whichTMU;
+ if (fxMesa->tmuSrc != tmu)
+ fxSelectSingleTMUSrc_NoLock(fxMesa, tmu, ti->LODblend);
+
+ if (textureset == 0 || !fxMesa->haveTwoTMUs)
+ unitsmode = fxGetTexSetConfiguration(ctx, tObj, NULL);
+ else
+ unitsmode = fxGetTexSetConfiguration(ctx, NULL, tObj);
+
+/* if(fxMesa->lastUnitsMode==unitsmode) */
+/* return; */
+
+ fxMesa->lastUnitsMode = unitsmode;
+
+ fxMesa->stw_hint_state = 0;
+ FX_grHints_NoLock(GR_HINT_STWHINT, 0);
+
+ ifmt = ti->baseLevelInternalFormat;
+
+ if (unitsmode & FX_UM_ALPHA_ITERATED)
+ locala = GR_COMBINE_LOCAL_ITERATED;
+ else
+ locala = GR_COMBINE_LOCAL_CONSTANT;
+
+ if (unitsmode & FX_UM_COLOR_ITERATED)
+ localc = GR_COMBINE_LOCAL_ITERATED;
+ else
+ localc = GR_COMBINE_LOCAL_CONSTANT;
+
+ if (TDFX_DEBUG & (VERBOSE_DRIVER | VERBOSE_TEXTURE))
+ fprintf(stderr, "fxSetupTextureSingleTMU_NoLock: envmode is %s\n",
+ _mesa_lookup_enum_by_nr(ctx->Texture.Unit[textureset].EnvMode));
+
+ alphaComb.Local = locala;
+ alphaComb.Invert = FXFALSE;
+ colorComb.Local = localc;
+ colorComb.Invert = FXFALSE;
+
+ switch (ctx->Texture.Unit[textureset].EnvMode) {
+ case GL_DECAL:
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+
+ colorComb.Function = GR_COMBINE_FUNCTION_BLEND;
+ colorComb.Factor = GR_COMBINE_FACTOR_TEXTURE_ALPHA;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ break;
+ case GL_MODULATE:
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+
+ if (ifmt == GL_ALPHA) {
+ colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ colorComb.Factor = GR_COMBINE_FACTOR_NONE;
+ colorComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+ break;
+ case GL_BLEND:
+ if (ifmt == GL_LUMINANCE || ifmt == GL_RGB) {
+ /* Av = Af */
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+ }
+ else if (ifmt == GL_INTENSITY) {
+ /* Av = Af * (1 - It) + Ac * It */
+ alphaComb.Function = GR_COMBINE_FUNCTION_BLEND;
+ alphaComb.Factor = GR_COMBINE_FACTOR_TEXTURE_ALPHA;
+ alphaComb.Other = GR_COMBINE_OTHER_CONSTANT;
+ }
+ else {
+ /* Av = Af * At */
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+
+ if (ifmt == GL_ALPHA) {
+ colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ colorComb.Factor = GR_COMBINE_FACTOR_NONE;
+ colorComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ if (fxMesa->type >= GR_SSTTYPE_Voodoo2) {
+ colorComb.Function = GR_COMBINE_FUNCTION_BLEND;
+ colorComb.Factor = GR_COMBINE_FACTOR_TEXTURE_RGB;
+ colorComb.Other = GR_COMBINE_OTHER_CONSTANT;
+ } else if (ifmt == GL_INTENSITY) {
+ /* just a hack: RGB == ALPHA */
+ colorComb.Function = GR_COMBINE_FUNCTION_BLEND;
+ colorComb.Factor = GR_COMBINE_FACTOR_TEXTURE_ALPHA;
+ colorComb.Other = GR_COMBINE_OTHER_CONSTANT;
+ } else {
+ /* Only Voodoo^2 can GL_BLEND (GR_COMBINE_FACTOR_TEXTURE_RGB)
+ * These settings assume that the TexEnv color is black and
+ * incoming fragment color is white.
+ */
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ colorComb.Invert = FXTRUE;
+ _mesa_problem(NULL, "can't GL_BLEND with SST1");
+ }
+ }
+
+ grConstantColorValue(
+ (((GLuint)(ctx->Texture.Unit[textureset].EnvColor[0] * 255.0f)) ) |
+ (((GLuint)(ctx->Texture.Unit[textureset].EnvColor[1] * 255.0f)) << 8) |
+ (((GLuint)(ctx->Texture.Unit[textureset].EnvColor[2] * 255.0f)) << 16) |
+ (((GLuint)(ctx->Texture.Unit[textureset].EnvColor[3] * 255.0f)) << 24));
+ break;
+ case GL_REPLACE:
+ if ((ifmt == GL_RGB) || (ifmt == GL_LUMINANCE)) {
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+
+ if (ifmt == GL_ALPHA) {
+ colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ colorComb.Factor = GR_COMBINE_FACTOR_NONE;
+ colorComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+ break;
+ case GL_ADD:
+ if (ifmt == GL_ALPHA ||
+ ifmt == GL_LUMINANCE_ALPHA ||
+ ifmt == GL_RGBA) {
+ /* product of texel and fragment alpha */
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+ else if (ifmt == GL_LUMINANCE || ifmt == GL_RGB) {
+ /* fragment alpha is unchanged */
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+ }
+ else {
+ /* sum of texel and fragment alpha */
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+
+ if (ifmt == GL_ALPHA) {
+ /* rgb unchanged */
+ colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ colorComb.Factor = GR_COMBINE_FACTOR_NONE;
+ colorComb.Other = GR_COMBINE_OTHER_NONE;
+ }
+ else {
+ /* sum of texel and fragment rgb */
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+ break;
+ default:
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTextureSingleTMU_NoLock: %x Texture.EnvMode not yet supported\n",
+ ctx->Texture.Unit[textureset].EnvMode);
+ }
+ return;
+ }
+
+ grAlphaCombine(alphaComb.Function,
+ alphaComb.Factor,
+ alphaComb.Local,
+ alphaComb.Other,
+ alphaComb.Invert);
+ grColorCombine(colorComb.Function,
+ colorComb.Factor,
+ colorComb.Local,
+ colorComb.Other,
+ colorComb.Invert);
+}
+
+#if 00
+static void
+fxSetupTextureSingleTMU(GLcontext * ctx, GLuint textureset)
+{
+ BEGIN_BOARD_LOCK();
+ fxSetupTextureSingleTMU_NoLock(ctx, textureset);
+ END_BOARD_LOCK();
+}
+#endif
+
+
+/************************* Double Texture Set ***************************/
+
+static void
+fxSetupDoubleTMU_NoLock(fxMesaContext 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
+
+ tfxTexInfo *ti0 = fxTMGetTexInfo(tObj0);
+ tfxTexInfo *ti1 = fxTMGetTexInfo(tObj1);
+ GLuint tstate = 0;
+ int tmu0 = 0, tmu1 = 1;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupDoubleTMU_NoLock(...)\n");
+ }
+
+ /* We shouldn't need to do this. There is something wrong with
+ mutlitexturing when the TMUs are swapped. So, we're forcing
+ them to always be loaded correctly. !!! */
+ if (ti0->whichTMU == FX_TMU1)
+ fxTMMoveOutTM_NoLock(fxMesa, tObj0);
+ if (ti1->whichTMU == FX_TMU0)
+ fxTMMoveOutTM_NoLock(fxMesa, tObj1);
+
+ if (ti0->isInTM) {
+ switch (ti0->whichTMU) {
+ case FX_TMU0:
+ tstate |= T0_IN_TMU0;
+ break;
+ case FX_TMU1:
+ tstate |= T0_IN_TMU1;
+ break;
+ case FX_TMU_BOTH:
+ tstate |= T0_IN_TMU0 | T0_IN_TMU1;
+ break;
+ case FX_TMU_SPLIT:
+ tstate |= T0_NOT_IN_TMU;
+ break;
+ }
+ }
+ else
+ tstate |= T0_NOT_IN_TMU;
+
+ if (ti1->isInTM) {
+ switch (ti1->whichTMU) {
+ case FX_TMU0:
+ tstate |= T1_IN_TMU0;
+ break;
+ case FX_TMU1:
+ tstate |= T1_IN_TMU1;
+ break;
+ case FX_TMU_BOTH:
+ tstate |= T1_IN_TMU0 | T1_IN_TMU1;
+ break;
+ case FX_TMU_SPLIT:
+ tstate |= T1_NOT_IN_TMU;
+ break;
+ }
+ }
+ else
+ tstate |= T1_NOT_IN_TMU;
+
+ ti0->lastTimeUsed = fxMesa->texBindNumber;
+ ti1->lastTimeUsed = fxMesa->texBindNumber;
+
+ /* 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)
+ fxTMMoveInTM_NoLock(fxMesa, tObj1, FX_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 */
+ fxTMMoveInTM_NoLock(fxMesa, tObj1, FX_TMU1);
+ }
+ else {
+ fxTMMoveInTM_NoLock(fxMesa, tObj0, FX_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 */
+ fxTMMoveInTM_NoLock(fxMesa, tObj0, FX_TMU1);
+ }
+ else {
+ fxTMMoveInTM_NoLock(fxMesa, tObj1, FX_TMU0);
+ }
+ tmu0 = 1;
+ tmu1 = 0;
+ }
+ else { /* Nothing is loaded */
+ fxTMMoveInTM_NoLock(fxMesa, tObj0, FX_TMU0);
+ fxTMMoveInTM_NoLock(fxMesa, tObj1, FX_TMU1);
+ /* tmu0 and tmu1 are setup */
+ }
+ }
+ }
+
+ /* [dBorca] Hack alert:
+ * we put these in reverse order, so that if we can't
+ * do _REAL_ pointcast, the TMU0 table gets broadcasted
+ */
+ if (!fxMesa->haveGlobalPaletteTexture) {
+ /* pointcast */
+ if (ti1->info.format == GR_TEXFMT_P_8) {
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupDoubleTMU_NoLock: uploading texture palette for TMU1\n");
+ }
+ fxMesa->Glide.grTexDownloadTableExt(ti1->whichTMU, ti1->paltype, &(ti1->palette));
+ }
+ if (ti0->info.format == GR_TEXFMT_P_8) {
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupDoubleTMU_NoLock: uploading texture palette for TMU0\n");
+ }
+ fxMesa->Glide.grTexDownloadTableExt(ti0->whichTMU, ti0->paltype, &(ti0->palette));
+ }
+ }
+
+ grTexSource(tmu0, ti0->tm[tmu0]->startAddr,
+ GR_MIPMAPLEVELMASK_BOTH, &(ti0->info));
+ grTexClampMode(tmu0, ti0->sClamp, ti0->tClamp);
+ grTexFilterMode(tmu0, ti0->minFilt, ti0->maxFilt);
+ grTexMipMapMode(tmu0, ti0->mmMode, FXFALSE);
+
+ grTexSource(tmu1, ti1->tm[tmu1]->startAddr,
+ GR_MIPMAPLEVELMASK_BOTH, &(ti1->info));
+ grTexClampMode(tmu1, ti1->sClamp, ti1->tClamp);
+ grTexFilterMode(tmu1, ti1->minFilt, ti1->maxFilt);
+ grTexMipMapMode(tmu1, ti1->mmMode, FXFALSE);
+
+#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
+fxSetupTextureDoubleTMU_NoLock(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ struct tdfx_combine alphaComb, colorComb;
+ struct tdfx_texcombine tex0, tex1;
+ GrCombineLocal_t localc, locala;
+ tfxTexInfo *ti0, *ti1;
+ struct gl_texture_object *tObj0 = ctx->Texture.Unit[1]._Current;
+ struct gl_texture_object *tObj1 = ctx->Texture.Unit[0]._Current;
+ GLuint envmode, ifmt, unitsmode;
+ int tmu0 = 0, tmu1 = 1;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTextureDoubleTMU_NoLock(...)\n");
+ }
+
+ ti0 = fxTMGetTexInfo(tObj0);
+ fxTexValidate(ctx, tObj0);
+
+ ti1 = fxTMGetTexInfo(tObj1);
+ fxTexValidate(ctx, tObj1);
+
+ fxSetupDoubleTMU_NoLock(fxMesa, tObj0, tObj1);
+
+ unitsmode = fxGetTexSetConfiguration(ctx, tObj0, tObj1);
+
+/* if(fxMesa->lastUnitsMode==unitsmode) */
+/* return; */
+
+ fxMesa->lastUnitsMode = unitsmode;
+
+ fxMesa->stw_hint_state |= GR_STWHINT_ST_DIFF_TMU1;
+ FX_grHints_NoLock(GR_HINT_STWHINT, fxMesa->stw_hint_state);
+
+ envmode = unitsmode & FX_UM_E_ENVMODE;
+ ifmt = unitsmode & FX_UM_E_IFMT;
+
+ if (unitsmode & FX_UM_ALPHA_ITERATED)
+ locala = GR_COMBINE_LOCAL_ITERATED;
+ else
+ locala = GR_COMBINE_LOCAL_CONSTANT;
+
+ if (unitsmode & FX_UM_COLOR_ITERATED)
+ localc = GR_COMBINE_LOCAL_ITERATED;
+ else
+ localc = GR_COMBINE_LOCAL_CONSTANT;
+
+
+ if (TDFX_DEBUG & (VERBOSE_DRIVER | VERBOSE_TEXTURE))
+ fprintf(stderr, "fxSetupTextureDoubleTMU_NoLock: envmode is %s/%s\n",
+ _mesa_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode),
+ _mesa_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode));
+
+
+ if ((ti0->whichTMU == FX_TMU1) || (ti1->whichTMU == FX_TMU0)) {
+ tmu0 = 1;
+ tmu1 = 0;
+ }
+ fxMesa->tmuSrc = FX_TMU_BOTH;
+
+ tex0.InvertRGB = FXFALSE;
+ tex0.InvertAlpha = FXFALSE;
+ tex1.InvertRGB = FXFALSE;
+ tex1.InvertAlpha = FXFALSE;
+ alphaComb.Local = locala;
+ alphaComb.Invert = FXFALSE;
+ colorComb.Local = localc;
+ colorComb.Invert = FXFALSE;
+
+ switch (envmode) {
+ case (FX_UM_E0_MODULATE | FX_UM_E1_MODULATE):
+ {
+ GLboolean isalpha[FX_NUM_TMU];
+
+ isalpha[tmu0] = (ti0->baseLevelInternalFormat == GL_ALPHA);
+ isalpha[tmu1] = (ti1->baseLevelInternalFormat == GL_ALPHA);
+
+ if (isalpha[FX_TMU1]) {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ tex1.InvertRGB = FXTRUE;
+ } else {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ }
+
+ if (isalpha[FX_TMU0]) {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
+ } else {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_LOCAL;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
+ }
+
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ break;
+ }
+ case (FX_UM_E0_REPLACE | FX_UM_E1_BLEND): /* Only for GLQuake */
+ if (tmu0 == FX_TMU1) {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ tex1.InvertRGB = FXTRUE;
+
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_LOCAL;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
+ }
+ else {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE_MINUS_LOCAL;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE_MINUS_LOCAL;
+ }
+
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ break;
+ case (FX_UM_E0_REPLACE | FX_UM_E1_MODULATE): /* Quake 2 and 3 */
+ if (tmu1 == FX_TMU1) {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ tex1.InvertAlpha = FXTRUE;
+
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_LOCAL;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
+ }
+ else {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_LOCAL;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE;
+ }
+
+ if (ti0->baseLevelInternalFormat == GL_RGB) {
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+ }
+
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ break;
+
+
+ case (FX_UM_E0_MODULATE | FX_UM_E1_ADD): /* Quake 3 Sky */
+ {
+ GLboolean isalpha[FX_NUM_TMU];
+
+ isalpha[tmu0] = (ti0->baseLevelInternalFormat == GL_ALPHA);
+ isalpha[tmu1] = (ti1->baseLevelInternalFormat == GL_ALPHA);
+
+ if (isalpha[FX_TMU1]) {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ tex1.InvertRGB = FXTRUE;
+ } else {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ }
+
+ if (isalpha[FX_TMU0]) {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE;
+ } else {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE;
+ }
+
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ break;
+ }
+
+ case (FX_UM_E0_REPLACE | FX_UM_E1_ADD): /* Vulpine Sky */
+ {
+ GLboolean isalpha[FX_NUM_TMU];
+
+ isalpha[tmu0] = (ti0->baseLevelInternalFormat == GL_ALPHA);
+ isalpha[tmu1] = (ti1->baseLevelInternalFormat == GL_ALPHA);
+
+ if (isalpha[FX_TMU1]) {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ tex1.InvertRGB = FXTRUE;
+ } else {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ }
+
+ if (isalpha[FX_TMU0]) {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE;
+ } else {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE;
+ }
+
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ break;
+ }
+
+ case (FX_UM_E0_MODULATE | FX_UM_E1_REPLACE): /* Homeworld2 */
+ {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ if (ifmt & (FX_UM_E0_RGB | FX_UM_E0_LUMINANCE)) {
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+
+ if (ifmt & FX_UM_E0_ALPHA) {
+ colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ colorComb.Factor = GR_COMBINE_FACTOR_NONE;
+ colorComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+ break;
+ }
+ default:
+ fprintf(stderr, "fxSetupTextureDoubleTMU_NoLock: Unexpected dual texture mode encountered\n");
+ return;
+ }
+
+ grAlphaCombine(alphaComb.Function,
+ alphaComb.Factor,
+ alphaComb.Local,
+ alphaComb.Other,
+ alphaComb.Invert);
+ grColorCombine(colorComb.Function,
+ colorComb.Factor,
+ colorComb.Local,
+ colorComb.Other,
+ colorComb.Invert);
+ grTexCombine(GR_TMU0,
+ tex0.FunctionRGB,
+ tex0.FactorRGB,
+ tex0.FunctionAlpha,
+ tex0.FactorAlpha,
+ tex0.InvertRGB,
+ tex0.InvertAlpha);
+ grTexCombine(GR_TMU1,
+ tex1.FunctionRGB,
+ tex1.FactorRGB,
+ tex1.FunctionAlpha,
+ tex1.FactorAlpha,
+ tex1.InvertRGB,
+ tex1.InvertAlpha);
+}
+
+/************************* No Texture ***************************/
+
+static void
+fxSetupTextureNone_NoLock(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrCombineLocal_t localc, locala;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTextureNone_NoLock(...)\n");
+ }
+
+ if ((ctx->Light.ShadeModel == GL_SMOOTH) || 1 ||
+ (ctx->Point.SmoothFlag) ||
+ (ctx->Line.SmoothFlag) ||
+ (ctx->Polygon.SmoothFlag)) locala = GR_COMBINE_LOCAL_ITERATED;
+ else
+ locala = GR_COMBINE_LOCAL_CONSTANT;
+
+ if (ctx->Light.ShadeModel == GL_SMOOTH || 1)
+ localc = GR_COMBINE_LOCAL_ITERATED;
+ else
+ localc = GR_COMBINE_LOCAL_CONSTANT;
+
+ grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ grColorCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ localc,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ fxMesa->lastUnitsMode = FX_UM_NONE;
+}
+
+#include "fxsetup.h"
+
+/************************************************************************/
+/************************** Texture Mode SetUp **************************/
+/************************************************************************/
+
+static void
+fxSetupTexture_NoLock(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTexture_NoLock(...)\n");
+ }
+
+ if (fxMesa->HaveCmbExt) {
+ /* Texture Combine, Color Combine and Alpha Combine. */
+ if ((ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) &&
+ (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) &&
+ fxMesa->haveTwoTMUs) {
+ fxSetupTextureDoubleTMUNapalm_NoLock(ctx);
+ }
+ else if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
+ fxSetupTextureSingleTMUNapalm_NoLock(ctx, 0);
+ }
+ else if (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
+ fxSetupTextureSingleTMUNapalm_NoLock(ctx, 1);
+ }
+ else {
+ fxSetupTextureNoneNapalm_NoLock(ctx);
+ }
+ } else {
+ /* Texture Combine, Color Combine and Alpha Combine. */
+ if ((ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) &&
+ (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) &&
+ fxMesa->haveTwoTMUs) {
+ fxSetupTextureDoubleTMU_NoLock(ctx);
+ }
+ else if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
+ fxSetupTextureSingleTMU_NoLock(ctx, 0);
+ }
+ else if (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
+ fxSetupTextureSingleTMU_NoLock(ctx, 1);
+ }
+ else {
+ fxSetupTextureNone_NoLock(ctx);
+ }
+ }
+}
+
+void
+fxSetupTexture(GLcontext * ctx)
+{
+ BEGIN_BOARD_LOCK();
+ fxSetupTexture_NoLock(ctx);
+ END_BOARD_LOCK();
+}
+
+/************************************************************************/
+/**************************** Blend SetUp *******************************/
+/************************************************************************/
+
+void
+fxDDBlendFuncSeparate(GLcontext * ctx, GLenum sfactor, GLenum dfactor, GLenum asfactor, GLenum adfactor)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+ GLboolean isNapalm = (fxMesa->type >= GR_SSTTYPE_Voodoo4);
+ GLboolean have32bpp = (fxMesa->colDepth == 32);
+ GLboolean haveAlpha = fxMesa->haveHwAlpha;
+ GrAlphaBlendFnc_t sfact, dfact, asfact, adfact;
+
+ /*
+ * 15/16 BPP alpha channel alpha blending modes
+ * 0x0 AZERO Zero
+ * 0x4 AONE One
+ *
+ * 32 BPP alpha channel alpha blending modes
+ * 0x0 AZERO Zero
+ * 0x1 ASRC_ALPHA Source alpha
+ * 0x3 ADST_ALPHA Destination alpha
+ * 0x4 AONE One
+ * 0x5 AOMSRC_ALPHA 1 - Source alpha
+ * 0x7 AOMDST_ALPHA 1 - Destination alpha
+ *
+ * If we don't have HW alpha buffer:
+ * DST_ALPHA == 1
+ * ONE_MINUS_DST_ALPHA == 0
+ * Unsupported modes are:
+ * 1 if used as src blending factor
+ * 0 if used as dst blending factor
+ */
+
+ switch (sfactor) {
+ case GL_ZERO:
+ sfact = GR_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ sfact = GR_BLEND_ONE;
+ break;
+ case GL_DST_COLOR:
+ sfact = GR_BLEND_DST_COLOR;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ sfact = GR_BLEND_ONE_MINUS_DST_COLOR;
+ break;
+ case GL_SRC_ALPHA:
+ sfact = GR_BLEND_SRC_ALPHA;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ sfact = GR_BLEND_ONE_MINUS_SRC_ALPHA;
+ break;
+ case GL_DST_ALPHA:
+ sfact = haveAlpha ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE/*bad*/;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ sfact = haveAlpha ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO/*bad*/;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ sfact = GR_BLEND_ALPHA_SATURATE;
+ break;
+ case GL_SRC_COLOR:
+ if (isNapalm) {
+ sfact = GR_BLEND_SAME_COLOR_EXT;
+ break;
+ }
+ case GL_ONE_MINUS_SRC_COLOR:
+ if (isNapalm) {
+ sfact = GR_BLEND_ONE_MINUS_SAME_COLOR_EXT;
+ break;
+ }
+ default:
+ sfact = GR_BLEND_ONE;
+ break;
+ }
+
+ switch (asfactor) {
+ case GL_ZERO:
+ asfact = GR_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ asfact = GR_BLEND_ONE;
+ break;
+ case GL_SRC_COLOR:
+ case GL_SRC_ALPHA:
+ asfact = have32bpp ? GR_BLEND_SRC_ALPHA : GR_BLEND_ONE/*bad*/;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ asfact = have32bpp ? GR_BLEND_ONE_MINUS_SRC_ALPHA : GR_BLEND_ONE/*bad*/;
+ break;
+ case GL_DST_COLOR:
+ case GL_DST_ALPHA:
+ asfact = (have32bpp && haveAlpha) ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE/*bad*/;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_ONE_MINUS_DST_ALPHA:
+ asfact = (have32bpp && haveAlpha) ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO/*bad*/;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ asfact = GR_BLEND_ONE;
+ break;
+ default:
+ asfact = GR_BLEND_ONE;
+ break;
+ }
+
+ switch (dfactor) {
+ case GL_ZERO:
+ dfact = GR_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ dfact = GR_BLEND_ONE;
+ break;
+ case GL_SRC_COLOR:
+ dfact = GR_BLEND_SRC_COLOR;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ dfact = GR_BLEND_ONE_MINUS_SRC_COLOR;
+ break;
+ case GL_SRC_ALPHA:
+ dfact = GR_BLEND_SRC_ALPHA;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ dfact = GR_BLEND_ONE_MINUS_SRC_ALPHA;
+ break;
+ case GL_DST_ALPHA:
+ dfact = haveAlpha ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE/*bad*/;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dfact = haveAlpha ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO/*bad*/;
+ break;
+ case GL_DST_COLOR:
+ if (isNapalm) {
+ dfact = GR_BLEND_SAME_COLOR_EXT;
+ break;
+ }
+ case GL_ONE_MINUS_DST_COLOR:
+ if (isNapalm) {
+ dfact = GR_BLEND_ONE_MINUS_SAME_COLOR_EXT;
+ break;
+ }
+ default:
+ dfact = GR_BLEND_ZERO;
+ break;
+ }
+
+ switch (adfactor) {
+ case GL_ZERO:
+ adfact = GR_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ adfact = GR_BLEND_ONE;
+ break;
+ case GL_SRC_COLOR:
+ case GL_SRC_ALPHA:
+ adfact = have32bpp ? GR_BLEND_SRC_ALPHA : GR_BLEND_ZERO/*bad*/;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ adfact = have32bpp ? GR_BLEND_ONE_MINUS_SRC_ALPHA : GR_BLEND_ZERO/*bad*/;
+ break;
+ case GL_DST_COLOR:
+ case GL_DST_ALPHA:
+ adfact = (have32bpp && haveAlpha) ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE/*bad*/;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_ONE_MINUS_DST_ALPHA:
+ adfact = (have32bpp && haveAlpha) ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO/*bad*/;
+ break;
+ default:
+ adfact = GR_BLEND_ZERO;
+ break;
+ }
+
+ if ((sfact != us->blendSrcFuncRGB) || (asfact != us->blendSrcFuncAlpha)) {
+ us->blendSrcFuncRGB = sfact;
+ us->blendSrcFuncAlpha = asfact;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ }
+
+ if ((dfact != us->blendDstFuncRGB) || (adfact != us->blendDstFuncAlpha)) {
+ us->blendDstFuncRGB = dfact;
+ us->blendDstFuncAlpha = adfact;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ }
+}
+
+void
+fxDDBlendEquationSeparate(GLcontext * ctx, GLenum modeRGB, GLenum modeA)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+ GrAlphaBlendOp_t q;
+
+ switch (modeRGB) {
+ case GL_FUNC_ADD:
+ q = GR_BLEND_OP_ADD;
+ break;
+ case GL_FUNC_SUBTRACT:
+ q = GR_BLEND_OP_SUB;
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ q = GR_BLEND_OP_REVSUB;
+ break;
+ default:
+ q = us->blendEqRGB;
+ }
+ if (q != us->blendEqRGB) {
+ us->blendEqRGB = q;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ }
+
+ switch (modeA) {
+ case GL_FUNC_ADD:
+ q = GR_BLEND_OP_ADD;
+ break;
+ case GL_FUNC_SUBTRACT:
+ q = GR_BLEND_OP_SUB;
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ q = GR_BLEND_OP_REVSUB;
+ break;
+ default:
+ q = us->blendEqAlpha;
+ }
+ if (q != us->blendEqAlpha) {
+ us->blendEqAlpha = q;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ }
+}
+
+void
+fxSetupBlend(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (fxMesa->HavePixExt) {
+ if (us->blendEnabled) {
+ fxMesa->Glide.grAlphaBlendFunctionExt(us->blendSrcFuncRGB, us->blendDstFuncRGB,
+ us->blendEqRGB,
+ us->blendSrcFuncAlpha, us->blendDstFuncAlpha,
+ us->blendEqAlpha);
+ } else {
+ fxMesa->Glide.grAlphaBlendFunctionExt(GR_BLEND_ONE, GR_BLEND_ZERO,
+ GR_BLEND_OP_ADD,
+ GR_BLEND_ONE, GR_BLEND_ZERO,
+ GR_BLEND_OP_ADD);
+ }
+ } else {
+ if (us->blendEnabled) {
+ grAlphaBlendFunction(us->blendSrcFuncRGB, us->blendDstFuncRGB,
+ us->blendSrcFuncAlpha, us->blendDstFuncAlpha);
+ } else {
+ grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO,
+ GR_BLEND_ONE, GR_BLEND_ZERO);
+ }
+ }
+}
+
+/************************************************************************/
+/************************** Alpha Test SetUp ****************************/
+/************************************************************************/
+
+void
+fxDDAlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (
+ (us->alphaTestFunc != func)
+ ||
+ (us->alphaTestRefValue != ref)
+ ) {
+ us->alphaTestFunc = func;
+ us->alphaTestRefValue = ref;
+ fxMesa->new_state |= FX_NEW_ALPHA;
+ }
+}
+
+static void
+fxSetupAlphaTest(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (us->alphaTestEnabled) {
+ GrAlpha_t ref = (GLint) (us->alphaTestRefValue * 255.0);
+ grAlphaTestFunction(us->alphaTestFunc - GL_NEVER + GR_CMP_NEVER);
+ grAlphaTestReferenceValue(ref);
+ }
+ else
+ grAlphaTestFunction(GR_CMP_ALWAYS);
+}
+
+/************************************************************************/
+/************************** Depth Test SetUp ****************************/
+/************************************************************************/
+
+void
+fxDDDepthFunc(GLcontext * ctx, GLenum func)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (us->depthTestFunc != func) {
+ us->depthTestFunc = func;
+ fxMesa->new_state |= FX_NEW_DEPTH;
+ }
+}
+
+void
+fxDDDepthMask(GLcontext * ctx, GLboolean flag)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (flag != us->depthMask) {
+ us->depthMask = flag;
+ fxMesa->new_state |= FX_NEW_DEPTH;
+ }
+}
+
+void
+fxSetupDepthTest(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (us->depthTestEnabled) {
+ grDepthBufferFunction(us->depthTestFunc - GL_NEVER + GR_CMP_NEVER);
+ grDepthMask(us->depthMask);
+ }
+ else {
+ grDepthBufferFunction(GR_CMP_ALWAYS);
+ grDepthMask(FXFALSE);
+ }
+}
+
+/************************************************************************/
+/************************** Stencil SetUp *******************************/
+/************************************************************************/
+
+static GrStencil_t convertGLStencilOp( GLenum op )
+{
+ switch ( op ) {
+ case GL_KEEP:
+ return GR_STENCILOP_KEEP;
+ case GL_ZERO:
+ return GR_STENCILOP_ZERO;
+ case GL_REPLACE:
+ return GR_STENCILOP_REPLACE;
+ case GL_INCR:
+ return GR_STENCILOP_INCR_CLAMP;
+ case GL_DECR:
+ return GR_STENCILOP_DECR_CLAMP;
+ case GL_INVERT:
+ return GR_STENCILOP_INVERT;
+ case GL_INCR_WRAP_EXT:
+ return GR_STENCILOP_INCR_WRAP;
+ case GL_DECR_WRAP_EXT:
+ return GR_STENCILOP_DECR_WRAP;
+ default:
+ _mesa_problem( NULL, "bad stencil op in convertGLStencilOp" );
+ }
+ return GR_STENCILOP_KEEP; /* never get, silence compiler warning */
+}
+
+void
+fxDDStencilFuncSeparate (GLcontext *ctx, GLenum face, GLenum func,
+ GLint ref, GLuint mask)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (ctx->Stencil.ActiveFace) {
+ return;
+ }
+
+ if (
+ (us->stencilFunction != func)
+ ||
+ (us->stencilRefValue != ref)
+ ||
+ (us->stencilValueMask != mask)
+ ) {
+ us->stencilFunction = func;
+ us->stencilRefValue = ref;
+ us->stencilValueMask = mask;
+ fxMesa->new_state |= FX_NEW_STENCIL;
+ }
+}
+
+void
+fxDDStencilMaskSeparate (GLcontext *ctx, GLenum face, GLuint mask)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (ctx->Stencil.ActiveFace) {
+ return;
+ }
+
+ if (us->stencilWriteMask != mask) {
+ us->stencilWriteMask = mask;
+ fxMesa->new_state |= FX_NEW_STENCIL;
+ }
+}
+
+void
+fxDDStencilOpSeparate (GLcontext *ctx, GLenum face, GLenum sfail,
+ GLenum zfail, GLenum zpass)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (ctx->Stencil.ActiveFace) {
+ return;
+ }
+
+ if (
+ (us->stencilFailFunc != sfail)
+ ||
+ (us->stencilZFailFunc != zfail)
+ ||
+ (us->stencilZPassFunc != zpass)
+ ) {
+ us->stencilFailFunc = sfail;
+ us->stencilZFailFunc = zfail;
+ us->stencilZPassFunc = zpass;
+ fxMesa->new_state |= FX_NEW_STENCIL;
+ }
+}
+
+void
+fxSetupStencil (GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (us->stencilEnabled) {
+ GrCmpFnc_t stencilFailFunc = GR_STENCILOP_KEEP;
+ GrCmpFnc_t stencilZFailFunc = GR_STENCILOP_KEEP;
+ GrCmpFnc_t stencilZPassFunc = GR_STENCILOP_KEEP;
+ if (!fxMesa->multipass) {
+ stencilFailFunc = convertGLStencilOp(us->stencilFailFunc);
+ stencilZFailFunc = convertGLStencilOp(us->stencilZFailFunc);
+ stencilZPassFunc = convertGLStencilOp(us->stencilZPassFunc);
+ }
+ grEnable(GR_STENCIL_MODE_EXT);
+ fxMesa->Glide.grStencilOpExt(stencilFailFunc,
+ stencilZFailFunc,
+ stencilZPassFunc);
+ fxMesa->Glide.grStencilFuncExt(us->stencilFunction - GL_NEVER + GR_CMP_NEVER,
+ us->stencilRefValue,
+ us->stencilValueMask);
+ fxMesa->Glide.grStencilMaskExt(us->stencilWriteMask);
+ } else {
+ grDisable(GR_STENCIL_MODE_EXT);
+ }
+}
+
+void
+fxSetupStencilFace (GLcontext * ctx, GLint face)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (us->stencilEnabled) {
+ GrCmpFnc_t stencilFailFunc = GR_STENCILOP_KEEP;
+ GrCmpFnc_t stencilZFailFunc = GR_STENCILOP_KEEP;
+ GrCmpFnc_t stencilZPassFunc = GR_STENCILOP_KEEP;
+ if (!fxMesa->multipass) {
+ stencilFailFunc = convertGLStencilOp(ctx->Stencil.FailFunc[face]);
+ stencilZFailFunc = convertGLStencilOp(ctx->Stencil.ZFailFunc[face]);
+ stencilZPassFunc = convertGLStencilOp(ctx->Stencil.ZPassFunc[face]);
+ }
+ grEnable(GR_STENCIL_MODE_EXT);
+ fxMesa->Glide.grStencilOpExt(stencilFailFunc,
+ stencilZFailFunc,
+ stencilZPassFunc);
+ fxMesa->Glide.grStencilFuncExt(ctx->Stencil.Function[face] - GL_NEVER + GR_CMP_NEVER,
+ ctx->Stencil.Ref[face],
+ ctx->Stencil.ValueMask[face]);
+ fxMesa->Glide.grStencilMaskExt(ctx->Stencil.WriteMask[face]);
+ } else {
+ grDisable(GR_STENCIL_MODE_EXT);
+ }
+}
+
+/************************************************************************/
+/**************************** Color Mask SetUp **************************/
+/************************************************************************/
+
+void
+fxDDColorMask(GLcontext * ctx,
+ GLboolean r, GLboolean g, GLboolean b, GLboolean a)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ fxMesa->new_state |= FX_NEW_COLOR_MASK;
+ (void) r;
+ (void) g;
+ (void) b;
+ (void) a;
+}
+
+void
+fxSetupColorMask(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (fxMesa->colDepth == 32) {
+ /* 32bpp mode */
+ fxMesa->Glide.grColorMaskExt(ctx->Color.ColorMask[RCOMP],
+ ctx->Color.ColorMask[GCOMP],
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP] && fxMesa->haveHwAlpha);
+ }
+ else {
+ /* 15/16 bpp mode */
+ grColorMask(ctx->Color.ColorMask[RCOMP] |
+ ctx->Color.ColorMask[GCOMP] |
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP] && fxMesa->haveHwAlpha);
+ }
+}
+
+
+
+
+/************************************************************************/
+/**************************** Fog Mode SetUp ****************************/
+/************************************************************************/
+
+/*
+ * This is called during state update in order to update the Glide fog state.
+ */
+static void
+fxSetupFog(GLcontext * ctx)
+{
+ if (ctx->Fog.Enabled /*&& ctx->FogMode==FOG_FRAGMENT */ ) {
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ /* update fog color */
+ GLubyte col[4];
+ col[0] = (unsigned int) (255 * ctx->Fog.Color[0]);
+ col[1] = (unsigned int) (255 * ctx->Fog.Color[1]);
+ col[2] = (unsigned int) (255 * ctx->Fog.Color[2]);
+ col[3] = (unsigned int) (255 * ctx->Fog.Color[3]);
+ grFogColorValue(FXCOLOR4(col));
+
+ if (fxMesa->fogTableMode != ctx->Fog.Mode ||
+ fxMesa->fogDensity != ctx->Fog.Density ||
+ fxMesa->fogStart != ctx->Fog.Start ||
+ fxMesa->fogEnd != ctx->Fog.End) {
+ /* reload the fog table */
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ guFogGenerateLinear(fxMesa->fogTable, ctx->Fog.Start,
+ ctx->Fog.End);
+ if (fxMesa->fogTable[0] > 63) {
+ /* [dBorca] Hack alert:
+ * As per Glide3 Programming Guide:
+ * The difference between consecutive fog values
+ * must be less than 64.
+ */
+ fxMesa->fogTable[0] = 63;
+ }
+ break;
+ case GL_EXP:
+ guFogGenerateExp(fxMesa->fogTable, ctx->Fog.Density);
+ break;
+ case GL_EXP2:
+ guFogGenerateExp2(fxMesa->fogTable, ctx->Fog.Density);
+ break;
+ default:
+ ;
+ }
+ fxMesa->fogTableMode = ctx->Fog.Mode;
+ fxMesa->fogDensity = ctx->Fog.Density;
+ fxMesa->fogStart = ctx->Fog.Start;
+ fxMesa->fogEnd = ctx->Fog.End;
+ }
+
+ grFogTable(fxMesa->fogTable);
+ if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) {
+ grVertexLayout(GR_PARAM_FOG_EXT, GR_VERTEX_FOG_OFFSET << 2,
+ GR_PARAM_ENABLE);
+ grFogMode(GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
+ } else {
+ grVertexLayout(GR_PARAM_FOG_EXT, GR_VERTEX_FOG_OFFSET << 2,
+ GR_PARAM_DISABLE);
+ grFogMode(GR_FOG_WITH_TABLE_ON_Q);
+ }
+ }
+ else {
+ grFogMode(GR_FOG_DISABLE);
+ }
+}
+
+void
+fxDDFogfv(GLcontext * ctx, GLenum pname, const GLfloat * params)
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_FOG;
+ switch (pname) {
+ case GL_FOG_COORDINATE_SOURCE_EXT: {
+ GLenum p = (GLenum)*params;
+ if (p == GL_FOG_COORDINATE_EXT) {
+ _swrast_allow_vertex_fog(ctx, GL_TRUE);
+ _swrast_allow_pixel_fog(ctx, GL_FALSE);
+ _tnl_allow_vertex_fog( ctx, GL_TRUE);
+ _tnl_allow_pixel_fog( ctx, GL_FALSE);
+ } else {
+ _swrast_allow_vertex_fog(ctx, GL_FALSE);
+ _swrast_allow_pixel_fog(ctx, GL_TRUE);
+ _tnl_allow_vertex_fog( ctx, GL_FALSE);
+ _tnl_allow_pixel_fog( ctx, GL_TRUE);
+ }
+ break;
+ }
+ default:
+ ;
+ }
+}
+
+/************************************************************************/
+/************************** Scissor Test SetUp **************************/
+/************************************************************************/
+
+/* This routine is used in managing the lock state, and therefore can't lock */
+void
+fxSetScissorValues(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ int xmin, xmax;
+ int ymin, ymax;
+
+ if (ctx->Scissor.Enabled) {
+ xmin = ctx->Scissor.X;
+ xmax = ctx->Scissor.X + ctx->Scissor.Width;
+ ymin = ctx->Scissor.Y;
+ ymax = ctx->Scissor.Y + ctx->Scissor.Height;
+
+ if (xmin < 0)
+ xmin = 0;
+ if (xmax > fxMesa->width)
+ xmax = fxMesa->width;
+ if (ymin < fxMesa->screen_height - fxMesa->height)
+ ymin = fxMesa->screen_height - fxMesa->height;
+ if (ymax > fxMesa->screen_height - 0)
+ ymax = fxMesa->screen_height - 0;
+ }
+ else {
+ xmin = 0;
+ ymin = 0;
+ xmax = fxMesa->width;
+ ymax = fxMesa->height;
+ }
+
+ fxMesa->clipMinX = xmin;
+ fxMesa->clipMinY = ymin;
+ fxMesa->clipMaxX = xmax;
+ fxMesa->clipMaxY = ymax;
+ grClipWindow(xmin, ymin, xmax, ymax);
+}
+
+void
+fxSetupScissor(GLcontext * ctx)
+{
+ BEGIN_BOARD_LOCK();
+ fxSetScissorValues(ctx);
+ END_BOARD_LOCK();
+}
+
+void
+fxDDScissor(GLcontext * ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_SCISSOR;
+}
+
+/************************************************************************/
+/*************************** Cull mode setup ****************************/
+/************************************************************************/
+
+
+void
+fxDDCullFace(GLcontext * ctx, GLenum mode)
+{
+ (void) mode;
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL;
+}
+
+void
+fxDDFrontFace(GLcontext * ctx, GLenum mode)
+{
+ (void) mode;
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL;
+}
+
+
+void
+fxSetupCull(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrCullMode_t mode = GR_CULL_DISABLE;
+
+ if (ctx->Polygon.CullFlag && (fxMesa->raster_primitive == GL_TRIANGLES)) {
+ switch (ctx->Polygon.CullFaceMode) {
+ case GL_BACK:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ mode = GR_CULL_NEGATIVE;
+ else
+ mode = GR_CULL_POSITIVE;
+ break;
+ case GL_FRONT:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ mode = GR_CULL_POSITIVE;
+ else
+ mode = GR_CULL_NEGATIVE;
+ break;
+ case GL_FRONT_AND_BACK:
+ /* Handled as a fallback on triangles in tdfx_tris.c */
+ return;
+ default:
+ ASSERT(0);
+ break;
+ }
+ }
+
+ if (fxMesa->cullMode != mode) {
+ fxMesa->cullMode = mode;
+ grCullMode(mode);
+ }
+}
+
+
+/************************************************************************/
+/****************************** DD Enable ******************************/
+/************************************************************************/
+
+void
+fxDDEnable(GLcontext * ctx, GLenum cap, GLboolean state)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "%s(%s)\n", state ? "fxDDEnable" : "fxDDDisable",
+ _mesa_lookup_enum_by_nr(cap));
+ }
+
+ switch (cap) {
+ case GL_ALPHA_TEST:
+ if (state != us->alphaTestEnabled) {
+ us->alphaTestEnabled = state;
+ fxMesa->new_state |= FX_NEW_ALPHA;
+ }
+ break;
+ case GL_BLEND:
+ if (state != us->blendEnabled) {
+ us->blendEnabled = state;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ }
+ break;
+ case GL_DEPTH_TEST:
+ if (state != us->depthTestEnabled) {
+ us->depthTestEnabled = state;
+ fxMesa->new_state |= FX_NEW_DEPTH;
+ }
+ break;
+ case GL_STENCIL_TEST:
+ if (fxMesa->haveHwStencil && state != us->stencilEnabled) {
+ us->stencilEnabled = state;
+ fxMesa->new_state |= FX_NEW_STENCIL;
+ }
+ break;
+ case GL_DITHER:
+ if (state) {
+ grDitherMode(GR_DITHER_4x4);
+ }
+ else {
+ grDitherMode(GR_DITHER_DISABLE);
+ }
+ break;
+ case GL_SCISSOR_TEST:
+ fxMesa->new_state |= FX_NEW_SCISSOR;
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ fxDDTexUseGlbPalette(ctx, state);
+ break;
+ case GL_FOG:
+ fxMesa->new_state |= FX_NEW_FOG;
+ break;
+ case GL_CULL_FACE:
+ fxMesa->new_state |= FX_NEW_CULL;
+ break;
+ case GL_LINE_SMOOTH:
+ case GL_LINE_STIPPLE:
+ case GL_POINT_SMOOTH:
+ case GL_POLYGON_SMOOTH:
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+ break;
+ default:
+ ; /* XXX no-op? */
+ }
+}
+
+
+
+
+/************************************************************************/
+/************************** Changes to units state **********************/
+/************************************************************************/
+
+
+/* All units setup is handled under texture setup.
+ */
+void
+fxDDShadeModel(GLcontext * ctx, GLenum mode)
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_TEXTURING;
+}
+
+
+
+/************************************************************************/
+/****************************** Units SetUp *****************************/
+/************************************************************************/
+static void
+fx_print_state_flags(const char *msg, GLuint flags)
+{
+ fprintf(stderr,
+ "%s: (0x%x) %s%s%s%s%s%s%s%s\n",
+ msg,
+ flags,
+ (flags & FX_NEW_TEXTURING) ? "texture, " : "",
+ (flags & FX_NEW_BLEND) ? "blend, " : "",
+ (flags & FX_NEW_ALPHA) ? "alpha, " : "",
+ (flags & FX_NEW_FOG) ? "fog, " : "",
+ (flags & FX_NEW_SCISSOR) ? "scissor, " : "",
+ (flags & FX_NEW_COLOR_MASK) ? "colormask, " : "",
+ (flags & FX_NEW_CULL) ? "cull, " : "",
+ (flags & FX_NEW_STENCIL) ? "stencil, " : "");
+}
+
+void
+fxSetupFXUnits(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLuint newstate = fxMesa->new_state;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER)
+ fx_print_state_flags("fxSetupFXUnits", newstate);
+
+ if (newstate) {
+ if (newstate & FX_NEW_TEXTURING)
+ fxSetupTexture(ctx);
+
+ if (newstate & FX_NEW_BLEND)
+ fxSetupBlend(ctx);
+
+ if (newstate & FX_NEW_ALPHA)
+ fxSetupAlphaTest(ctx);
+
+ if (newstate & FX_NEW_DEPTH)
+ fxSetupDepthTest(ctx);
+
+ if (newstate & FX_NEW_STENCIL)
+ fxSetupStencil(ctx);
+
+ if (newstate & FX_NEW_FOG)
+ fxSetupFog(ctx);
+
+ if (newstate & FX_NEW_SCISSOR)
+ fxSetupScissor(ctx);
+
+ if (newstate & FX_NEW_COLOR_MASK)
+ fxSetupColorMask(ctx);
+
+ if (newstate & FX_NEW_CULL)
+ fxSetupCull(ctx);
+
+ fxMesa->new_state = 0;
+ }
+}
+
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+extern int gl_fx_dummy_function_setup(void);
+int
+gl_fx_dummy_function_setup(void)
+{
+ return 0;
+}
+
+#endif /* FX */