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