/* * 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/t_context.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 1||FX_RESCALE_BIG_TEXURES { extern void _mesa_rescale_teximage2d( GLuint bytesPerPixel, GLuint dstRowStride, GLint srcWidth, GLint srcHeight, GLint dstWidth, GLint dstHeight, const GLvoid *srcImage, GLvoid *dstImage ); fxMesaContext fxMesa = FX_CONTEXT(ctx); if (maxl - minl > fxMesa->textureMaxLod) { /* [dBorca] * Ooooooook! Here's a(nother) long story. * We get here because we need to handle a texture larger * than hardware can support. Two cases: * 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 texture; two ways: * a) create a new LOD and push up ti->minLevel and tObj->BaseLevel * but this means we need to rescale on both axes, which * yield unnecessary ugly texture. Also, same issues as 1) * b) rescale the biggest LOD in place and go two ways: * - update texImage->Width and texImage->Height, then * decrease maxLevel, so we won't rescale again on the * next validation. Changing texImage-> parameters is * not quite legal here (see convolution), but... * - leaving texImage-> parameters alone, while rescaling * texture and decreasing maxLevel makes Mesa puke. Also * this approach requires that mml->[wh]Scale go below 1, * otherwise bad ju-ju will be in our future (see fetch_texel) * Will this interfere with GL_TEXTURE_MAX_LEVEL? How? * 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. * NB: we could handle mml->[wh]Scale nicely, using (biased) shifts. * * Which brings me to another issue. How can we handle NPOT textures? * - rescaling NPOT to the next bigger POT (mml->[wh]Scale can't shift) * - upping the max LOD to the next power-of-two, in fxTexGetInfo; then * choosing non-power-of-two values for ti->[st]Scale... Anyhow, we * still need to align mipmaps correctly in texture memory! */ if ((tObj->MinFilter == GL_NEAREST) || (tObj->MinFilter == GL_LINEAR)) { /* no mipmaps! need to rescale */ struct gl_texture_image *texImage = tObj->Image[0][minl]; tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage); GLint texelBytes = texImage->TexFormat->TexelBytes; GLvoid *texImage_Data = texImage->Data; GLint _w = MIN2(mml->width, 1 << fxMesa->textureMaxLod); GLint _h = MIN2(mml->height, 1 << fxMesa->textureMaxLod); if (TDFX_DEBUG & VERBOSE_TEXTURE) { fprintf(stderr, "fxTexValidate: rescaling %d x %d -> %d x %d\n", mml->width, mml->height, _w, _h); } fxTexGetInfo(_w, _h, NULL, NULL, NULL, NULL, &(mml->wScale), &(mml->hScale)); texImage->Width = _w / mml->wScale; texImage->Height = _h / mml->hScale; texImage->Data = MESA_PBUFFER_ALLOC(_w * _h * texelBytes); _mesa_rescale_teximage2d(texelBytes, _w * texelBytes, /* dst stride */ mml->width, mml->height, /* src */ _w, _h, /* dst */ texImage_Data /*src*/, texImage->Data /*dst*/ ); MESA_PBUFFER_FREE(texImage_Data); mml->width = _w; mml->height = _h; maxl = ti->maxLevel = tObj->Image[0][0]->MaxLog2 = minl + fxMesa->textureMaxLod; } else { /* 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); 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); } #if 1 /* [dBorca] Good... bad... I'm the guy with the gun! */ ti->lastTimeUsed = fxMesa->texBindNumber; #endif /* 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)); } #if FX_TC_NCC if ((ti->info.format == GR_TEXFMT_AYIQ_8422) || (ti->info.format == GR_TEXFMT_YIQ_422)) { if (TDFX_DEBUG & VERBOSE_DRIVER) { fprintf(stderr, "fxSetupSingleTMU_NoLock: uploading NCC table\n"); } grTexDownloadTable(GR_TEXTABLE_NCC0, &(ti->palette)); } #endif 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)); } #if FX_TC_NCC if ((ti->info.format == GR_TEXFMT_AYIQ_8422) || (ti->info.format == GR_TEXFMT_YIQ_422)) { if (TDFX_DEBUG & VERBOSE_DRIVER) { fprintf(stderr, "fxSetupSingleTMU_NoLock: uploading NCC table\n"); } fxMesa->Glide.grTexDownloadTableExt(tmu, GR_TEXTABLE_NCC0, &(ti->palette)); } #endif /* 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; /* [dBorca] Hack alert: * don't use GR_COMBINE_FUNCTION_SCALE_OTHER * such that Glide recognizes 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 { /* [dBorca] Hack alert: * only Voodoo^2 can GL_BLEND (GR_COMBINE_FACTOR_TEXTURE_RGB) */ 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 { _mesa_problem(NULL, "can't GL_BLEND with SST1"); return; } } 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)); } } #if FX_TC_NCC /* pointcast */ if ((ti1->info.format == GR_TEXFMT_AYIQ_8422) || (ti1->info.format == GR_TEXFMT_YIQ_422)) { if (TDFX_DEBUG & VERBOSE_DRIVER) { fprintf(stderr, "fxSetupDoubleTMU_NoLock: uploading NCC0 table for TMU1\n"); } fxMesa->Glide.grTexDownloadTableExt(ti1->whichTMU, GR_TEXTABLE_NCC0, &(ti1->palette)); } if ((ti0->info.format == GR_TEXFMT_AYIQ_8422) || (ti0->info.format == GR_TEXFMT_YIQ_422)) { if (TDFX_DEBUG & VERBOSE_DRIVER) { fprintf(stderr, "fxSetupDoubleTMU_NoLock: uploading NCC0 table for TMU0\n"); } fxMesa->Glide.grTexDownloadTableExt(ti0->whichTMU, GR_TEXTABLE_NCC0, &(ti0->palette)); } #endif 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; } 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 have32bpp = (fxMesa->colDepth == 32); GLboolean haveAlpha = fxMesa->haveHwAlpha; GrAlphaBlendFnc_t sfact, dfact, asfact, adfact; /* [dBorca] Hack alert: * We should condition *DST_ALPHA* modes * by the boolean `haveAlpha' above! * It indicates whether we really have HW alpha buffer... */ /* When the value A_COLOR is selected as the destination alpha blending factor, the source pixel color is used as the destination blending factor. When the value A_COLOR is selected as the source alpha blending factor, the destination pixel color is used as the source blending factor. When the value A_SAMECOLOR is selected as the destination alpha blending factor, the destination pixel color is used as the destination blending factor. When the value A_SAMECOLOR is selected as the source alpha blending factor, the source pixel color is used as the source blending factor. Note also that the alpha blending function 0xf (A_COLORBEFOREFOG/ASATURATE) is different depending upon whether it is being used as a source or destination alpha blending function. When the value 0xf is selected as the destination alpha blending factor, the source color before the fog unit ("unfogged" color) is used as the destination blending factor -- this alpha blending function is useful for multi-pass rendering with atmospheric effects. When the value 0xf is selected as the source alpha blending factor, the alpha-saturate anti-aliasing algorithm is selected -- this MIN function performs polygonal anti-aliasing for polygons which are drawn front-to-back. 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 */ 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 = GR_BLEND_DST_ALPHA; break; case GL_ONE_MINUS_DST_ALPHA: sfact = GR_BLEND_ONE_MINUS_DST_ALPHA; break; case GL_SRC_ALPHA_SATURATE: sfact = GR_BLEND_ALPHA_SATURATE; break; case GL_SRC_COLOR: case GL_ONE_MINUS_SRC_COLOR: /* USELESS */ sfact = GR_BLEND_ONE; 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_DST_COLOR: asfact = GR_BLEND_ONE/*bad*/; break; case GL_ONE_MINUS_DST_COLOR: asfact = GR_BLEND_ONE/*bad*/; break; case GL_SRC_ALPHA: asfact = have32bpp ? GR_BLEND_SRC_ALPHA : GR_BLEND_ONE/*bad*/; break; case GL_ONE_MINUS_SRC_ALPHA: asfact = have32bpp ? GR_BLEND_ONE_MINUS_SRC_ALPHA : GR_BLEND_ONE/*bad*/; break; case GL_DST_ALPHA: asfact = have32bpp ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE/*bad*/; break; case GL_ONE_MINUS_DST_ALPHA: asfact = have32bpp ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ONE/*bad*/; break; case GL_SRC_ALPHA_SATURATE: asfact = GR_BLEND_ONE/*bad*/; break; case GL_SRC_COLOR: case GL_ONE_MINUS_SRC_COLOR: /* USELESS */ asfact = GR_BLEND_ONE/*bad*/; break; default: asfact = GR_BLEND_ONE/*bad*/; 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=GR_BLEND_DST_ALPHA; */ /* We can't do DST_ALPHA */ dfact = GR_BLEND_ONE; break; case GL_ONE_MINUS_DST_ALPHA: /* dfact=GR_BLEND_ONE_MINUS_DST_ALPHA; */ /* We can't do DST_ALPHA */ dfact = GR_BLEND_ZERO; break; case GL_SRC_ALPHA_SATURATE: case GL_DST_COLOR: case GL_ONE_MINUS_DST_COLOR: /* USELESS */ dfact = GR_BLEND_ZERO; 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: adfact = GR_BLEND_ZERO/*bad*/; break; case GL_ONE_MINUS_SRC_COLOR: adfact = GR_BLEND_ZERO/*bad*/; break; case GL_SRC_ALPHA: adfact = have32bpp ? GR_BLEND_SRC_ALPHA : GR_BLEND_ZERO/*bad*/; break; case GL_ONE_MINUS_SRC_ALPHA: adfact = have32bpp ? GR_BLEND_ONE_MINUS_SRC_ALPHA : GR_BLEND_ZERO/*bad*/; break; case GL_DST_ALPHA: adfact = have32bpp ? GR_BLEND_DST_ALPHA : GR_BLEND_ZERO/*bad*/; break; case GL_ONE_MINUS_DST_ALPHA: adfact = have32bpp ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO/*bad*/; break; case GL_SRC_ALPHA_SATURATE: case GL_DST_COLOR: case GL_ONE_MINUS_DST_COLOR: /* USELESS */ adfact = GR_BLEND_ZERO/*bad*/; break; default: adfact = GR_BLEND_ZERO/*bad*/; 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; assert( modeRGB == modeA ); 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: return; } if ((q != us->blendEq) && fxMesa->HavePixExt) { us->blendEq = 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->blendEq, us->blendSrcFuncAlpha, us->blendDstFuncAlpha, us->blendEq); } 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 ( (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 (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 ( (us->stencilFailFunc != sfail) || (us->stencilZFailFunc != zfail) || (us->stencilZPassFunc != zpass) ) { us->stencilFailFunc = sfail; us->stencilZFailFunc = zfail; us->stencilZPassFunc = zpass; fxMesa->new_state |= FX_NEW_STENCIL; } } static void fxSetupStencil (GLcontext * ctx) { fxMesaContext fxMesa = FX_CONTEXT(ctx); tfxUnitsState *us = &fxMesa->unitsState; if (us->stencilEnabled) { grEnable(GR_STENCIL_MODE_EXT); fxMesa->Glide.grStencilOpExt(convertGLStencilOp(us->stencilFailFunc), convertGLStencilOp(us->stencilZFailFunc), convertGLStencilOp(us->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); } } /************************************************************************/ /**************************** 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 != 16) { /* 32bpp mode or 15bpp mode */ fxMesa->Glide.grColorMaskExt(ctx->Color.ColorMask[RCOMP], ctx->Color.ColorMask[GCOMP], ctx->Color.ColorMask[BCOMP], ctx->Color.ColorMask[ACOMP] && fxMesa->haveHwAlpha); } else { /* 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); 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); 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; } /************************************************************************/ /************************** 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 */