From f4092abdf94af6a99aff944d6264bc1284e8bdd4 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Mon, 10 Oct 2011 17:43:39 +0200 Subject: Imported nx-X11-3.1.0-1.tar.gz Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository --- .../extras/Mesa/src/mesa/drivers/glide/fxsetup.c | 2217 ++++++++++++++++++++ 1 file changed, 2217 insertions(+) create mode 100644 nx-X11/extras/Mesa/src/mesa/drivers/glide/fxsetup.c (limited to 'nx-X11/extras/Mesa/src/mesa/drivers/glide/fxsetup.c') diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/glide/fxsetup.c b/nx-X11/extras/Mesa/src/mesa/drivers/glide/fxsetup.c new file mode 100644 index 000000000..360a42f7e --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/glide/fxsetup.c @@ -0,0 +1,2217 @@ +/* + * 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 +fxDDStencilFunc (GLcontext *ctx, 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 +fxDDStencilMask (GLcontext *ctx, 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 +fxDDStencilOp (GLcontext *ctx, 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 */ -- cgit v1.2.3