fix GL_BACK color material bug
[mesa.git] / src / mesa / drivers / glide / fxsetup.c
index ce70b472d5c926ef8b443476855777b27a5cca7b..f1a56650bdef4a24feeb3f205c870340c0e374e3 100644 (file)
@@ -1,27 +1,51 @@
-/* -*- mode: C; tab-width:8;  -*-
-
-             fxsetup.c - 3Dfx VooDoo rendering mode setup functions
-*/
+/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */
 
 /*
- * 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.
+ * 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.
  *
- * 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.
+ * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the
+ * terms stated above.
  *
- * See the file fxapi.c for more informations about authors
+ * 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
 #include "fxdrv.h"
 #include "enums.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=(tfxTexInfo *)tObj->DriverData;
-  GLint minl,maxl;
+  tfxTexInfo *ti=fxTMGetTexInfo(tObj);
+  GLint minl, maxl;
 
   if (MESA_VERBOSE&VERBOSE_DRIVER) {
      fprintf(stderr,"fxmesa: fxTexValidate(...) Start\n");
@@ -47,15 +88,15 @@ static void fxTexValidate(GLcontext *ctx, struct gl_texture_object *tObj)
     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);
-
+  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,
@@ -66,7 +107,32 @@ static void fxTexValidate(GLcontext *ctx, struct gl_texture_object *tObj)
   else
     FX_smallLodLog2(ti->info)=FX_largeLodLog2(ti->info);
 
-  fxTexGetFormat(tObj->Image[minl]->Format,&(ti->info.format),&(ti->baseLevelInternalFormat));
+  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;
 
@@ -109,15 +175,15 @@ static void fxPrintUnitsMode( const char *msg, GLuint mode )
           (mode & FX_UM_ALPHA_CONSTANT)     ? "ALPHA_CONSTANT, " : "");
 }
 
-GLuint fxGetTexSetConfiguration(GLcontext *ctx,
-                               struct gl_texture_object *tObj0,
-                               struct gl_texture_object *tObj1)
+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) ||
+  if((ctx->Light.ShadeModel==GL_SMOOTH) || 1 ||
      (ctx->Point.SmoothFlag) ||
      (ctx->Line.SmoothFlag) ||
      (ctx->Polygon.SmoothFlag))
@@ -125,13 +191,19 @@ GLuint fxGetTexSetConfiguration(GLcontext *ctx,
   else
     unitsmode|=FX_UM_ALPHA_CONSTANT;
 
-  if(ctx->Light.ShadeModel==GL_SMOOTH)
+  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=(tfxTexInfo *)tObj0->DriverData;
+    tfxTexInfo *ti0=fxTMGetTexInfo(tObj0);
 
     switch(ti0->baseLevelInternalFormat) {
     case GL_ALPHA:
@@ -177,7 +249,7 @@ GLuint fxGetTexSetConfiguration(GLcontext *ctx,
   }
 
   if(tObj1) {
-    tfxTexInfo *ti1=(tfxTexInfo *)tObj1->DriverData;
+    tfxTexInfo *ti1=fxTMGetTexInfo(tObj1);
 
     switch(ti1->baseLevelInternalFormat) {
     case GL_ALPHA:
@@ -227,7 +299,7 @@ GLuint fxGetTexSetConfiguration(GLcontext *ctx,
 
   unitsmode|=(ifmt | envmode);
 
-  if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE))
+  if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE)) 
      fxPrintUnitsMode("unitsmode", unitsmode);
 
   return unitsmode;
@@ -239,50 +311,69 @@ GLuint fxGetTexSetConfiguration(GLcontext *ctx,
 
 /************************* Single Texture Set ***************************/
 
-static void fxSetupSingleTMU(fxMesaContext fxMesa, struct gl_texture_object *tObj)
+static void fxSetupSingleTMU_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj)
 {
-  tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+  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);
+    }
+  }
 
