blob: 2cc6add1d28b0d57524924116e12a8ac61ea9c49 [file] [log] [blame]
/*
* Mesa 3-D graphics library
* Version: 3.3
*
* Copyright (C) 1999-2000 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.
*
*
* Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the
* terms stated above.
*
* Thank you for your contribution, David!
*
* Please make note of the above copyright/license statement. If you
* contributed code or bug fixes to this code under the previous (GNU
* Library) license and object to the new license, your code will be
* removed at your request. Please see the Mesa docs/COPYRIGHT file
* for more information.
*
* Additional Mesa/3Dfx driver developers:
* Daryll Strauss <daryll@precisioninsight.com>
* Keith Whitwell <keith@precisioninsight.com>
*
* See fxapi.h for more revision/author details.
*/
/* 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 GLuint fxGetTexSetConfiguration(GLcontext *ctx,
struct gl_texture_object *tObj0,
struct gl_texture_object *tObj1);
static void fxSetupTextureSingleTMU_NoLock(GLcontext *ctx, GLuint textureset);
static void fxSetupDoubleTMU_NoLock(fxMesaContext fxMesa,
struct gl_texture_object *tObj0,
struct gl_texture_object *tObj1);
static void fxSetupTexture_NoLock(GLcontext *ctx);
static void fxSetupTexture(GLcontext *ctx);
static void fxSetupBlend(GLcontext *ctx);
static void fxSetupDepthTest(GLcontext *ctx);
static void fxSetupScissor(GLcontext *ctx);
static void fxSetupCull(GLcontext *ctx);
static void gl_print_fx_state_flags( const char *msg, GLuint flags);
/*static GLboolean fxMultipassBlend(struct vertex_buffer *, GLuint);*/
static GLboolean fxMultipassTexture( struct vertex_buffer *, GLuint );
static void fxTexValidate(GLcontext *ctx, struct gl_texture_object *tObj)
{
tfxTexInfo *ti=fxTMGetTexInfo(tObj);
GLint minl, maxl;
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: fxTexValidate(...) Start\n");
}
if(ti->validated) {
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: fxTexValidate(...) End (validated=GL_TRUE)\n");
}
return;
}
ti->tObj=tObj;
minl=ti->minLevel=tObj->BaseLevel;
maxl=ti->maxLevel=MIN2(tObj->MaxLevel,tObj->Image[0]->MaxLog2);
fxTexGetInfo(tObj->Image[minl]->Width, tObj->Image[minl]->Height,
&(FX_largeLodLog2(ti->info)), &(FX_aspectRatioLog2(ti->info)),
&(ti->sScale), &(ti->tScale),
&(ti->int_sScale), &(ti->int_tScale),
NULL, NULL);
if((tObj->MinFilter!=GL_NEAREST) && (tObj->MinFilter!=GL_LINEAR))
fxTexGetInfo(tObj->Image[maxl]->Width,tObj->Image[maxl]->Height,
&(FX_smallLodLog2(ti->info)),NULL,
NULL,NULL,
NULL,NULL,
NULL,NULL);
else
FX_smallLodLog2(ti->info)=FX_largeLodLog2(ti->info);
fxTexGetFormat(tObj->Image[minl]->IntFormat,&(ti->info.format),&(ti->baseLevelInternalFormat));
switch (tObj->WrapS) {
case GL_CLAMP_TO_EDGE:
/* What's this really mean compared to GL_CLAMP? */
case GL_CLAMP:
ti->sClamp=1;
break;
case GL_REPEAT:
ti->sClamp=0;
break;
default:
; /* silence compiler warning */
}
switch (tObj->WrapT) {
case GL_CLAMP_TO_EDGE:
/* What's this really mean compared to GL_CLAMP? */
case GL_CLAMP:
ti->tClamp=1;
break;
case GL_REPEAT:
ti->tClamp=0;
break;
default:
; /* silence compiler warning */
}
ti->validated=GL_TRUE;
ti->info.data=NULL;
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: fxTexValidate(...) End\n");
}
}
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 (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE))
fxPrintUnitsMode("unitsmode", 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;
/* 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 (fxMesa->freeTexMem[FX_TMU0] >
FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_BOTH,
&(ti->info))) {
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) {
if ((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->haveGlobalPaletteTexture)) {
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: uploading texture palette\n");
}
FX_grTexDownloadTable_NoLock(GR_TMU0,GR_TEXTABLE_PALETTE,&(ti->palette));
FX_grTexDownloadTable_NoLock(GR_TMU1,GR_TEXTABLE_PALETTE,&(ti->palette));
}
FX_grTexClampMode_NoLock(GR_TMU0,ti->sClamp,ti->tClamp);
FX_grTexClampMode_NoLock(GR_TMU1,ti->sClamp,ti->tClamp);
FX_grTexFilterMode_NoLock(GR_TMU0,ti->minFilt,ti->maxFilt);
FX_grTexFilterMode_NoLock(GR_TMU1,ti->minFilt,ti->maxFilt);
FX_grTexMipMapMode_NoLock(GR_TMU0,ti->mmMode,ti->LODblend);
FX_grTexMipMapMode_NoLock(GR_TMU1,ti->mmMode,ti->LODblend);
FX_grTexSource_NoLock(GR_TMU0,ti->tm[FX_TMU0]->startAddr,
GR_MIPMAPLEVELMASK_ODD,&(ti->info));
FX_grTexSource_NoLock(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;
if((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->haveGlobalPaletteTexture)) {
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: uploading texture palette\n");
}
FX_grTexDownloadTable_NoLock(tmu, GR_TEXTABLE_PALETTE, &(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 && (MESA_VERBOSE&VERBOSE_DRIVER))
fprintf(stderr, "fxmesa: not blending texture - only on one tmu\n");
FX_grTexClampMode_NoLock(tmu, ti->sClamp, ti->tClamp);
FX_grTexFilterMode_NoLock(tmu, ti->minFilt, ti->maxFilt);
FX_grTexMipMapMode_NoLock(tmu, ti->mmMode, FXFALSE);
FX_grTexSource_NoLock(tmu, ti->tm[tmu]->startAddr,
GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
}
}
static void fxSelectSingleTMUSrc_NoLock(fxMesaContext fxMesa, GLint tmu,
FxBool LODblend)
{
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: fxSelectSingleTMUSrc(%d,%d)\n",tmu,LODblend);
}
if (LODblend) {
FX_grTexCombine_NoLock(GR_TMU0,
GR_COMBINE_FUNCTION_BLEND,
GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION,
GR_COMBINE_FUNCTION_BLEND,
GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION,
FXFALSE,FXFALSE);
if (fxMesa->haveTwoTMUs)
FX_grTexCombine_NoLock(GR_TMU1,
GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
FXFALSE,FXFALSE);
fxMesa->tmuSrc=FX_TMU_SPLIT;
}
else {
if (tmu!=FX_TMU1) {
FX_grTexCombine_NoLock(GR_TMU0,
GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
FXFALSE,FXFALSE);
if (fxMesa->haveTwoTMUs) {
FX_grTexCombine_NoLock(GR_TMU1,
GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE,
FXFALSE,FXFALSE);
}
fxMesa->tmuSrc=FX_TMU0;
}
else {
FX_grTexCombine_NoLock(GR_TMU1,
GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
FXFALSE,FXFALSE);
/* GR_COMBINE_FUNCTION_SCALE_OTHER doesn't work ?!? */
FX_grTexCombine_NoLock(GR_TMU0,
GR_COMBINE_FUNCTION_BLEND,
GR_COMBINE_FACTOR_ONE,
GR_COMBINE_FUNCTION_BLEND,
GR_COMBINE_FACTOR_ONE,
FXFALSE,FXFALSE);
fxMesa->tmuSrc=FX_TMU1;
}
}
}
static void fxSetupTextureSingleTMU_NoLock(GLcontext *ctx, GLuint textureset)
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
GrCombineLocal_t localc,locala;
GLuint unitsmode;
GLint ifmt;
tfxTexInfo *ti;
struct gl_texture_object *tObj=ctx->Texture.Unit[textureset].CurrentD[2];
int tmu;
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: fxSetupTextureSingleTMU(...) Start\n");
}
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 (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE))
fprintf(stderr, "fxMesa: fxSetupTextureSingleTMU, envmode is %s\n",
gl_lookup_enum_by_nr(ctx->Texture.Unit[textureset].EnvMode));
switch(ctx->Texture.Unit[textureset].EnvMode) {
case GL_DECAL:
FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
locala,
GR_COMBINE_OTHER_NONE,
FXFALSE);
FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_BLEND,
GR_COMBINE_FACTOR_TEXTURE_ALPHA,
localc,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE);
break;
case GL_MODULATE:
FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_LOCAL,
locala,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE);
if(ifmt==GL_ALPHA)
FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
localc,
GR_COMBINE_OTHER_NONE,
FXFALSE);
else
FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_LOCAL,
localc,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE);
break;
case GL_BLEND:
#if 0
FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_LOCAL,
locala,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE);
if (ifmt==GL_ALPHA)
FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
localc,
GR_COMBINE_OTHER_NONE,
FXFALSE);
else
FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
GR_COMBINE_FACTOR_LOCAL,
localc,
GR_COMBINE_OTHER_TEXTURE,
FXTRUE);
ctx->Driver.MultipassFunc = fxMultipassBlend;
#else
if (MESA_VERBOSE&VERBOSE_DRIVER)
fprintf(stderr,"fx Driver: GL_BLEND not yet supported\n");
#endif
break;
case GL_REPLACE:
if((ifmt==GL_RGB) || (ifmt==GL_LUMINANCE))
FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
locala,
GR_COMBINE_OTHER_NONE,
FXFALSE);
else
FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_ONE,
locala,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE);
if(ifmt==GL_ALPHA)
FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
localc,
GR_COMBINE_OTHER_NONE,
FXFALSE);
else
FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_ONE,
localc,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE);
break;
default:
if (MESA_VERBOSE&VERBOSE_DRIVER)
fprintf(stderr, "fx Driver: %x Texture.EnvMode not yet supported\n",
ctx->Texture.Unit[textureset].EnvMode);
break;
}
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: fxSetupTextureSingleTMU(...) End\n");
}
}
static void fxSetupTextureSingleTMU(GLcontext *ctx, GLuint textureset) {
BEGIN_BOARD_LOCK();
fxSetupTextureSingleTMU_NoLock(ctx, textureset);
END_BOARD_LOCK();
}
/************************* 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 (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: fxSetupDoubleTMU(...)\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 */
}
}
}
if (!fxMesa->haveGlobalPaletteTexture) {
if (ti0->info.format==GR_TEXFMT_P_8) {
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: uploading texture palette TMU0\n");
}
FX_grTexDownloadTable_NoLock(tmu0, GR_TEXTABLE_PALETTE, &(ti0->palette));
}
if (ti1->info.format==GR_TEXFMT_P_8) {
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: uploading texture palette TMU1\n");
}
FX_grTexDownloadTable_NoLock(tmu1, GR_TEXTABLE_PALETTE, &(ti1->palette));
}
}
FX_grTexSource_NoLock(tmu0, ti0->tm[tmu0]->startAddr,
GR_MIPMAPLEVELMASK_BOTH, &(ti0->info));
FX_grTexClampMode_NoLock(tmu0, ti0->sClamp, ti0->tClamp);
FX_grTexFilterMode_NoLock(tmu0, ti0->minFilt, ti0->maxFilt);
FX_grTexMipMapMode_NoLock(tmu0, ti0->mmMode, FXFALSE);
FX_grTexSource_NoLock(tmu1, ti1->tm[tmu1]->startAddr,
GR_MIPMAPLEVELMASK_BOTH, &(ti1->info));
FX_grTexClampMode_NoLock(tmu1, ti1->sClamp, ti1->tClamp);
FX_grTexFilterMode_NoLock(tmu1, ti1->minFilt, ti1->maxFilt);
FX_grTexMipMapMode_NoLock(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=(fxMesaContext)ctx->DriverCtx;
GrCombineLocal_t localc,locala;
tfxTexInfo *ti0,*ti1;
struct gl_texture_object *tObj0=ctx->Texture.Unit[0].CurrentD[2];
struct gl_texture_object *tObj1=ctx->Texture.Unit[1].CurrentD[2];
GLuint envmode,ifmt,unitsmode;
int tmu0=0, tmu1=1;
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: fxSetupTextureDoubleTMU(...) Start\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 (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE))
fprintf(stderr, "fxMesa: fxSetupTextureDoubleTMU, envmode is %s/%s\n",
gl_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode),
gl_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;
switch(envmode) {
case (FX_UM_E0_MODULATE | FX_UM_E1_MODULATE):
{
GLboolean isalpha[FX_NUM_TMU];
if(ti0->baseLevelInternalFormat==GL_ALPHA)
isalpha[tmu0]=GL_TRUE;
else
isalpha[tmu0]=GL_FALSE;
if(ti1->baseLevelInternalFormat==GL_ALPHA)
isalpha[tmu1]=GL_TRUE;
else
isalpha[tmu1]=GL_FALSE;
if(isalpha[FX_TMU1])
FX_grTexCombine_NoLock(GR_TMU1,
GR_COMBINE_FUNCTION_ZERO,
GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
FXTRUE,FXFALSE);
else
FX_grTexCombine_NoLock(GR_TMU1,
GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
FXFALSE,FXFALSE);
if(isalpha[FX_TMU0])
FX_grTexCombine_NoLock(GR_TMU0,
GR_COMBINE_FUNCTION_BLEND_OTHER,
GR_COMBINE_FACTOR_ONE,
GR_COMBINE_FUNCTION_BLEND_OTHER,
GR_COMBINE_FACTOR_LOCAL,
FXFALSE,FXFALSE);
else
FX_grTexCombine_NoLock(GR_TMU0,
GR_COMBINE_FUNCTION_BLEND_OTHER,
GR_COMBINE_FACTOR_LOCAL,
GR_COMBINE_FUNCTION_BLEND_OTHER,
GR_COMBINE_FACTOR_LOCAL,
FXFALSE,FXFALSE);
FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_LOCAL,
localc,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE);
FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_LOCAL,
locala,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE);
break;
}
case (FX_UM_E0_REPLACE | FX_UM_E1_BLEND): /* Only for GLQuake */
if (tmu1==FX_TMU1) {
FX_grTexCombine_NoLock(GR_TMU1,
GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
FXTRUE,FXFALSE);
FX_grTexCombine_NoLock(GR_TMU0,
GR_COMBINE_FUNCTION_BLEND_OTHER,
GR_COMBINE_FACTOR_LOCAL,
GR_COMBINE_FUNCTION_BLEND_OTHER,
GR_COMBINE_FACTOR_LOCAL,
FXFALSE,FXFALSE);
} else {
FX_grTexCombine_NoLock(GR_TMU1,
GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
FXFALSE,FXFALSE);
FX_grTexCombine_NoLock(GR_TMU0,
GR_COMBINE_FUNCTION_BLEND_OTHER,
GR_COMBINE_FACTOR_ONE_MINUS_LOCAL,
GR_COMBINE_FUNCTION_BLEND_OTHER,
GR_COMBINE_FACTOR_ONE_MINUS_LOCAL,
FXFALSE,FXFALSE);
}
FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
locala,
GR_COMBINE_OTHER_NONE,
FXFALSE);
FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_ONE,
localc,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE);
break;
case (FX_UM_E0_REPLACE | FX_UM_E1_MODULATE): /* Quake 2 and 3 */
if (tmu1==FX_TMU1) {
FX_grTexCombine_NoLock(GR_TMU1,
GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_ZERO,
GR_COMBINE_FACTOR_NONE,
FXFALSE,FXTRUE);
FX_grTexCombine_NoLock(GR_TMU0,
GR_COMBINE_FUNCTION_BLEND_OTHER,
GR_COMBINE_FACTOR_LOCAL,
GR_COMBINE_FUNCTION_BLEND_OTHER,
GR_COMBINE_FACTOR_LOCAL,
FXFALSE,FXFALSE);
} else {
FX_grTexCombine_NoLock(GR_TMU1,
GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
FXFALSE,FXFALSE);
FX_grTexCombine_NoLock(GR_TMU0,
GR_COMBINE_FUNCTION_BLEND_OTHER,
GR_COMBINE_FACTOR_LOCAL,
GR_COMBINE_FUNCTION_BLEND_OTHER,
GR_COMBINE_FACTOR_ONE,
FXFALSE,FXFALSE);
}
if(ti0->baseLevelInternalFormat==GL_RGB)
FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
locala,
GR_COMBINE_OTHER_NONE,
FXFALSE);
else
FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_ONE,
locala,
GR_COMBINE_OTHER_NONE,
FXFALSE);
FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_ONE,
localc,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE);
break;
case (FX_UM_E0_MODULATE | FX_UM_E1_ADD): /* Quake 3 Sky */
{
GLboolean isalpha[FX_NUM_TMU];
if(ti0->baseLevelInternalFormat==GL_ALPHA)
isalpha[tmu0]=GL_TRUE;
else
isalpha[tmu0]=GL_FALSE;
if(ti1->baseLevelInternalFormat==GL_ALPHA)
isalpha[tmu1]=GL_TRUE;
else
isalpha[tmu1]=GL_FALSE;
if(isalpha[FX_TMU1])
FX_grTexCombine_NoLock(GR_TMU1,
GR_COMBINE_FUNCTION_ZERO,
GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
FXTRUE,FXFALSE);
else
FX_grTexCombine_NoLock(GR_TMU1,
GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
FXFALSE,FXFALSE);
if(isalpha[FX_TMU0])
FX_grTexCombine_NoLock(GR_TMU0,
GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_ONE,
GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
GR_COMBINE_FACTOR_ONE,
FXFALSE,FXFALSE);
else
FX_grTexCombine_NoLock(GR_TMU0,
GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
GR_COMBINE_FACTOR_ONE,
GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
GR_COMBINE_FACTOR_ONE,
FXFALSE,FXFALSE);
FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_LOCAL,
localc,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE);
FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER,
GR_COMBINE_FACTOR_LOCAL,
locala,
GR_COMBINE_OTHER_TEXTURE,
FXFALSE);
break;
}
default:
fprintf(stderr, "Unexpected dual texture mode encountered\n");
break;
}
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: fxSetupTextureDoubleTMU(...) End\n");
}
}
/************************* No Texture ***************************/
static void fxSetupTextureNone_NoLock(GLcontext *ctx)
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
GrCombineLocal_t localc,locala;
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: fxSetupTextureNone(...)\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;
FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
locala,
GR_COMBINE_OTHER_NONE,
FXFALSE);
FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL,
GR_COMBINE_FACTOR_NONE,
localc,
GR_COMBINE_OTHER_NONE,
FXFALSE);
fxMesa->lastUnitsMode=FX_UM_NONE;
}
/************************************************************************/
/************************** Texture Mode SetUp **************************/
/************************************************************************/
static void fxSetupTexture_NoLock(GLcontext *ctx)
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
GLuint tex2Denabled;
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: fxSetupTexture(...)\n");
}
/* Disable multipass texturing.
*/
ctx->Driver.MultipassFunc = 0;
/* Texture Combine, Color Combine and Alpha Combine.
*/
tex2Denabled = (ctx->Texture._ReallyEnabled & TEXTURE0_2D);
if (fxMesa->emulateTwoTMUs)
tex2Denabled |= (ctx->Texture._ReallyEnabled & TEXTURE1_2D);
switch(tex2Denabled) {
case TEXTURE0_2D:
fxSetupTextureSingleTMU_NoLock(ctx,0);
break;
case TEXTURE1_2D:
fxSetupTextureSingleTMU_NoLock(ctx,1);
break;
case (TEXTURE0_2D|TEXTURE1_2D):
if (fxMesa->haveTwoTMUs)
fxSetupTextureDoubleTMU_NoLock(ctx);
else {
if (MESA_VERBOSE&VERBOSE_DRIVER)
fprintf(stderr, "fxmesa: enabling fake multitexture\n");
fxSetupTextureSingleTMU_NoLock(ctx,0);
ctx->Driver.MultipassFunc = fxMultipassTexture;
}
break;
default:
fxSetupTextureNone_NoLock(ctx);
break;
}
}
static void fxSetupTexture(GLcontext *ctx) {
BEGIN_BOARD_LOCK();
fxSetupTexture_NoLock(ctx);
END_BOARD_LOCK();
}
/************************************************************************/
/**************************** Blend SetUp *******************************/
/************************************************************************/
/* XXX consider supporting GL_INGR_blend_func_separate */
void fxDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor)
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
tfxUnitsState *us=&fxMesa->unitsState;
GrAlphaBlendFnc_t sfact,dfact,asfact,adfact;
/* From the Glide documentation:
For alpha source and destination blend function factor
parameters, Voodoo Graphics supports only
GR_BLEND_ZERO and GR_BLEND_ONE.
*/
switch(sfactor) {
case GL_ZERO:
asfact=sfact=GR_BLEND_ZERO;
break;
case GL_ONE:
asfact=sfact=GR_BLEND_ONE;
break;
case GL_DST_COLOR:
sfact=GR_BLEND_DST_COLOR;
asfact=GR_BLEND_ONE;
break;
case GL_ONE_MINUS_DST_COLOR:
sfact=GR_BLEND_ONE_MINUS_DST_COLOR;
asfact=GR_BLEND_ONE;
break;
case GL_SRC_ALPHA:
sfact=GR_BLEND_SRC_ALPHA;
asfact=GR_BLEND_ONE;
break;
case GL_ONE_MINUS_SRC_ALPHA:
sfact=GR_BLEND_ONE_MINUS_SRC_ALPHA;
asfact=GR_BLEND_ONE;
break;
case GL_DST_ALPHA:
sfact=GR_BLEND_DST_ALPHA;
asfact=GR_BLEND_ONE;
break;
case GL_ONE_MINUS_DST_ALPHA:
sfact=GR_BLEND_ONE_MINUS_DST_ALPHA;
asfact=GR_BLEND_ONE;
break;
case GL_SRC_ALPHA_SATURATE:
sfact=GR_BLEND_ALPHA_SATURATE;
asfact=GR_BLEND_ONE;
break;
case GL_SRC_COLOR:
case GL_ONE_MINUS_SRC_COLOR:
/* USELESS */
asfact=sfact=GR_BLEND_ONE;
break;
default:
asfact=sfact=GR_BLEND_ONE;
break;
}
if((sfact!=us->blendSrcFuncRGB) ||
(asfact!=us->blendSrcFuncAlpha)) {
us->blendSrcFuncRGB=sfact;
us->blendSrcFuncAlpha=asfact;
fxMesa->new_state |= FX_NEW_BLEND;
ctx->Driver.RenderStart = fxSetupFXUnits;
}
switch(dfactor) {
case GL_ZERO:
adfact=dfact=GR_BLEND_ZERO;
break;
case GL_ONE:
adfact=dfact=GR_BLEND_ONE;
break;
case GL_SRC_COLOR:
dfact=GR_BLEND_SRC_COLOR;
adfact=GR_BLEND_ZERO;
break;
case GL_ONE_MINUS_SRC_COLOR:
dfact=GR_BLEND_ONE_MINUS_SRC_COLOR;
adfact=GR_BLEND_ZERO;
break;
case GL_SRC_ALPHA:
dfact=GR_BLEND_SRC_ALPHA;
adfact=GR_BLEND_ZERO;
break;
case GL_ONE_MINUS_SRC_ALPHA:
dfact=GR_BLEND_ONE_MINUS_SRC_ALPHA;
adfact=GR_BLEND_ZERO;
break;
case GL_DST_ALPHA:
/* dfact=GR_BLEND_DST_ALPHA; */
/* We can't do DST_ALPHA */
dfact=GR_BLEND_ONE;
adfact=GR_BLEND_ZERO;
break;
case GL_ONE_MINUS_DST_ALPHA:
/* dfact=GR_BLEND_ONE_MINUS_DST_ALPHA; */
/* We can't do DST_ALPHA */
dfact=GR_BLEND_ZERO;
adfact=GR_BLEND_ZERO;
break;
case GL_SRC_ALPHA_SATURATE:
case GL_DST_COLOR:
case GL_ONE_MINUS_DST_COLOR:
/* USELESS */
adfact=dfact=GR_BLEND_ZERO;
break;
default:
adfact=dfact=GR_BLEND_ZERO;
break;
}
if((dfact!=us->blendDstFuncRGB) ||
(adfact!=us->blendDstFuncAlpha)) {
us->blendDstFuncRGB=dfact;
us->blendDstFuncAlpha=adfact;
fxMesa->new_state |= FX_NEW_BLEND;
ctx->Driver.RenderStart = fxSetupFXUnits;
}
}
static void fxSetupBlend(GLcontext *ctx)
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
tfxUnitsState *us=&fxMesa->unitsState;
if(us->blendEnabled)
FX_grAlphaBlendFunction(us->blendSrcFuncRGB,us->blendDstFuncRGB,
us->blendSrcFuncAlpha,us->blendDstFuncAlpha);
else
FX_grAlphaBlendFunction(GR_BLEND_ONE,GR_BLEND_ZERO,GR_BLEND_ONE,GR_BLEND_ZERO);
}
/************************************************************************/
/************************** Alpha Test SetUp ****************************/
/************************************************************************/
void fxDDAlphaFunc(GLcontext *ctx, GLenum func, GLclampf ref)
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
tfxUnitsState *us=&fxMesa->unitsState;
GrCmpFnc_t newfunc;
switch(func) {
case GL_NEVER:
newfunc=GR_CMP_NEVER;
break;
case GL_LESS:
newfunc=GR_CMP_LESS;
break;
case GL_EQUAL:
newfunc=GR_CMP_EQUAL;
break;
case GL_LEQUAL:
newfunc=GR_CMP_LEQUAL;
break;
case GL_GREATER:
newfunc=GR_CMP_GREATER;
break;
case GL_NOTEQUAL:
newfunc=GR_CMP_NOTEQUAL;
break;
case GL_GEQUAL:
newfunc=GR_CMP_GEQUAL;
break;
case GL_ALWAYS:
newfunc=GR_CMP_ALWAYS;
break;
default:
fprintf(stderr,"fx Driver: internal error in fxDDAlphaFunc()\n");
fxCloseHardware();
exit(-1);
break;
}
if(newfunc!=us->alphaTestFunc) {
us->alphaTestFunc=newfunc;
fxMesa->new_state |= FX_NEW_ALPHA;
ctx->Driver.RenderStart = fxSetupFXUnits;
}
if(ctx->Color.AlphaRef!=us->alphaTestRefValue) {
us->alphaTestRefValue=ctx->Color.AlphaRef;
fxMesa->new_state |= FX_NEW_ALPHA;
ctx->Driver.RenderStart = fxSetupFXUnits;
}
}
static void fxSetupAlphaTest(GLcontext *ctx)
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
tfxUnitsState *us=&fxMesa->unitsState;
if(us->alphaTestEnabled) {
FX_grAlphaTestFunction(us->alphaTestFunc);
FX_grAlphaTestReferenceValue(us->alphaTestRefValue);
} else
FX_grAlphaTestFunction(GR_CMP_ALWAYS);
}
/************************************************************************/
/************************** Depth Test SetUp ****************************/
/************************************************************************/
void fxDDDepthFunc(GLcontext *ctx, GLenum func)
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
tfxUnitsState *us=&fxMesa->unitsState;
GrCmpFnc_t dfunc;
switch(func) {
case GL_NEVER:
dfunc=GR_CMP_NEVER;
break;
case GL_LESS:
dfunc=GR_CMP_LESS;
break;
case GL_GEQUAL:
dfunc=GR_CMP_GEQUAL;
break;
case GL_LEQUAL:
dfunc=GR_CMP_LEQUAL;
break;
case GL_GREATER:
dfunc=GR_CMP_GREATER;
break;
case GL_NOTEQUAL:
dfunc=GR_CMP_NOTEQUAL;
break;
case GL_EQUAL:
dfunc=GR_CMP_EQUAL;
break;
case GL_ALWAYS:
dfunc=GR_CMP_ALWAYS;
break;
default:
fprintf(stderr,"fx Driver: internal error in fxDDDepthFunc()\n");
fxCloseHardware();
exit(-1);
break;
}
if(dfunc!=us->depthTestFunc) {
us->depthTestFunc=dfunc;
fxMesa->new_state |= FX_NEW_DEPTH;
ctx->Driver.RenderStart = fxSetupFXUnits;
}
}
void fxDDDepthMask(GLcontext *ctx, GLboolean flag)
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
tfxUnitsState *us=&fxMesa->unitsState;
if(flag!=us->depthMask) {
us->depthMask=flag;
fxMesa->new_state |= FX_NEW_DEPTH;
ctx->Driver.RenderStart = fxSetupFXUnits;
}
}
static void fxSetupDepthTest(GLcontext *ctx)
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
tfxUnitsState *us=&fxMesa->unitsState;
if (us->depthTestEnabled) {
FX_grDepthBufferFunction(us->depthTestFunc);
FX_grDepthMask(us->depthMask);
}
else {
FX_grDepthBufferFunction(GR_CMP_ALWAYS);
FX_grDepthMask(FXFALSE);
}
}
/************************************************************************/
/**************************** Color Mask SetUp **************************/
/************************************************************************/
void fxDDColorMask(GLcontext *ctx,
GLboolean r, GLboolean g,
GLboolean b, GLboolean a )
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
fxMesa->new_state |= FX_NEW_COLOR_MASK;
ctx->Driver.RenderStart = fxSetupFXUnits;
(void) r; (void) g; (void) b; (void) a;
}
static void fxSetupColorMask(GLcontext *ctx)
{
fxMesaContext fxMesa = FX_CONTEXT(ctx);
if (ctx->Color.DrawBuffer == GL_NONE) {
FX_grColorMask(FXFALSE, FXFALSE);
}
else {
FX_grColorMask(ctx->Color.ColorMask[RCOMP] ||
ctx->Color.ColorMask[GCOMP] ||
ctx->Color.ColorMask[BCOMP],
ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer);
}
}
/************************************************************************/
/**************************** 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]);
FX_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;
}
FX_grFogTable(fxMesa->fogTable);
FX_grFogMode(GR_FOG_WITH_TABLE);
}
else {
FX_grFogMode(GR_FOG_DISABLE);
}
}
void fxDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
{
FX_CONTEXT(ctx)->new_state |= FX_NEW_FOG;
ctx->Driver.RenderStart = fxSetupFXUnits; /* XXX why is this here? */
}
/************************************************************************/
/************************** Scissor Test SetUp **************************/
/************************************************************************/
/* This routine is used in managing the lock state, and therefore can't lock */
void fxSetScissorValues(GLcontext *ctx)
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
int xmin, xmax;
int ymin, ymax, check;
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;
check=1;
} else {
xmin=0;
ymin=0;
xmax=fxMesa->width;
ymax=fxMesa->height;
check=0;
}
if (xmin<fxMesa->clipMinX) xmin=fxMesa->clipMinX;
if (xmax>fxMesa->clipMaxX) xmax=fxMesa->clipMaxX;
if (ymin<fxMesa->screen_height-fxMesa->clipMaxY)
ymin=fxMesa->screen_height-fxMesa->clipMaxY;
if (ymax>fxMesa->screen_height-fxMesa->clipMinY)
ymax=fxMesa->screen_height-fxMesa->clipMinY;
FX_grClipWindow_NoLock(xmin, ymin, xmax, ymax);
}
static 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;
ctx->Driver.RenderStart = fxSetupFXUnits;
}
/************************************************************************/
/*************************** Cull mode setup ****************************/
/************************************************************************/
void fxDDCullFace(GLcontext *ctx, GLenum mode)
{
(void) mode;
FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL;
ctx->Driver.RenderStart = fxSetupFXUnits;
}
void fxDDFrontFace(GLcontext *ctx, GLenum mode)
{
(void) mode;
FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL;
ctx->Driver.RenderStart = fxSetupFXUnits;
}
static void fxSetupCull(GLcontext *ctx)
{
if (ctx->Polygon.CullFlag) {
switch (ctx->Polygon.CullFaceMode) {
case GL_BACK:
if (ctx->Polygon.FrontFace==GL_CCW)
FX_CONTEXT(ctx)->cullMode=GR_CULL_NEGATIVE;
else
FX_CONTEXT(ctx)->cullMode=GR_CULL_POSITIVE;
break;
case GL_FRONT:
if(ctx->Polygon.FrontFace==GL_CCW)
FX_CONTEXT(ctx)->cullMode=GR_CULL_POSITIVE;
else
FX_CONTEXT(ctx)->cullMode=GR_CULL_NEGATIVE;
break;
case GL_FRONT_AND_BACK:
FX_CONTEXT(ctx)->cullMode=GR_CULL_DISABLE;
break;
default:
break;
}
} else FX_CONTEXT(ctx)->cullMode=GR_CULL_DISABLE;
FX_grCullMode(FX_CONTEXT(ctx)->cullMode);
}
/************************************************************************/
/****************************** DD Enable ******************************/
/************************************************************************/
void fxDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
tfxUnitsState *us=&fxMesa->unitsState;
if (MESA_VERBOSE&VERBOSE_DRIVER) {
fprintf(stderr,"fxmesa: fxDDEnable(...)\n");
}
switch(cap) {
case GL_ALPHA_TEST:
if(state!=us->alphaTestEnabled) {
us->alphaTestEnabled=state;
fxMesa->new_state |= FX_NEW_ALPHA;
ctx->Driver.RenderStart = fxSetupFXUnits;
}
break;
case GL_BLEND:
if(state!=us->blendEnabled) {
us->blendEnabled=state;
fxMesa->new_state |= FX_NEW_BLEND;
ctx->Driver.RenderStart = fxSetupFXUnits;
}
break;
case GL_DEPTH_TEST:
if(state!=us->depthTestEnabled) {
us->depthTestEnabled=state;
fxMesa->new_state |= FX_NEW_DEPTH;
ctx->Driver.RenderStart = fxSetupFXUnits;
}
break;
case GL_DITHER:
if (state) {
FX_grDitherMode(GR_DITHER_4x4);
} else {
FX_grDitherMode(GR_DITHER_DISABLE);
}
break;
case GL_SCISSOR_TEST:
fxMesa->new_state |= FX_NEW_SCISSOR;
ctx->Driver.RenderStart = fxSetupFXUnits;
break;
case GL_SHARED_TEXTURE_PALETTE_EXT:
fxDDTexUseGlbPalette(ctx, state);
break;
case GL_FOG:
fxMesa->new_state |= FX_NEW_FOG;
ctx->Driver.RenderStart = fxSetupFXUnits;
break;
case GL_CULL_FACE:
fxMesa->new_state |= FX_NEW_CULL;
ctx->Driver.RenderStart = fxSetupFXUnits;
break;
case GL_LINE_SMOOTH:
case GL_LINE_STIPPLE:
case GL_POINT_SMOOTH:
case GL_POLYGON_SMOOTH:
case GL_TEXTURE_2D:
fxMesa->new_state |= FX_NEW_TEXTURING;
ctx->Driver.RenderStart = fxSetupFXUnits;
break;
default:
; /* XXX no-op? */
}
}
#if 0
/*
Multipass to do GL_BLEND texture functions
Cf*(1-Ct) has already been written to the buffer during the first pass
Cc*Ct gets written during the second pass (in this function)
Everything gets reset in the third call (in this function)
*/
static GLboolean fxMultipassBlend(struct vertex_buffer *VB, GLuint pass)
{
GLcontext *ctx = VB->ctx;
fxMesaContext fxMesa = FX_CONTEXT(ctx);
switch (pass) {
case 1:
/* Add Cc*Ct */
fxMesa->restoreUnitsState=fxMesa->unitsState;
if (ctx->Depth.Mask) {
/* We don't want to check or change the depth buffers */
switch (ctx->Depth.Func) {
case GL_NEVER:
case GL_ALWAYS:
break;
default:
fxDDDepthFunc(ctx, GL_EQUAL);
break;
}
fxDDDepthMask(ctx, FALSE);
}
/* Enable Cc*Ct mode */
/* XXX Set the Constant Color ? */
fxDDEnable(ctx, GL_BLEND, GL_TRUE);
fxDDBlendFunc(ctx, XXX, XXX);
fxSetupTextureSingleTMU(ctx, XXX);
fxSetupBlend(ctx);
fxSetupDepthTest(ctx);
break;
case 2:
/* Reset everything back to normal */
fxMesa->unitsState = fxMesa->restoreUnitsState;
fxMesa->setupdone &= XXX;
fxSetupTextureSingleTMU(ctx, XXX);
fxSetupBlend(ctx);
fxSetupDepthTest(ctx);
break;
}
return pass==1;
}
#endif
/************************************************************************/
/******************** Fake Multitexture Support *************************/
/************************************************************************/
/* Its considered cheeky to try to fake ARB multitexture by doing
* multipass rendering, because it is not possible to emulate the full
* spec in this way. The fact is that the voodoo 2 supports only a
* subset of the possible multitexturing modes, and it is possible to
* support almost the same subset using multipass blending on the
* voodoo 1. In all other cases for both voodoo 1 and 2, we fall back
* to software rendering, satisfying the spec if not the user.
*/
static GLboolean fxMultipassTexture( struct vertex_buffer *VB, GLuint pass )
{
GLcontext *ctx = VB->ctx;
fxVertex *v = FX_DRIVER_DATA(VB)->verts;
fxVertex *last = FX_DRIVER_DATA(VB)->last_vert;
fxMesaContext fxMesa = FX_CONTEXT(ctx);
switch (pass) {
case 1:
if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_PIPELINE|VERBOSE_TEXTURE))
fprintf(stderr, "fxmesa: Second texture pass\n");
for ( ; v != last ; v++) {
v->f[S0COORD] = v->f[S1COORD];
v->f[T0COORD] = v->f[T1COORD];
}
fxMesa->restoreUnitsState = fxMesa->unitsState;
fxMesa->tmu_source[0] = 1;
if (ctx->Depth.Mask) {
switch (ctx->Depth.Func) {
case GL_NEVER:
case GL_ALWAYS:
break;
default:
fxDDDepthFunc( ctx, GL_EQUAL );
break;
}
fxDDDepthMask( ctx, GL_FALSE );
}
if (ctx->Texture.Unit[1].EnvMode == GL_MODULATE) {
fxDDEnable( ctx, GL_BLEND, GL_TRUE );
fxDDBlendFunc( ctx, GL_DST_COLOR, GL_ZERO );
}
fxSetupTextureSingleTMU( ctx, 1 );
fxSetupBlend( ctx );
fxSetupDepthTest( ctx );
break;
case 2:
/* Restore original state.
*/
fxMesa->tmu_source[0] = 0;
fxMesa->unitsState = fxMesa->restoreUnitsState;
fxMesa->setupdone &= ~SETUP_TMU0;
fxSetupTextureSingleTMU( ctx, 0 );
fxSetupBlend( ctx );
fxSetupDepthTest( ctx );
break;
}
return pass == 1;
}
/************************************************************************/
/************************** 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;
ctx->Driver.RenderStart = fxSetupFXUnits;
}
/************************************************************************/
/****************************** Units SetUp *****************************/
/************************************************************************/
static void gl_print_fx_state_flags( const char *msg, GLuint flags )
{
fprintf(stderr,
"%s: (0x%x) %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, " : "");
}
void fxSetupFXUnits( GLcontext *ctx )
{
fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
GLuint newstate = fxMesa->new_state;
if (MESA_VERBOSE&VERBOSE_DRIVER)
gl_print_fx_state_flags("fxmesa: 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_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->draw_point = fxMesa->initial_point;
fxMesa->draw_line = fxMesa->initial_line;
fxMesa->draw_tri = fxMesa->initial_tri;
fxMesa->new_state = 0;
}
}
#else
/*
* Need this to provide at least one external definition.
*/
int gl_fx_dummy_function_setup(void)
{
return 0;
}
#endif /* FX */