/* -*- mode: C; tab-width:8; -*- fxsetup.c - 3Dfx VooDoo rendering mode setup functions */ /* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * See the file fxapi.c for more informations about authors * */ #ifdef HAVE_CONFIG_H #include "conf.h" #endif #if defined(FX) #include "fxdrv.h" #include "enums.h" static void fxTexValidate(GLcontext *ctx, struct gl_texture_object *tObj) { tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData; 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; } 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]->Format,&(ti->info.format),&(ti->baseLevelInternalFormat)); 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, " : ""); } 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) || (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) unitsmode|=FX_UM_COLOR_ITERATED; else unitsmode|=FX_UM_COLOR_CONSTANT; if(tObj0) { tfxTexInfo *ti0=(tfxTexInfo *)tObj0->DriverData; 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; default: /* do nothing */ break; } } if(tObj1) { tfxTexInfo *ti1=(tfxTexInfo *)tObj1->DriverData; 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; 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(fxMesaContext fxMesa, struct gl_texture_object *tObj) { tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData; if(!ti->tmi.isInTM) { if(ti->LODblend) fxTMMoveInTM(fxMesa,tObj,FX_TMU_SPLIT); else { if(fxMesa->haveTwoTMUs) { if(fxMesa->freeTexMem[FX_TMU0]>grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,&(ti->info))) fxTMMoveInTM(fxMesa,tObj,FX_TMU0); else fxTMMoveInTM(fxMesa,tObj,FX_TMU1); } else fxTMMoveInTM(fxMesa,tObj,FX_TMU0); } } if(ti->LODblend && ti->tmi.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(GR_TMU0,GR_TEXTABLE_PALETTE,&(ti->palette)); FX_grTexDownloadTable(GR_TMU1,GR_TEXTABLE_PALETTE,&(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->tmi.tm[FX_TMU0]->startAddress, GR_MIPMAPLEVELMASK_ODD,&(ti->info)); grTexSource(GR_TMU1,ti->tmi.tm[FX_TMU1]->startAddress, GR_MIPMAPLEVELMASK_EVEN,&(ti->info)); } else { if((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->haveGlobalPaletteTexture)) { if (MESA_VERBOSE&VERBOSE_DRIVER) { fprintf(stderr,"fxmesa: uploading texture palette\n"); } FX_grTexDownloadTable(ti->tmi.whichTMU,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"); grTexClampMode(ti->tmi.whichTMU,ti->sClamp,ti->tClamp); grTexFilterMode(ti->tmi.whichTMU,ti->minFilt,ti->maxFilt); grTexMipMapMode(ti->tmi.whichTMU,ti->mmMode,FXFALSE); grTexSource(ti->tmi.whichTMU,ti->tmi.tm[ti->tmi.whichTMU]->startAddress, GR_MIPMAPLEVELMASK_BOTH,&(ti->info)); } } static void fxSelectSingleTMUSrc(fxMesaContext fxMesa, GLint tmu, FxBool LODblend) { if (MESA_VERBOSE&VERBOSE_DRIVER) { fprintf(stderr,"fxmesa: fxSelectSingleTMUSrc(%d,%d)\n",tmu,LODblend); } if(LODblend) { grTexCombine(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); grTexCombine(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_TMU0) { grTexCombine(GR_TMU0, GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, FXFALSE,FXFALSE); fxMesa->tmuSrc=FX_TMU0; } else { grTexCombine(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 ?!? */ grTexCombine(GR_TMU0, GR_COMBINE_FUNCTION_BLEND,GR_COMBINE_FACTOR_ONE, GR_COMBINE_FUNCTION_BLEND,GR_COMBINE_FACTOR_ONE, FXFALSE,FXFALSE); fxMesa->tmuSrc=FX_TMU1; } } } void fxSetupTextureSingleTMU(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]; if (MESA_VERBOSE&VERBOSE_DRIVER) { fprintf(stderr,"fxmesa: fxSetupTextureSingleTMU(...) Start\n"); } ti=(tfxTexInfo *)tObj->DriverData; fxTexValidate(ctx,tObj); fxSetupSingleTMU(fxMesa,tObj); if(fxMesa->tmuSrc!=ti->tmi.whichTMU) fxSelectSingleTMUSrc(fxMesa,ti->tmi.whichTMU,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(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: grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, locala, GR_COMBINE_OTHER_NONE, FXFALSE); grColorCombine(GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_TEXTURE_ALPHA, localc, GR_COMBINE_OTHER_TEXTURE, FXFALSE); break; case GL_MODULATE: grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, locala, GR_COMBINE_OTHER_TEXTURE, FXFALSE); if(ifmt==GL_ALPHA) grColorCombine(GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, localc, GR_COMBINE_OTHER_NONE, FXFALSE); else grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, localc, GR_COMBINE_OTHER_TEXTURE, FXFALSE); break; case GL_BLEND: #ifndef FX_SILENT fprintf(stderr,"fx Driver: GL_BLEND not yet supported\n"); #endif /* TO DO (I think that the Voodoo Graphics isn't able to support GL_BLEND) */ break; case GL_REPLACE: if((ifmt==GL_RGB) || (ifmt==GL_LUMINANCE)) grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, locala, GR_COMBINE_OTHER_NONE, FXFALSE); else grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, locala, GR_COMBINE_OTHER_TEXTURE, FXFALSE); if(ifmt==GL_ALPHA) grColorCombine(GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, localc, GR_COMBINE_OTHER_NONE, FXFALSE); else grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, localc, GR_COMBINE_OTHER_TEXTURE, FXFALSE); break; default: #ifndef FX_SILENT fprintf(stderr,"fx Driver: %x Texture.EnvMode not yet supported\n",ctx->Texture.Unit[textureset].EnvMode); #endif break; } if (MESA_VERBOSE&VERBOSE_DRIVER) { fprintf(stderr,"fxmesa: fxSetupTextureSingleTMU(...) End\n"); } } /************************* Double Texture Set ***************************/ void fxSetupDoubleTMU(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=(tfxTexInfo *)tObj0->DriverData; tfxTexInfo *ti1=(tfxTexInfo *)tObj1->DriverData; GLuint tstate=0; if (MESA_VERBOSE&VERBOSE_DRIVER) { fprintf(stderr,"fxmesa: fxSetupDoubleTMU(...)\n"); } if(ti0->tmi.isInTM) { if(ti0->tmi.whichTMU==FX_TMU0) tstate|=T0_IN_TMU0; else if(ti0->tmi.whichTMU==FX_TMU1) tstate|=T0_IN_TMU1; else { fxTMMoveOutTM(fxMesa,tObj0); tstate|=T0_NOT_IN_TMU; } } else tstate|=T0_NOT_IN_TMU; if(ti1->tmi.isInTM) { if(ti1->tmi.whichTMU==FX_TMU0) tstate|=T1_IN_TMU0; else if(ti1->tmi.whichTMU==FX_TMU1) tstate|=T1_IN_TMU1; else { fxTMMoveOutTM(fxMesa,tObj1); tstate|=T1_NOT_IN_TMU; } } else tstate|=T1_NOT_IN_TMU; ti0->tmi.lastTimeUsed=fxMesa->texBindNumber; ti1->tmi.lastTimeUsed=fxMesa->texBindNumber; /* Move texture maps in TMUs */ switch(tstate) { case (T0_IN_TMU0 | T1_IN_TMU0): fxTMMoveOutTM(fxMesa,tObj1); fxTMMoveInTM(fxMesa,tObj1,FX_TMU1); break; case (T0_IN_TMU1 | T1_IN_TMU1): fxTMMoveOutTM(fxMesa,tObj0); fxTMMoveInTM(fxMesa,tObj0,FX_TMU0); break; case (T0_NOT_IN_TMU | T1_NOT_IN_TMU): fxTMMoveInTM(fxMesa,tObj0,FX_TMU0); fxTMMoveInTM(fxMesa,tObj1,FX_TMU1); break; /*** T0/T1 ***/ case (T0_NOT_IN_TMU | T1_IN_TMU0): fxTMMoveInTM(fxMesa,tObj0,FX_TMU1); break; case (T0_NOT_IN_TMU | T1_IN_TMU1): fxTMMoveInTM(fxMesa,tObj0,FX_TMU0); break; case (T0_IN_TMU0 | T1_NOT_IN_TMU): fxTMMoveInTM(fxMesa,tObj1,FX_TMU1); break; case (T0_IN_TMU1 | T1_NOT_IN_TMU): fxTMMoveInTM(fxMesa,tObj1,FX_TMU0); break; /*** Best Case ***/ case (T0_IN_TMU1 | T1_IN_TMU0): case (T0_IN_TMU0 | T1_IN_TMU1): break; default: fprintf(stderr,"fx Driver: internal error in fxSetupDoubleTMU()\n"); fxCloseHardware(); exit(-1); break; } 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(ti0->tmi.whichTMU,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(ti1->tmi.whichTMU,GR_TEXTABLE_PALETTE,&(ti1->palette)); } } grTexClampMode(ti0->tmi.whichTMU,ti0->sClamp,ti0->tClamp); grTexFilterMode(ti0->tmi.whichTMU,ti0->minFilt,ti0->maxFilt); grTexMipMapMode(ti0->tmi.whichTMU,ti0->mmMode,FXFALSE); grTexSource(ti0->tmi.whichTMU,ti0->tmi.tm[ti0->tmi.whichTMU]->startAddress, GR_MIPMAPLEVELMASK_BOTH,&(ti0->info)); grTexClampMode(ti1->tmi.whichTMU,ti1->sClamp,ti1->tClamp); grTexFilterMode(ti1->tmi.whichTMU,ti1->minFilt,ti1->maxFilt); grTexMipMapMode(ti1->tmi.whichTMU,ti1->mmMode,FXFALSE); grTexSource(ti1->tmi.whichTMU,ti1->tmi.tm[ti1->tmi.whichTMU]->startAddress, GR_MIPMAPLEVELMASK_BOTH,&(ti1->info)); #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(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; if (MESA_VERBOSE&VERBOSE_DRIVER) { fprintf(stderr,"fxmesa: fxSetupTextureDoubleTMU(...) Start\n"); } ti0=(tfxTexInfo *)tObj0->DriverData; fxTexValidate(ctx,tObj0); ti1=(tfxTexInfo *)tObj1->DriverData; fxTexValidate(ctx,tObj1); fxSetupDoubleTMU(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(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)); 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[ti0->tmi.whichTMU]=GL_TRUE; else isalpha[ti0->tmi.whichTMU]=GL_FALSE; if(ti1->baseLevelInternalFormat==GL_ALPHA) isalpha[ti1->tmi.whichTMU]=GL_TRUE; else isalpha[ti1->tmi.whichTMU]=GL_FALSE; if(isalpha[FX_TMU1]) grTexCombine(GR_TMU1, GR_COMBINE_FUNCTION_ZERO,GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, FXTRUE,FXFALSE); else grTexCombine(GR_TMU1, GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, FXFALSE,FXFALSE); if(isalpha[FX_TMU0]) grTexCombine(GR_TMU0, GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE, GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, FXFALSE,FXFALSE); else grTexCombine(GR_TMU0, GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, FXFALSE,FXFALSE); grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, localc, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaCombine(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(ti1->tmi.whichTMU==FX_TMU1) { grTexCombine(GR_TMU1, GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, FXTRUE,FXFALSE); grTexCombine(GR_TMU0, GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, FXFALSE,FXFALSE); } else { grTexCombine(GR_TMU1, GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, FXFALSE,FXFALSE); grTexCombine(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); } grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, locala, GR_COMBINE_OTHER_NONE, FXFALSE); grColorCombine(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(ti1->tmi.whichTMU==FX_TMU1) { grTexCombine(GR_TMU1, GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_ZERO,GR_COMBINE_FACTOR_NONE, FXFALSE,FXTRUE); grTexCombine(GR_TMU0, GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL, FXFALSE,FXFALSE); } else { grTexCombine(GR_TMU1, GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE, FXFALSE,FXFALSE); grTexCombine(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) grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, locala, GR_COMBINE_OTHER_NONE, FXFALSE); else grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, locala, GR_COMBINE_OTHER_NONE, FXFALSE); grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, localc, GR_COMBINE_OTHER_TEXTURE, FXFALSE); break; } if (MESA_VERBOSE&VERBOSE_DRIVER) { fprintf(stderr,"fxmesa: fxSetupTextureDoubleTMU(...) End\n"); } } /************************* No Texture ***************************/ static void fxSetupTextureNone(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) || (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) 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; } /* See below. */ static GLboolean fxMultipassTexture( struct vertex_buffer *, GLuint ); /************************************************************************/ /************************** Texture Mode SetUp **************************/ /************************************************************************/ void fxSetupTexture(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(ctx,0); break; case TEXTURE1_2D: fxSetupTextureSingleTMU(ctx,1); break; case (TEXTURE0_2D|TEXTURE1_2D): if (fxMesa->haveTwoTMUs) fxSetupTextureDoubleTMU(ctx); else { if (MESA_VERBOSE&VERBOSE_DRIVER) fprintf(stderr, "fxmesa: enabling fake multitexture\n"); fxSetupTextureSingleTMU(ctx,0); ctx->Driver.MultipassFunc = fxMultipassTexture; } break; default: fxSetupTextureNone(ctx); break; } } /************************************************************************/ /**************************** 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; adfact=GR_BLEND_ZERO; break; case GL_ONE_MINUS_DST_ALPHA: dfact=GR_BLEND_ONE_MINUS_DST_ALPHA; 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; } } void fxSetupBlend(GLcontext *ctx) { fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; tfxUnitsState *us=&fxMesa->unitsState; 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, 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) { grAlphaTestFunction(us->alphaTestFunc); grAlphaTestReferenceValue(us->alphaTestRefValue); } else 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; } } void fxSetupDepthTest(GLcontext *ctx) { fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; tfxUnitsState *us=&fxMesa->unitsState; if(us->depthTestEnabled) grDepthBufferFunction(us->depthTestFunc); else grDepthBufferFunction(GR_CMP_ALWAYS); grDepthMask(us->depthMask); } /************************************************************************/ /**************************** Color Mask SetUp **************************/ /************************************************************************/ GLboolean 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; return 1; } static void fxSetupColorMask(GLcontext *ctx) { fxMesaContext fxMesa = FX_CONTEXT(ctx); grColorMask(ctx->Color.ColorMask[RCOMP] || ctx->Color.ColorMask[GCOMP] || ctx->Color.ColorMask[BCOMP], ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer); } /************************************************************************/ /**************************** Fog Mode SetUp ****************************/ /************************************************************************/ void fxFogTableGenerate(GLcontext *ctx) { int i; float f,eyez; fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; for(i=0;iFog.Mode) { case GL_LINEAR: f=(ctx->Fog.End-eyez)/(ctx->Fog.End-ctx->Fog.Start); break; case GL_EXP: f=exp(-ctx->Fog.Density*eyez); break; case GL_EXP2: f=exp(-ctx->Fog.Density*ctx->Fog.Density*eyez*eyez); break; default: /* That should never happen */ f=0.0f; break; } fxMesa->fogTable[i]=(GrFog_t)((1.0f-CLAMP(f,0.0f,1.0f))*255.0f); } } void fxSetupFog(GLcontext *ctx, GLboolean forceTableRebuild) { fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; if(ctx->Fog.Enabled && ctx->FogMode==FOG_FRAGMENT) { GLubyte col[4]; grFogMode(GR_FOG_WITH_TABLE); 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(forceTableRebuild || (fxMesa->fogTableMode!=ctx->Fog.Mode) || (fxMesa->fogDensity!=ctx->Fog.Density)) { fxFogTableGenerate(ctx); fxMesa->fogTableMode=ctx->Fog.Mode; fxMesa->fogDensity=ctx->Fog.Density; } grFogTable(fxMesa->fogTable); } else 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; } /************************************************************************/ /************************** Scissor Test SetUp **************************/ /************************************************************************/ static void fxSetupScissor(GLcontext *ctx) { fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx; if (ctx->Scissor.Enabled) { int ymin, ymax; ymin=ctx->Scissor.Y; ymax=ctx->Scissor.Y+ctx->Scissor.Height; if (ymin<0) ymin=0; if (ymax>fxMesa->height) ymax=fxMesa->height; grClipWindow(ctx->Scissor.X, ymin, ctx->Scissor.X+ctx->Scissor.Width, ymax); } else grClipWindow(0,0,fxMesa->width,fxMesa->height); } 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; } void fxSetupCull(GLcontext *ctx) { if(ctx->Polygon.CullFlag) { switch(ctx->Polygon.CullFaceMode) { case GL_BACK: if(ctx->Polygon.FrontFace==GL_CCW) grCullMode(GR_CULL_NEGATIVE); else grCullMode(GR_CULL_POSITIVE); break; case GL_FRONT: if(ctx->Polygon.FrontFace==GL_CCW) grCullMode(GR_CULL_POSITIVE); else grCullMode(GR_CULL_NEGATIVE); break; case GL_FRONT_AND_BACK: grCullMode(GR_CULL_DISABLE); break; default: break; } } else grCullMode(GR_CULL_DISABLE); } /************************************************************************/ /****************************** 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_SCISSOR_TEST: fxMesa->new_state |= FX_NEW_SCISSOR; ctx->Driver.RenderStart = fxSetupFXUnits; 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_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??? */ } } /************************************************************************/ /******************** 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 *****************************/ /************************************************************************/ 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,GL_FALSE); 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; ctx->Driver.RenderStart = 0; } } #else /* * Need this to provide at least one external definition. */ int gl_fx_dummy_function_setup(void) { return 0; } #endif /* FX */