-  if(!ti->tmi.isInTM) {
-    if(ti->LODblend)
-      fxTMMoveInTM(fxMesa,tObj,FX_TMU_SPLIT);
+  /* 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]>grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,&(ti->info)))
-         fxTMMoveInTM(fxMesa,tObj,FX_TMU0);
-       else
-         fxTMMoveInTM(fxMesa,tObj,FX_TMU1);
+      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(fxMesa,tObj,FX_TMU0);
+       fxTMMoveInTM_NoLock(fxMesa,tObj,FX_TMU0);
     }
   }
 
-  if(ti->LODblend && ti->tmi.whichTMU == FX_TMU_SPLIT) {
-    if((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->haveGlobalPaletteTexture)) {
+  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(GR_TMU0,GR_TEXTABLE_PALETTE,&(ti->palette));
-      FX_grTexDownloadTable(GR_TMU1,GR_TEXTABLE_PALETTE,&(ti->palette));
+      FX_grTexDownloadTable_NoLock(GR_TMU0,GR_TEXTABLE_PALETTE,&(ti->palette));
+      FX_grTexDownloadTable_NoLock(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));
+    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(ti->tmi.whichTMU,GR_TEXTABLE_PALETTE,&(ti->palette));
+      FX_grTexDownloadTable_NoLock(tmu, GR_TEXTABLE_PALETTE, &(ti->palette));
     }
 
     /* KW: The alternative is to do the download to the other tmu.  If
@@ -292,62 +383,72 @@ static void fxSetupSingleTMU(fxMesaContext fxMesa, struct gl_texture_object *tOb
     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);
+    FX_grTexClampMode_NoLock(tmu, ti->sClamp, ti->tClamp);
+    FX_grTexFilterMode_NoLock(tmu, ti->minFilt, ti->maxFilt);
+    FX_grTexMipMapMode_NoLock(tmu, ti->mmMode, FXFALSE);
 
-    grTexSource(ti->tmi.whichTMU,ti->tmi.tm[ti->tmi.whichTMU]->startAddress,
-               GR_MIPMAPLEVELMASK_BOTH,&(ti->info));
+    FX_grTexSource_NoLock(tmu, ti->tm[tmu]->startAddr,
+                         GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
   }
 }
 
-static void fxSelectSingleTMUSrc(fxMesaContext fxMesa, GLint tmu, FxBool LODblend)
+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) {
-    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);
+  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_TMU0) {
-      grTexCombine(GR_TMU0,
-                  GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
-                  GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
-                  FXFALSE,FXFALSE);
-      
+  }
+  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 {
-      grTexCombine(GR_TMU1,
-                  GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
-                  GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
-                  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);
+
       /* 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);
-    
+
+      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;
     }
   }
 }
 
-void fxSetupTextureSingleTMU(GLcontext *ctx, GLuint textureset)
+static void fxSetupTextureSingleTMU_NoLock(GLcontext *ctx, GLuint textureset)
 {
   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
   GrCombineLocal_t localc,locala;
@@ -355,32 +456,35 @@ void fxSetupTextureSingleTMU(GLcontext *ctx, GLuint textureset)
   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=(tfxTexInfo *)tObj->DriverData;
+  ti=fxTMGetTexInfo(tObj);
 
   fxTexValidate(ctx,tObj);
 
-  fxSetupSingleTMU(fxMesa,tObj);
+  fxSetupSingleTMU_NoLock(fxMesa,tObj);
 
-  if(fxMesa->tmuSrc!=ti->tmi.whichTMU)
-    fxSelectSingleTMUSrc(fxMesa,ti->tmi.whichTMU,ti->LODblend);
+  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;
+/*    if(fxMesa->lastUnitsMode==unitsmode) */
+/*      return; */
 
   fxMesa->lastUnitsMode=unitsmode;
 
   fxMesa->stw_hint_state = 0;
-  FX_grHints(GR_HINT_STWHINT,0);
+  FX_grHints_NoLock(GR_HINT_STWHINT,0);
 
   ifmt=ti->baseLevelInternalFormat;
 
@@ -400,75 +504,94 @@ void fxSetupTextureSingleTMU(GLcontext *ctx, GLuint textureset)
 
   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);
+    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:
-    grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
-                  GR_COMBINE_FACTOR_LOCAL,
-                  locala,
-                  GR_COMBINE_OTHER_TEXTURE,
-                  FXFALSE);
+    FX_grAlphaCombine_NoLock(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);
+      FX_grColorCombine_NoLock(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);
+      FX_grColorCombine_NoLock(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) */
+#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))
-      grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
-                    GR_COMBINE_FACTOR_NONE,
-                    locala,
-                    GR_COMBINE_OTHER_NONE,
-                    FXFALSE);
+      FX_grAlphaCombine_NoLock(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);
+      FX_grAlphaCombine_NoLock(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);
+      FX_grColorCombine_NoLock(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);
+      FX_grColorCombine_NoLock(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
+    if (MESA_VERBOSE&VERBOSE_DRIVER)
+      fprintf(stderr, "fx Driver: %x Texture.EnvMode not yet supported\n",
+             ctx->Texture.Unit[textureset].EnvMode);
     break;
   }
 
@@ -477,10 +600,17 @@ void fxSetupTextureSingleTMU(GLcontext *ctx, GLuint textureset)
   }
 }
 
+static void fxSetupTextureSingleTMU(GLcontext *ctx, GLuint textureset) {
+  BEGIN_BOARD_LOCK();
+  fxSetupTextureSingleTMU_NoLock(ctx, textureset);
+  END_BOARD_LOCK();
+}
+
 /************************* Double Texture Set ***************************/
 
-void fxSetupDoubleTMU(fxMesaContext fxMesa, struct gl_texture_object *tObj0,
-                     struct gl_texture_object *tObj1)
+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
@@ -489,119 +619,119 @@ void fxSetupDoubleTMU(fxMesaContext fxMesa, struct gl_texture_object *tObj0,
 #define T0_IN_TMU1     0x10
 #define T1_IN_TMU1     0x20
 
-  tfxTexInfo *ti0=(tfxTexInfo *)tObj0->DriverData;
-  tfxTexInfo *ti1=(tfxTexInfo *)tObj1->DriverData;
+  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");
   }
 
-  if(ti0->tmi.isInTM) {
-    if(ti0->tmi.whichTMU==FX_TMU0)
+  /* 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;
-    else if(ti0->tmi.whichTMU==FX_TMU1)
+      break;
+    case FX_TMU1:
       tstate|=T0_IN_TMU1;
-    else {
-      fxTMMoveOutTM(fxMesa,tObj0);
+      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;
+  } else tstate|=T0_NOT_IN_TMU;
 
-  if(ti1->tmi.isInTM) {
-    if(ti1->tmi.whichTMU==FX_TMU0)
+  if (ti1->isInTM) {
+    switch (ti1->whichTMU) {
+    case FX_TMU0:
       tstate|=T1_IN_TMU0;
-    else if(ti1->tmi.whichTMU==FX_TMU1)
+      break;
+    case FX_TMU1:
       tstate|=T1_IN_TMU1;
-    else {
-      fxTMMoveOutTM(fxMesa,tObj1);
+      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->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;
+  } else tstate|=T1_NOT_IN_TMU;
 
-  case (T0_NOT_IN_TMU | T1_IN_TMU1):
-    fxTMMoveInTM(fxMesa,tObj0,FX_TMU0);
-    break;
+  ti0->lastTimeUsed=fxMesa->texBindNumber;
+  ti1->lastTimeUsed=fxMesa->texBindNumber;
 
-  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;
+  /* Move texture maps into TMUs */ 
 
-  default:
-    fprintf(stderr,"fx Driver: internal error in fxSetupDoubleTMU()\n");
-    fxCloseHardware();
-    exit(-1);
-    break;
+  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 (!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));
+       FX_grTexDownloadTable_NoLock(tmu0, GR_TEXTABLE_PALETTE, &(ti0->palette));
     }
 
-    if(ti1->info.format==GR_TEXFMT_P_8) {
+    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));
+       FX_grTexDownloadTable_NoLock(tmu1, 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));
+  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);
 
-  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));
+  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
@@ -611,7 +741,7 @@ void fxSetupDoubleTMU(fxMesaContext fxMesa, struct gl_texture_object *tObj0,
 #undef T1_IN_TMU1
 }
 
-static void fxSetupTextureDoubleTMU(GLcontext *ctx)
+static void fxSetupTextureDoubleTMU_NoLock(GLcontext *ctx)
 {
   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
   GrCombineLocal_t localc,locala;
@@ -619,28 +749,29 @@ static void fxSetupTextureDoubleTMU(GLcontext *ctx)
   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=(tfxTexInfo *)tObj0->DriverData;
+  ti0=fxTMGetTexInfo(tObj0);
   fxTexValidate(ctx,tObj0);
 
-  ti1=(tfxTexInfo *)tObj1->DriverData;
+  ti1=fxTMGetTexInfo(tObj1);
   fxTexValidate(ctx,tObj1);
 
-  fxSetupDoubleTMU(fxMesa,tObj0,tObj1);
+  fxSetupDoubleTMU_NoLock(fxMesa,tObj0,tObj1);
 
   unitsmode=fxGetTexSetConfiguration(ctx,tObj0,tObj1);
 
-  if(fxMesa->lastUnitsMode==unitsmode)
-    return;
+/*    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);
+  FX_grHints_NoLock(GR_HINT_STWHINT, fxMesa->stw_hint_state);
 
   envmode=unitsmode & FX_UM_E_ENVMODE;
   ifmt=unitsmode & FX_UM_E_IFMT;
@@ -662,6 +793,10 @@ static void fxSetupTextureDoubleTMU(GLcontext *ctx)
             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):
@@ -669,128 +804,152 @@ static void fxSetupTextureDoubleTMU(GLcontext *ctx)
       GLboolean isalpha[FX_NUM_TMU];
 
       if(ti0->baseLevelInternalFormat==GL_ALPHA)
-       isalpha[ti0->tmi.whichTMU]=GL_TRUE;
+       isalpha[tmu0]=GL_TRUE;
       else
-       isalpha[ti0->tmi.whichTMU]=GL_FALSE;
+       isalpha[tmu0]=GL_FALSE;
 
       if(ti1->baseLevelInternalFormat==GL_ALPHA)
-       isalpha[ti1->tmi.whichTMU]=GL_TRUE;
+       isalpha[tmu1]=GL_TRUE;
       else
-       isalpha[ti1->tmi.whichTMU]=GL_FALSE;
+       isalpha[tmu1]=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);
+       FX_grTexCombine_NoLock(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);
+       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])
-       grTexCombine(GR_TMU0,
-                    GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE,
-                    GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
-                    FXFALSE,FXFALSE);
+       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
-       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);
+       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(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);
+    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);
                  
-      grTexCombine(GR_TMU0,
-                  GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
-                  GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
-                  FXFALSE,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 {
-      grTexCombine(GR_TMU1,
-                  GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
-                  GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
-                  FXFALSE,FXFALSE);
+      FX_grTexCombine_NoLock(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);
+      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);
     }
          
-    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);
+    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(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);
+    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);
                  
-      grTexCombine(GR_TMU0,
-                  GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
-                  GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
-                  FXFALSE,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 {
-      grTexCombine(GR_TMU1,
-                  GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
-                  GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
-                  FXFALSE,FXFALSE);
+      FX_grTexCombine_NoLock(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);
+      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)
-      grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
-                    GR_COMBINE_FACTOR_NONE,
-                    locala,
-                    GR_COMBINE_OTHER_NONE,
-                    FXFALSE);
+      FX_grAlphaCombine_NoLock(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);
+      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;
   
 
@@ -799,50 +958,61 @@ static void fxSetupTextureDoubleTMU(GLcontext *ctx)
       GLboolean isalpha[FX_NUM_TMU];
 
       if(ti0->baseLevelInternalFormat==GL_ALPHA)
-       isalpha[ti0->tmi.whichTMU]=GL_TRUE;
+       isalpha[tmu0]=GL_TRUE;
       else
-       isalpha[ti0->tmi.whichTMU]=GL_FALSE;
+       isalpha[tmu0]=GL_FALSE;
 
       if(ti1->baseLevelInternalFormat==GL_ALPHA)
-       isalpha[ti1->tmi.whichTMU]=GL_TRUE;
+       isalpha[tmu1]=GL_TRUE;
       else
-       isalpha[ti1->tmi.whichTMU]=GL_FALSE;
+       isalpha[tmu1]=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);
+       FX_grTexCombine_NoLock(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);
+       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])
-       grTexCombine(GR_TMU0,
-                    GR_COMBINE_FUNCTION_SCALE_OTHER,GR_COMBINE_FACTOR_ONE,
-                    GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,GR_COMBINE_FACTOR_ONE,
-                    FXFALSE,FXFALSE);
+       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
-       grTexCombine(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);
-
-      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);
+       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) {
@@ -852,7 +1022,7 @@ static void fxSetupTextureDoubleTMU(GLcontext *ctx)
 
 /************************* No Texture ***************************/
 
-static void fxSetupTextureNone(GLcontext *ctx)
+static void fxSetupTextureNone_NoLock(GLcontext *ctx)
 {
   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
   GrCombineLocal_t localc,locala;
@@ -861,7 +1031,7 @@ static void fxSetupTextureNone(GLcontext *ctx)
      fprintf(stderr,"fxmesa: fxSetupTextureNone(...)\n");
   }
 
-  if((ctx->Light.ShadeModel==GL_SMOOTH) ||
+  if((ctx->Light.ShadeModel==GL_SMOOTH) || 1 ||
      (ctx->Point.SmoothFlag) ||
      (ctx->Line.SmoothFlag) ||
      (ctx->Polygon.SmoothFlag))
@@ -869,37 +1039,31 @@ static void fxSetupTextureNone(GLcontext *ctx)
   else
     locala=GR_COMBINE_LOCAL_CONSTANT;
   
-  if(ctx->Light.ShadeModel==GL_SMOOTH)
+  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);
+  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;
 }
 
-/* See below.
- */
-static GLboolean fxMultipassTexture( struct vertex_buffer *, GLuint );
-
-
-
 /************************************************************************/
 /************************** Texture Mode SetUp **************************/
 /************************************************************************/
 
-void fxSetupTexture(GLcontext *ctx)
+static void fxSetupTexture_NoLock(GLcontext *ctx)
 {
   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
   GLuint tex2Denabled;
@@ -921,28 +1085,34 @@ void fxSetupTexture(GLcontext *ctx)
   
   switch(tex2Denabled) {
   case TEXTURE0_2D:
-    fxSetupTextureSingleTMU(ctx,0);    
+    fxSetupTextureSingleTMU_NoLock(ctx,0);    
     break;
   case TEXTURE1_2D:
-    fxSetupTextureSingleTMU(ctx,1);
+    fxSetupTextureSingleTMU_NoLock(ctx,1);
     break;
   case (TEXTURE0_2D|TEXTURE1_2D):
      if (fxMesa->haveTwoTMUs)
-       fxSetupTextureDoubleTMU(ctx);
+       fxSetupTextureDoubleTMU_NoLock(ctx);
      else {
        if (MESA_VERBOSE&VERBOSE_DRIVER)
           fprintf(stderr, "fxmesa: enabling fake multitexture\n");
 
-       fxSetupTextureSingleTMU(ctx,0);
+       fxSetupTextureSingleTMU_NoLock(ctx,0);
        ctx->Driver.MultipassFunc = fxMultipassTexture;
      }
     break;
   default:
-    fxSetupTextureNone(ctx);
+    fxSetupTextureNone_NoLock(ctx);
     break;
   }
 }
 
+static void fxSetupTexture(GLcontext *ctx) {
+  BEGIN_BOARD_LOCK();
+  fxSetupTexture_NoLock(ctx);
+  END_BOARD_LOCK();
+}
+
 /************************************************************************/
 /**************************** Blend SetUp *******************************/
 /************************************************************************/
@@ -1037,11 +1207,15 @@ void fxDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor)
     adfact=GR_BLEND_ZERO;
     break;
   case GL_DST_ALPHA:
-    dfact=GR_BLEND_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;
+    /* 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:
@@ -1064,16 +1238,16 @@ void fxDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor)
   }
 }
 
-void fxSetupBlend(GLcontext *ctx)
+static void fxSetupBlend(GLcontext *ctx)
 {
   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
   tfxUnitsState *us=&fxMesa->unitsState;
 
   if(us->blendEnabled)
-     grAlphaBlendFunction(us->blendSrcFuncRGB,us->blendDstFuncRGB,
+     FX_grAlphaBlendFunction(us->blendSrcFuncRGB,us->blendDstFuncRGB,
                          us->blendSrcFuncAlpha,us->blendDstFuncAlpha);
   else
-     grAlphaBlendFunction(GR_BLEND_ONE,GR_BLEND_ZERO,GR_BLEND_ONE,GR_BLEND_ZERO);
+     FX_grAlphaBlendFunction(GR_BLEND_ONE,GR_BLEND_ZERO,GR_BLEND_ONE,GR_BLEND_ZERO);
 }
   
 /************************************************************************/
@@ -1137,10 +1311,10 @@ static void fxSetupAlphaTest(GLcontext *ctx)
   tfxUnitsState *us=&fxMesa->unitsState;
 
   if(us->alphaTestEnabled) {
-     grAlphaTestFunction(us->alphaTestFunc);
-     grAlphaTestReferenceValue(us->alphaTestRefValue);
+     FX_grAlphaTestFunction(us->alphaTestFunc);
+     FX_grAlphaTestReferenceValue(us->alphaTestRefValue);
   } else
-     grAlphaTestFunction(GR_CMP_ALWAYS);
+     FX_grAlphaTestFunction(GR_CMP_ALWAYS);
 }
 
 /************************************************************************/
@@ -1205,17 +1379,19 @@ void fxDDDepthMask(GLcontext *ctx, GLboolean flag)
   }
 }
 
-void fxSetupDepthTest(GLcontext *ctx)
+static 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);
+  if (us->depthTestEnabled) {
+     FX_grDepthBufferFunction(us->depthTestFunc);
+     FX_grDepthMask(us->depthMask);
+  }
+  else {
+     FX_grDepthBufferFunction(GR_CMP_ALWAYS);
+     FX_grDepthMask(FXFALSE);
+  }
 }
 
 /************************************************************************/
@@ -1230,112 +1406,130 @@ GLboolean fxDDColorMask(GLcontext *ctx,
   fxMesa->new_state |= FX_NEW_COLOR_MASK;
   ctx->Driver.RenderStart = fxSetupFXUnits;
   (void) r; (void) g; (void) b; (void) a;
-  return 1;
+  return GL_FALSE;
 }
 
 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);
+  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 ****************************/
 /************************************************************************/
 
-void fxFogTableGenerate(GLcontext *ctx)
-{
-  int i;
-  float f,eyez;
-  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
-
-  for(i=0;i<FX_grGetInteger(FX_FOG_TABLE_ENTRIES);i++) {
-    eyez=guFogTableIndexToW(i);
-
-    switch(ctx->Fog.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)
+/*
+ * This is called during state update in order to update the Glide fog state.
+ */
+static void fxSetupFog(GLcontext *ctx)
 {
-  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+  if (ctx->Fog.Enabled && ctx->FogMode==FOG_FRAGMENT) {
+    fxMesaContext fxMesa = FX_CONTEXT(ctx);
 
-  if(ctx->Fog.Enabled && ctx->FogMode==FOG_FRAGMENT) {
+    /* update fog color */
     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;
+    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;
     }
-      
-    grFogTable(fxMesa->fogTable);
-  } else
-    grFogMode(GR_FOG_DISABLE);
+
+    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;
+   ctx->Driver.RenderStart = fxSetupFXUnits;  /* XXX why is this here? */
 }
 
 /************************************************************************/
 /************************** Scissor Test SetUp **************************/
 /************************************************************************/
 
-static void fxSetupScissor(GLcontext *ctx)
+/* 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) {
-    int ymin, ymax;
-
+    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;
+  }
+  xmin+=fxMesa->x_offset;
+  xmax+=fxMesa->x_offset;
+  ymin+=fxMesa->y_delta;
+  ymax+=fxMesa->y_delta;
+  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);
+}
 
-    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);
+static void fxSetupScissor(GLcontext *ctx)
+{
+  fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+  if (!fxMesa->needClip) {
+    BEGIN_BOARD_LOCK();
+    fxSetScissorValues(ctx);
+    END_BOARD_LOCK();
+  }
 }
 
 void fxDDScissor( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h )
@@ -1364,30 +1558,30 @@ void fxDDFrontFace(GLcontext *ctx, GLenum mode)
 }
 
 
-void fxSetupCull(GLcontext *ctx)
+static 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);
+  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);
 }
 
 
@@ -1430,6 +1624,9 @@ void fxDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
      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;
@@ -1439,6 +1636,7 @@ void fxDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
      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:
@@ -1446,10 +1644,61 @@ void fxDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
       ctx->Driver.RenderStart = fxSetupFXUnits;
       break;
   default:
-    ;  /* XXX no-op??? */
+    ;  /* 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 *************************/
 /************************************************************************/
@@ -1539,7 +1788,7 @@ void fxDDShadeModel(GLcontext *ctx, GLenum mode)
 /************************************************************************/
 /****************************** Units SetUp *****************************/
 /************************************************************************/
-void gl_print_fx_state_flags( const char *msg, GLuint flags )
+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",
@@ -1559,7 +1808,7 @@ void fxSetupFXUnits( GLcontext *ctx )
   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
   GLuint newstate = fxMesa->new_state;
 
-  if (MESA_VERBOSE&VERBOSE_DRIVER) 
+  if (MESA_VERBOSE&VERBOSE_DRIVER)
      gl_print_fx_state_flags("fxmesa: fxSetupFXUnits", newstate);
 
   if (newstate) {
@@ -1576,7 +1825,7 @@ void fxSetupFXUnits( GLcontext *ctx )
        fxSetupDepthTest(ctx);
 
      if (newstate & FX_NEW_FOG)
-       fxSetupFog(ctx,GL_FALSE);
+       fxSetupFog(ctx);
 
      if (newstate & FX_NEW_SCISSOR)
        fxSetupScissor(ctx);
@@ -1588,7 +1837,7 @@ void fxSetupFXUnits( GLcontext *ctx )
        fxSetupCull(ctx);     
 
      fxMesa->new_state = 0;
-     ctx->Driver.RenderStart = 0;
+/*       ctx->Driver.RenderStart = 0; */
   }
 }