updated with latest DRI tree changes
authorBrian Paul <brian.paul@tungstengraphics.com>
Tue, 18 Jan 2000 17:56:05 +0000 (17:56 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Tue, 18 Jan 2000 17:56:05 +0000 (17:56 +0000)
src/mesa/drivers/glide/fxdd.c
src/mesa/drivers/glide/fxddspan.c
src/mesa/drivers/glide/fxddtex.c
src/mesa/drivers/glide/fxdrv.h
src/mesa/drivers/glide/fxglidew.h
src/mesa/drivers/glide/fxsetup.c
src/mesa/drivers/glide/fxtexman.c

index 71e11dfd14d9c0871e5ed9ab444b7a71f7b2b0aa..9c0fc4de5371eda123bc45df94619312ffe6b808 100644 (file)
@@ -403,10 +403,16 @@ static GLboolean fxDDDrawBitMap(GLcontext *ctx, GLint px, GLint py,
   g=(GLint)(ctx->Current.RasterColor[1]*255.0f);
   b=(GLint)(ctx->Current.RasterColor[2]*255.0f);
   a=(GLint)(ctx->Current.RasterColor[3]*255.0f);
-  color=(FxU16)
-    ( ((FxU16)0xf8 & b) <<(11-3))  |
-    ( ((FxU16)0xfc & g) <<(5-3+1)) |
-    ( ((FxU16)0xf8 & r) >> 3);
+  if (fxMesa->bgrOrder)
+    color=(FxU16)
+      ( ((FxU16)0xf8 & b) <<(11-3))  |
+      ( ((FxU16)0xfc & g) <<(5-3+1)) |
+      ( ((FxU16)0xf8 & r) >> 3);
+  else
+    color=(FxU16)
+      ( ((FxU16)0xf8 & r) <<(11-3))  |
+      ( ((FxU16)0xfc & g) <<(5-3+1)) |
+      ( ((FxU16)0xf8 & b) >> 3);
 
   stride=info.strideInBytes>>1;
 
index b792caa0610da8f75e22970faf17aa862bf9e3ee..b950b3f1c3e1ffdd8511f8fecd9047f4d30fb804 100644 (file)
 
 #if !defined(FXMESA_USE_ARGB) 
 
+
+#if defined(FX_GLIDE3) && defined(XF86DRI)
+
+static FxBool writeRegionClipped(fxMesaContext fxMesa, GrBuffer_t dst_buffer,
+                         FxU32 dst_x, FxU32 dst_y, GrLfbSrcFmt_t src_format,
+                         FxU32 src_width, FxU32 src_height, FxI32 src_stride,
+                         void *src_data)
+{
+  int i, x, w, srcElt;
+  void *data;
+
+  if (src_width==1 && src_height==1) { /* Easy case writing a point */
+    for (i=0; i<fxMesa->numClipRects; i++) {
+      if ((dst_x>=fxMesa->pClipRects[i].x1) && 
+         (dst_x<fxMesa->pClipRects[i].x2) &&
+         (dst_y>=fxMesa->pClipRects[i].y1) && 
+         (dst_y<fxMesa->pClipRects[i].y2)) {
+       FX_grLfbWriteRegion(dst_buffer, dst_x, dst_y, src_format,
+                           1, 1, src_stride, src_data);
+       return GL_TRUE;
+      }
+    }
+  } else if (src_height==1) { /* Writing a span */
+    if (src_format==GR_LFB_SRC_FMT_8888) srcElt=4;
+    else if (src_format==GR_LFB_SRC_FMT_ZA16) srcElt=2;
+    else {
+      fprintf(stderr, "Unknown src_format passed to writeRegionClipped\n");
+      return GL_FALSE;
+    }
+    for (i=0; i<fxMesa->numClipRects; i++) {
+      if (dst_y>=fxMesa->pClipRects[i].y1 && dst_y<fxMesa->pClipRects[i].y2) {
+       if (dst_x<fxMesa->pClipRects[i].x1) {
+         x=fxMesa->pClipRects[i].x1;
+         data=((char*)src_data)+srcElt*(dst_x-x);
+         w=src_width-(x-dst_x);
+       } else {
+         x=dst_x;
+         data=src_data;
+         w=src_width;
+       }
+       if (x+w>fxMesa->pClipRects[i].x2) {
+         w=fxMesa->pClipRects[i].x2-x;
+       }
+       FX_grLfbWriteRegion(dst_buffer, x, dst_y, src_format, w, 1,
+                           src_stride, data);
+      }
+    }
+  } else { /* Punt on the case of arbitrary rectangles */
+    return GL_FALSE;
+  }
+  return GL_TRUE;
+}
+
+#else
+
+#define writeRegionClipped(fxm,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)             \
+  FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)
+
+#endif
+
+
 /* KW: Rearranged the args in the call to grLfbWriteRegion().
  */
 #define LFB_WRITE_SPAN_MESA(dst_buffer,                \
                   src_data)                    \
 
 
-#else /* defined(FXMESA_USE_RGBA) */
+#else /* !defined(FXMESA_USE_RGBA) */
+
+#define writeRegionClipped(fxm,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)             \
+  FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)
+
 
 #define MESACOLOR_TO_ARGB(c) (                         \
              ( ((unsigned int)(c[ACOMP]))<<24 ) |      \
              ( ((unsigned int)(c[GCOMP]))<<8 )  |      \
              (  (unsigned int)(c[BCOMP])) )
   
-void LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer, 
+inline void LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer, 
                         FxU32 dst_x, 
                         FxU32 dst_y, 
                         FxU32 src_width,
@@ -108,7 +173,7 @@ void LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer,
    {
       argb[i] = MESACOLOR_TO_ARGB(rgba[i]);
    }
-   writeRegionClipped(fxMesa, dst_buffer,
+   writeRegionClipped( /*fxMesa,*/ NULL, dst_buffer,
                       dst_x,
                       dst_y,
                       GR_LFB_SRC_FMT_8888,
@@ -117,61 +182,9 @@ void LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer,
                       src_stride,
                       (void*)argb);
 }
+#endif /* !defined(FXMESA_USE_RGBA) */
 
-#endif
-
-#if defined(FX_GLIDE3) && defined(XF86DRI)
-
-FxBool writeRegionClipped(fxMesaContext fxMesa, GrBuffer_t dst_buffer,
-                         FxU32 dst_x, FxU32 dst_y, GrLfbSrcFmt_t src_format,
-                         FxU32 src_width, FxU32 src_height, FxI32 src_stride,
-                         void *src_data)
-{
-  int i, x, w;
-  void *data;
-
-  if (src_width==1 && src_height==1) { /* Easy case writing a point */
-    for (i=0; i<fxMesa->numClipRects; i++) {
-      if ((dst_x>=fxMesa->pClipRects[i].x1) && 
-         (dst_x<fxMesa->pClipRects[i].x2) &&
-         (dst_y>=fxMesa->pClipRects[i].y1) && 
-         (dst_y<fxMesa->pClipRects[i].y2)) {
-       FX_grLfbWriteRegion(dst_buffer, dst_x, dst_y, src_format,
-                           src_width, src_height, src_stride, src_data);
-       return GL_TRUE;
-      }
-    }
-  } else if (src_height==1) { /* Writing a span */
-    for (i=0; i<fxMesa->numClipRects; i++) {
-      if (dst_y>=fxMesa->pClipRects[i].y1 && dst_y<fxMesa->pClipRects[i].y2) {
-       if (dst_x<fxMesa->pClipRects[i].x1) {
-         x=fxMesa->pClipRects[i].x1;
-         data=((char*)src_data)+2*(dst_x-x);
-         w=src_width-(x-dst_x);
-       } else {
-         x=dst_x;
-         data=src_data;
-         w=src_width;
-       }
-       if (x+w>fxMesa->pClipRects[i].x2) {
-         w=fxMesa->pClipRects[i].x2-x;
-       }
-       FX_grLfbWriteRegion(dst_buffer, x, dst_y, src_format, w, src_height,
-                           src_stride, data);
-      }
-    }
-  } else { /* Punt on the case of arbitrary rectangles */
-    return GL_FALSE;
-  }
-  return GL_TRUE;
-}
-
-#else
-
-#define writeRegionClipped(fxm,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)             \
-  FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)
-
-#endif
 
 /************************************************************************/
 /*****                    Span functions                            *****/
index 64fc193357877fe9e596f4a5ab78b193b2175939..747d2555c7950520f72ac59cd5d4ad5a83ecda54 100644 (file)
@@ -43,9 +43,6 @@
  */
 
 
-/* fxddtex.c - 3Dfx VooDoo Texture mapping functions */
-
-
 #ifdef HAVE_CONFIG_H
 #include "conf.h"
 #endif
@@ -127,13 +124,8 @@ static tfxTexInfo *fxAllocTexObjData(fxMesaContext fxMesa)
   ti->sClamp=GR_TEXTURECLAMP_WRAP;
   ti->tClamp=GR_TEXTURECLAMP_WRAP;
 
-  if(fxMesa->haveTwoTMUs) {
-    ti->mmMode=GR_MIPMAP_NEAREST;
-    ti->LODblend=FXTRUE;
-  } else {
-    ti->mmMode=GR_MIPMAP_NEAREST_DITHER;
-    ti->LODblend=FXFALSE;
-  }
+  ti->mmMode=GR_MIPMAP_NEAREST;
+  ti->LODblend=FXFALSE;
 
   for(i=0;i<MAX_TEXTURE_LEVELS;i++) {
     ti->mipmapLevel[i].used=GL_FALSE;
index c469daa67015cc09f35f497474d44c908506da44..382ec61a06f354e8bd6fa17537146397939f2f8f 100644 (file)
@@ -256,10 +256,10 @@ typedef struct {
 
 #define FX_UM_E_IFMT                0x00fff000
 
-#define FX_UM_COLOR_ITERATED        0x00100000
-#define FX_UM_COLOR_CONSTANT        0x00200000
-#define FX_UM_ALPHA_ITERATED        0x00400000
-#define FX_UM_ALPHA_CONSTANT        0x00800000
+#define FX_UM_COLOR_ITERATED        0x01000000
+#define FX_UM_COLOR_CONSTANT        0x02000000
+#define FX_UM_ALPHA_ITERATED        0x04000000
+#define FX_UM_ALPHA_CONSTANT        0x08000000
 
 typedef void (*tfxRenderVBFunc)(GLcontext *);
 
@@ -471,7 +471,6 @@ struct tfxMesaContext {
   GLuint texBindNumber;
   GLint tmuSrc;
   GLuint lastUnitsMode;
-  GLuint texStart[FX_NUM_TMU];
   GLuint freeTexMem[FX_NUM_TMU];
   MemRange *tmPool;
   MemRange *tmFree[FX_NUM_TMU];
@@ -621,6 +620,7 @@ extern void fxTMInit(fxMesaContext ctx);
 extern void fxTMClose(fxMesaContext ctx);
 extern void fxTMMoveInTM(fxMesaContext, struct gl_texture_object *, GLint);
 extern void fxTMMoveOutTM(fxMesaContext, struct gl_texture_object *);
+#define fxTMMoveOutTM_NoLock fxTMMoveOutTM
 extern void fxTMFreeTexture(fxMesaContext, struct gl_texture_object *);
 extern void fxTMReloadMipMapLevel(fxMesaContext, struct gl_texture_object *, GLint);
 extern void fxTMReloadSubMipMapLevel(fxMesaContext, struct gl_texture_object *,
@@ -670,9 +670,6 @@ extern void fxSetScissorValues(GLcontext *ctx);
 extern void fxTMMoveInTM_NoLock(fxMesaContext fxMesa, 
                                struct gl_texture_object *tObj, 
                                GLint where);
-extern void fxSetupTexture_NoLock(GLcontext *ctx);
-extern void fxSetupTexture(GLcontext *ctx);
-
 extern void fxInitPixelTables(fxMesaContext fxMesa, GLboolean bgrOrder);
 
 #endif
index 49c28f222cecc036e26bda80ffe15e1286a9aa3c..c3e8057e4ea10eb8ca6582ec61b6c75ff6c99462 100644 (file)
@@ -223,23 +223,23 @@ typedef struct
 
 typedef struct
 {
-  float x, y;         /* X and Y in screen space */
-  float ooz;          /* 65535/Z (used for Z-buffering) */
-  float oow;          /* 1/W (used for W-buffering, texturing) */
-  float r, g, b, a;   /* R, G, B, A [0..255.0] */
-  float z;            /* Z is ignored */
+  float x, y, z;                /* X, Y, and Z of scrn space -- Z is ignored */
+  float r, g, b;                /* R, G, B, ([0..255.0]) */
+  float ooz;                    /* 65535/Z (used for Z-buffering) */
+  float a;                      /* Alpha [0..255.0] */
+  float oow;                    /* 1/W (used for W-buffering, texturing) */
   GrTmuVertex  tmuvtx[GLIDE_NUM_TMU];
 } GrVertex;
 
 #define GR_VERTEX_X_OFFSET              0
 #define GR_VERTEX_Y_OFFSET              1
-#define GR_VERTEX_OOZ_OFFSET            2
-#define GR_VERTEX_OOW_OFFSET            3
-#define GR_VERTEX_R_OFFSET              4
-#define GR_VERTEX_G_OFFSET              5
-#define GR_VERTEX_B_OFFSET              6
+#define GR_VERTEX_Z_OFFSET              2
+#define GR_VERTEX_R_OFFSET              3
+#define GR_VERTEX_G_OFFSET              4
+#define GR_VERTEX_B_OFFSET              5
+#define GR_VERTEX_OOZ_OFFSET            6
 #define GR_VERTEX_A_OFFSET              7
-#define GR_VERTEX_Z_OFFSET              8
+#define GR_VERTEX_OOW_OFFSET            8
 #define GR_VERTEX_SOW_TMU0_OFFSET       9
 #define GR_VERTEX_TOW_TMU0_OFFSET       10
 #define GR_VERTEX_OOW_TMU0_OFFSET       11
@@ -473,7 +473,6 @@ typedef struct
 #else
        #define FX_setupGrVertexLayout()                do {} while (0)
 #endif
-
 /*
  * grSstControl stuff
  */
index 20381c6728041998b854bf551945bb12b76059d4..e13e8c3b0549d2ca5a905c773abb39d914da8c90 100644 (file)
@@ -59,10 +59,11 @@ 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 fxSetupTextureSingleTMU(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 fxFogTableGenerate(GLcontext *ctx);
@@ -70,6 +71,7 @@ static void fxSetupFog(GLcontext *ctx, GLboolean forceTableRebuild);
 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)
@@ -118,6 +120,8 @@ static void fxTexValidate(GLcontext *ctx, struct gl_texture_object *tObj)
   case GL_REPEAT:
     ti->sClamp=0;
     break;
+  default:
+    ;  /* silence compiler warning */
   }
   switch (tObj->WrapT) {
   case GL_CLAMP_TO_EDGE:
@@ -128,6 +132,8 @@ static void fxTexValidate(GLcontext *ctx, struct gl_texture_object *tObj)
   case GL_REPEAT:
     ti->tClamp=0;
     break;
+  default:
+    ;  /* silence compiler warning */
   }
 
   ti->validated=GL_TRUE;
@@ -192,6 +198,10 @@ static GLuint fxGetTexSetConfiguration(GLcontext *ctx,
   else
     unitsmode|=FX_UM_COLOR_CONSTANT;
 
+  /* 
+     OpenGL Feeds Texture 0 into Texture 1
+     Glide Feeds Texture 1 into Texture 0
+  */
   if(tObj0) {
     tfxTexInfo *ti0=fxTMGetTexInfo(tObj0);
 
@@ -289,7 +299,7 @@ static 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;
@@ -304,7 +314,20 @@ static GLuint fxGetTexSetConfiguration(GLcontext *ctx,
 static void fxSetupSingleTMU_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj)
 {
   tfxTexInfo *ti=fxTMGetTexInfo(tObj);
+  int tmu;
+
+  /* Make sure we're not loaded incorrectly */
+  if (ti->isInTM) {
+    if (ti->LODblend) {
+      if (ti->whichTMU!=FX_TMU_SPLIT)
+       fxTMMoveOutTM(fxMesa, tObj);
+    } else {
+      if (ti->whichTMU==FX_TMU_SPLIT)
+       fxTMMoveOutTM(fxMesa, tObj);
+    }
+  }
 
+  /* Make sure we're loaded correctly */
   if (!ti->isInTM) {
     if (ti->LODblend)
       fxTMMoveInTM_NoLock(fxMesa,tObj,FX_TMU_SPLIT);
@@ -312,10 +335,11 @@ static void fxSetupSingleTMU_NoLock(fxMesaContext fxMesa, struct gl_texture_obje
       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);
+                                             &(ti->info))) {
+         fxTMMoveInTM_NoLock(fxMesa,tObj, FX_TMU0);
+       } else {
+         fxTMMoveInTM_NoLock(fxMesa,tObj, FX_TMU1);
+       }
       } else
        fxTMMoveInTM_NoLock(fxMesa,tObj,FX_TMU0);
     }
@@ -342,11 +366,14 @@ static void fxSetupSingleTMU_NoLock(fxMesaContext fxMesa, struct gl_texture_obje
     FX_grTexSource_NoLock(GR_TMU1,ti->tm[FX_TMU1]->startAddr,
                          GR_MIPMAPLEVELMASK_EVEN,&(ti->info));
   } else {
+    if (ti->whichTMU==FX_TMU_BOTH) tmu=FX_TMU0;
+    else tmu=ti->whichTMU;
+
     if((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->haveGlobalPaletteTexture)) {
        if (MESA_VERBOSE&VERBOSE_DRIVER) {
          fprintf(stderr,"fxmesa: uploading texture palette\n");
        }
-      FX_grTexDownloadTable_NoLock(ti->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
@@ -356,23 +383,17 @@ static void fxSetupSingleTMU_NoLock(fxMesaContext fxMesa, struct gl_texture_obje
     if (ti->LODblend && (MESA_VERBOSE&VERBOSE_DRIVER))
        fprintf(stderr, "fxmesa: not blending texture - only on one tmu\n");
 
-    FX_grTexClampMode_NoLock(ti->whichTMU,ti->sClamp,ti->tClamp);
-    FX_grTexFilterMode_NoLock(ti->whichTMU,ti->minFilt,ti->maxFilt);
-    FX_grTexMipMapMode_NoLock(ti->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);
 
-    FX_grTexSource_NoLock(ti->whichTMU,
-                         ti->tm[ti->whichTMU]->startAddr,
-                         GR_MIPMAPLEVELMASK_BOTH,&(ti->info));
+    FX_grTexSource_NoLock(tmu, ti->tm[tmu]->startAddr,
+                         GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
   }
 }
 
-static void fxSetupSingleTMU(fxMesaContext fxMesa, struct gl_texture_object *tObj) {
-  BEGIN_BOARD_LOCK();
-  fxSetupSingleTMU_NoLock(fxMesa, tObj);
-  END_BOARD_LOCK();
-}
-
-static void fxSelectSingleTMUSrc_NoLock(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);
@@ -390,15 +411,17 @@ static void fxSelectSingleTMUSrc_NoLock(fxMesaContext fxMesa, GLint tmu, FxBool
                           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) {
+    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);
-      
+      FX_grTexCombine_NoLock(GR_TMU1,
+                            GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE,
+                            GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE,
+                            FXFALSE,FXFALSE);
       fxMesa->tmuSrc=FX_TMU0;
     } else {
       FX_grTexCombine_NoLock(GR_TMU1,
@@ -409,8 +432,10 @@ static void fxSelectSingleTMUSrc_NoLock(fxMesaContext fxMesa, GLint tmu, FxBool
       /* GR_COMBINE_FUNCTION_SCALE_OTHER doesn't work ?!? */
     
       FX_grTexCombine_NoLock(GR_TMU0,
-                            GR_COMBINE_FUNCTION_BLEND,GR_COMBINE_FACTOR_ONE,
-                            GR_COMBINE_FUNCTION_BLEND,GR_COMBINE_FACTOR_ONE,
+                            GR_COMBINE_FUNCTION_BLEND,
+                            GR_COMBINE_FACTOR_ONE,
+                            GR_COMBINE_FUNCTION_BLEND,
+                            GR_COMBINE_FACTOR_ONE,
                             FXFALSE,FXFALSE);
     
       fxMesa->tmuSrc=FX_TMU1;
@@ -426,6 +451,7 @@ static void fxSetupTextureSingleTMU_NoLock(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");
@@ -437,8 +463,10 @@ static void fxSetupTextureSingleTMU_NoLock(GLcontext *ctx, GLuint textureset)
 
   fxSetupSingleTMU_NoLock(fxMesa,tObj);
 
-  if(fxMesa->tmuSrc!=ti->whichTMU)
-    fxSelectSingleTMUSrc_NoLock(fxMesa,ti->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);
@@ -504,10 +532,30 @@ static void fxSetupTextureSingleTMU_NoLock(GLcontext *ctx, GLuint textureset)
                               FXFALSE);
     break;
   case GL_BLEND:
+#if 0
+    FX_grAlphaCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER,
+                            GR_COMBINE_FACTOR_LOCAL,
+                            locala,
+                            GR_COMBINE_OTHER_TEXTURE,
+                            FXFALSE);
+    if (ifmt==GL_ALPHA)
+      FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_LOCAL,
+                              GR_COMBINE_FACTOR_NONE,
+                              localc,
+                              GR_COMBINE_OTHER_NONE,
+                              FXFALSE);
+    else
+      FX_grColorCombine_NoLock(GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+                              GR_COMBINE_FACTOR_LOCAL,
+                              localc,
+                              GR_COMBINE_OTHER_TEXTURE,
+                              FXTRUE);
+    ctx->Driver.MultipassFunc = fxMultipassBlend;
+#else
 #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) */
+#endif    
     break;
   case GL_REPLACE:
     if((ifmt==GL_RGB) || (ifmt==GL_LUMINANCE))
@@ -570,87 +618,87 @@ static void fxSetupDoubleTMU_NoLock(fxMesaContext fxMesa,
   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->isInTM) {
-    if(ti0->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->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->isInTM) {
-    if(ti1->whichTMU==FX_TMU0)
+  if (ti1->isInTM) {
+    switch (ti1->whichTMU) {
+    case FX_TMU0:
       tstate|=T1_IN_TMU0;
-    else if(ti1->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;
+  } else tstate|=T1_NOT_IN_TMU;
 
   ti0->lastTimeUsed=fxMesa->texBindNumber;
   ti1->lastTimeUsed=fxMesa->texBindNumber;
 
-  /* Move texture maps in TMUs */ 
-
-  switch(tstate) {
-  case (T0_IN_TMU0 | T1_IN_TMU0):
-    fxTMMoveOutTM(fxMesa,tObj1);
-
-    fxTMMoveInTM_NoLock(fxMesa,tObj1,FX_TMU1);
-    break;
-
-  case (T0_IN_TMU1 | T1_IN_TMU1):
-    fxTMMoveOutTM(fxMesa,tObj0);
-
-    fxTMMoveInTM_NoLock(fxMesa,tObj0,FX_TMU0);
-    break;
-
-  case (T0_NOT_IN_TMU | T1_NOT_IN_TMU):
-    fxTMMoveInTM_NoLock(fxMesa,tObj0,FX_TMU0);
-    fxTMMoveInTM_NoLock(fxMesa,tObj1,FX_TMU1);
-    break;
-
-    /*** T0/T1 ***/
-
-  case (T0_NOT_IN_TMU | T1_IN_TMU0):
-    fxTMMoveInTM_NoLock(fxMesa,tObj0,FX_TMU1);
-    break;
+  /* Move texture maps into TMUs */ 
 
-  case (T0_NOT_IN_TMU | T1_IN_TMU1):
-    fxTMMoveInTM_NoLock(fxMesa,tObj0,FX_TMU0);
-    break;
-
-  case (T0_IN_TMU0 | T1_NOT_IN_TMU):
-    fxTMMoveInTM_NoLock(fxMesa,tObj1,FX_TMU1);
-    break;
-
-  case (T0_IN_TMU1 | T1_NOT_IN_TMU):
-    fxTMMoveInTM_NoLock(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 (!(((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) {
@@ -658,30 +706,28 @@ static void fxSetupDoubleTMU_NoLock(fxMesaContext fxMesa,
        if (MESA_VERBOSE&VERBOSE_DRIVER) {
          fprintf(stderr,"fxmesa: uploading texture palette TMU0\n");
        }
-       FX_grTexDownloadTable_NoLock(ti0->whichTMU,GR_TEXTABLE_PALETTE,&(ti0->palette));
+       FX_grTexDownloadTable_NoLock(tmu0, GR_TEXTABLE_PALETTE, &(ti0->palette));
     }
 
     if (ti1->info.format==GR_TEXFMT_P_8) {
        if (MESA_VERBOSE&VERBOSE_DRIVER) {
          fprintf(stderr,"fxmesa: uploading texture palette TMU1\n");
        }
-       FX_grTexDownloadTable_NoLock(ti1->whichTMU, GR_TEXTABLE_PALETTE,&(ti1->palette));
+       FX_grTexDownloadTable_NoLock(tmu1, GR_TEXTABLE_PALETTE, &(ti1->palette));
     }
   }
 
-  FX_grTexSource_NoLock(ti0->whichTMU,
-                       ti0->tm[ti0->whichTMU]->startAddr,
-                       GR_MIPMAPLEVELMASK_BOTH,&(ti0->info));
-  FX_grTexClampMode_NoLock(ti0->whichTMU,ti0->sClamp,ti0->tClamp);
-  FX_grTexFilterMode_NoLock(ti0->whichTMU,ti0->minFilt,ti0->maxFilt);
-  FX_grTexMipMapMode_NoLock(ti0->whichTMU,ti0->mmMode,FXFALSE);
+  FX_grTexSource_NoLock(tmu0, ti0->tm[tmu0]->startAddr, 
+                       GR_MIPMAPLEVELMASK_BOTH, &(ti0->info));
+  FX_grTexClampMode_NoLock(tmu0, ti0->sClamp, ti0->tClamp);
+  FX_grTexFilterMode_NoLock(tmu0, ti0->minFilt, ti0->maxFilt);
+  FX_grTexMipMapMode_NoLock(tmu0, ti0->mmMode, FXFALSE);
 
-  FX_grTexSource_NoLock(ti1->whichTMU,
-                       ti1->tm[ti1->whichTMU]->startAddr,
-                       GR_MIPMAPLEVELMASK_BOTH,&(ti1->info));
-  FX_grTexClampMode_NoLock(ti1->whichTMU,ti1->sClamp,ti1->tClamp);
-  FX_grTexFilterMode_NoLock(ti1->whichTMU,ti1->minFilt,ti1->maxFilt);
-  FX_grTexMipMapMode_NoLock(ti1->whichTMU,ti1->mmMode,FXFALSE);
+  FX_grTexSource_NoLock(tmu1, ti1->tm[tmu1]->startAddr,
+                       GR_MIPMAPLEVELMASK_BOTH, &(ti1->info));
+  FX_grTexClampMode_NoLock(tmu1, ti1->sClamp, ti1->tClamp);
+  FX_grTexFilterMode_NoLock(tmu1, ti1->minFilt, ti1->maxFilt);
+  FX_grTexMipMapMode_NoLock(tmu1, ti1->mmMode, FXFALSE);
 
 #undef T0_NOT_IN_TMU
 #undef T1_NOT_IN_TMU
@@ -699,6 +745,7 @@ static void fxSetupTextureDoubleTMU_NoLock(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");
@@ -742,6 +789,10 @@ static void fxSetupTextureDoubleTMU_NoLock(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):
@@ -749,14 +800,14 @@ static void fxSetupTextureDoubleTMU_NoLock(GLcontext *ctx)
       GLboolean isalpha[FX_NUM_TMU];
 
       if(ti0->baseLevelInternalFormat==GL_ALPHA)
-       isalpha[ti0->whichTMU]=GL_TRUE;
+       isalpha[tmu0]=GL_TRUE;
       else
-       isalpha[ti0->whichTMU]=GL_FALSE;
+       isalpha[tmu0]=GL_FALSE;
 
       if(ti1->baseLevelInternalFormat==GL_ALPHA)
-       isalpha[ti1->whichTMU]=GL_TRUE;
+       isalpha[tmu1]=GL_TRUE;
       else
-       isalpha[ti1->whichTMU]=GL_FALSE;
+       isalpha[tmu1]=GL_FALSE;
        
       if(isalpha[FX_TMU1])
        FX_grTexCombine_NoLock(GR_TMU1,
@@ -802,7 +853,7 @@ static void fxSetupTextureDoubleTMU_NoLock(GLcontext *ctx)
       break;
     }
   case (FX_UM_E0_REPLACE | FX_UM_E1_BLEND): /* Only for GLQuake */
-    if(ti1->whichTMU==FX_TMU1) {
+    if (tmu1==FX_TMU1) {
       FX_grTexCombine_NoLock(GR_TMU1,
                             GR_COMBINE_FUNCTION_LOCAL,
                             GR_COMBINE_FACTOR_NONE,
@@ -845,7 +896,7 @@ static void fxSetupTextureDoubleTMU_NoLock(GLcontext *ctx)
                             FXFALSE);
     break;
   case (FX_UM_E0_REPLACE | FX_UM_E1_MODULATE): /* Quake 2 and 3 */
-    if(ti1->whichTMU==FX_TMU1) {
+    if (tmu1==FX_TMU1) {
       FX_grTexCombine_NoLock(GR_TMU1,
                             GR_COMBINE_FUNCTION_LOCAL,
                             GR_COMBINE_FACTOR_NONE,
@@ -903,14 +954,14 @@ static void fxSetupTextureDoubleTMU_NoLock(GLcontext *ctx)
       GLboolean isalpha[FX_NUM_TMU];
 
       if(ti0->baseLevelInternalFormat==GL_ALPHA)
-       isalpha[ti0->whichTMU]=GL_TRUE;
+       isalpha[tmu0]=GL_TRUE;
       else
-       isalpha[ti0->whichTMU]=GL_FALSE;
+       isalpha[tmu0]=GL_FALSE;
 
       if(ti1->baseLevelInternalFormat==GL_ALPHA)
-       isalpha[ti1->whichTMU]=GL_TRUE;
+       isalpha[tmu1]=GL_TRUE;
       else
-       isalpha[ti1->whichTMU]=GL_FALSE;
+       isalpha[tmu1]=GL_FALSE;
        
       if(isalpha[FX_TMU1])
        FX_grTexCombine_NoLock(GR_TMU1,
@@ -955,7 +1006,9 @@ static void fxSetupTextureDoubleTMU_NoLock(GLcontext *ctx)
                               FXFALSE);
       break;
     }
-    
+  default:
+    fprintf(stderr, "Unexpected dual texture mode encountered\n");
+    break;
   }
 
   if (MESA_VERBOSE&VERBOSE_DRIVER) {
@@ -1006,7 +1059,7 @@ static void fxSetupTextureNone_NoLock(GLcontext *ctx)
 /************************** Texture Mode SetUp **************************/
 /************************************************************************/
 
-void fxSetupTexture_NoLock(GLcontext *ctx)
+static void fxSetupTexture_NoLock(GLcontext *ctx)
 {
   fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
   GLuint tex2Denabled;
@@ -1050,7 +1103,7 @@ void fxSetupTexture_NoLock(GLcontext *ctx)
   }
 }
 
-void fxSetupTexture(GLcontext *ctx) {
+static void fxSetupTexture(GLcontext *ctx) {
   BEGIN_BOARD_LOCK();
   fxSetupTexture_NoLock(ctx);
   END_BOARD_LOCK();
@@ -1150,11 +1203,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:
@@ -1584,6 +1641,57 @@ void fxDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
   }    
 }
 
+#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 */
+    /* ??? Set the Constant Color ??? */
+    fxDDEnable(ctx, GL_BLEND, GL_TRUE);
+    fxDDBlendFunc(ctx, ???, ???);
+    fxSetupTextureSingleTMU(ctx, ???);
+    fxSetupBlend(ctx);
+    fxSetupDepthTest(ctx);
+    break;
+
+  case 2:
+    /* Reset everything back to normal */
+    fxMesa->unitsState = fxMesa->restoreUnitsState;
+    fxMesa->setupdone &= ???;
+    fxSetupTextureSingleTMU(ctx, ???);
+    fxSetupBlend(ctx);
+    fxSetupDepthTest(ctx);
+    break;
+  }
+
+  return pass==1;
+}
+#endif
+
 /************************************************************************/
 /******************** Fake Multitexture Support *************************/
 /************************************************************************/
@@ -1693,7 +1801,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) {
index 770f095ab8cb9edad63e7bb0b6488b4b3022d496..3f4439549db58314785f6a4f31cafb903969b8d3 100644 (file)
 
 #include "fxdrv.h"
 
+int texSwaps=0;
+
 #define FX_2MB_SPLIT 0x200000
 
 static struct gl_texture_object *fxTMFindOldestObject(fxMesaContext fxMesa,
                                                      int tmu);
 
 
-#if 0
+#ifdef TEXSANITY
 static void fubar()
 {
 }
 
   /* Sanity Check */
-static void sanity(fxMesaContext fxMesa, int tmu)
+static void sanity(fxMesaContext fxMesa)
 {
-  MemRange *tmp, *prev;
-  int i;
+  MemRange *tmp, *prev, *pos;
 
   prev=0;
-  tmp = fxMesa->tmFree[tmu];
-  i=0;
+  tmp = fxMesa->tmFree[0];
+  while (tmp) {
+    if (!tmp->startAddr && !tmp->endAddr) {
+      fprintf(stderr, "Textures fubar\n");
+      fubar();
+    }
+    if (tmp->startAddr>=tmp->endAddr) {
+      fprintf(stderr, "Node fubar\n");
+      fubar();
+    }
+    if (prev && (prev->startAddr>=tmp->startAddr || 
+       prev->endAddr>tmp->startAddr)) {
+      fprintf(stderr, "Sorting fubar\n");
+      fubar();
+    }
+    prev=tmp;
+    tmp=tmp->next;
+  }
+  prev=0;
+  tmp = fxMesa->tmFree[1];
   while (tmp) {
-    fprintf(stderr, "TMU %d Sanity %d %d-%d\n", tmu, i, 
-           tmp->startAddr, tmp->endAddr);
-    i++;
     if (!tmp->startAddr && !tmp->endAddr) {
       fprintf(stderr, "Textures fubar\n");
       fubar();
@@ -87,7 +103,7 @@ static void sanity(fxMesaContext fxMesa, int tmu)
       fubar();
     }
     if (prev && (prev->startAddr>=tmp->startAddr || 
-       prev->endAddr>=tmp->startAddr)) {
+       prev->endAddr>tmp->startAddr)) {
       fprintf(stderr, "Sorting fubar\n");
       fubar();
     }
@@ -128,13 +144,12 @@ static void fxTMUInit(fxMesaContext fxMesa, int tmu)
 
   start=FX_grTexMinAddress(tmu);
   end=FX_grTexMaxAddress(tmu);
-  fxMesa->texStart[tmu]=start;
 
   if(fxMesa->verbose) {
     fprintf(stderr,"%s configuration:",(tmu==FX_TMU0) ? "TMU0" : "TMU1");
     fprintf(stderr,"  Lower texture memory address (%u)\n",(unsigned int)start);
     fprintf(stderr,"  Higher texture memory address (%u)\n",(unsigned int)end);
-    fprintf(stderr,"  Splitting Texture memory in 2Mb blocks:\n");
+    fprintf(stderr,"  Splitting Texture memory in 2b blocks:\n");
   }
 
   fxMesa->freeTexMem[tmu]=end-start;
@@ -182,6 +197,7 @@ static int fxTMFindStartAddr(fxMesaContext fxMesa, GLint tmu, int size)
          }
          fxTMDeleteRangeNode(fxMesa, tmp);
        }
+       fxMesa->freeTexMem[tmu]-=size;
        return result;
       }
       prev=tmp;
@@ -194,17 +210,19 @@ static int fxTMFindStartAddr(fxMesaContext fxMesa, GLint tmu, int size)
       return -1;
     }
     fxTMMoveOutTM(fxMesa, obj);
+    texSwaps++;
   }
 }
 
 static void fxTMRemoveRange(fxMesaContext fxMesa, GLint tmu, MemRange *range)
 {
-  MemRange *tmp, *prev, *next;
+  MemRange *tmp, *prev;
 
   if (range->startAddr==range->endAddr) {
     fxTMDeleteRangeNode(fxMesa, range);
     return;
   }
+  fxMesa->freeTexMem[tmu]+=range->endAddr-range->startAddr;
   prev=0;
   tmp=fxMesa->tmFree[tmu];
   while (tmp) {
@@ -254,8 +272,8 @@ static struct gl_texture_object *fxTMFindOldestObject(fxMesaContext fxMesa,
     info=fxTMGetTexInfo(tmp);
 
     if (info && info->isInTM &&
-       (info->whichTMU==tmu || info->whichTMU==FX_TMU_BOTH || 
-       info->whichTMU==FX_TMU_SPLIT)) {
+       ((info->whichTMU==tmu) || (info->whichTMU==FX_TMU_BOTH) || 
+       (info->whichTMU==FX_TMU_SPLIT))) {
       lasttime=info->lastTimeUsed;
 
       if (lasttime>bindnumber)
@@ -306,7 +324,15 @@ void fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj, G
     exit(-1);
   }
 
-  if (ti->isInTM) return;
+  if (ti->isInTM) {
+    if (ti->whichTMU==where) return;
+    if (where==FX_TMU_SPLIT || ti->whichTMU==FX_TMU_SPLIT)
+      fxTMMoveOutTM_NoLock(fxMesa, tObj);
+    else {
+      if (ti->whichTMU==FX_TMU_BOTH) return;
+      where=FX_TMU_BOTH;
+    }
+  }
 
   if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_TEXTURE)) {
      fprintf(stderr,"fxmesa: downloading %x (%d) in texture memory in %d\n",(GLuint)tObj,tObj->Name,where);
@@ -334,7 +360,7 @@ void fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj, G
                                         GR_MIPMAPLEVELMASK_BOTH,
                                         ti->mipmapLevel[l].data);
     break;
-  case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */
+  case FX_TMU_SPLIT: 
     texmemsize=(int)FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_ODD,
                                                      &(ti->info));
     ti->tm[FX_TMU0]=fxTMAddObj(fxMesa, tObj, FX_TMU0, texmemsize);
@@ -367,6 +393,39 @@ void fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj, G
                                         ti->mipmapLevel[l].data);
     }
     break;
+  case FX_TMU_BOTH:
+    texmemsize=(int)FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_BOTH,
+                                                     &(ti->info));
+    ti->tm[FX_TMU0]=fxTMAddObj(fxMesa, tObj, FX_TMU0, texmemsize);
+    fxMesa->stats.memTexUpload+=texmemsize;
+
+    texmemsize=(int)FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_BOTH,
+                                                     &(ti->info));
+    ti->tm[FX_TMU1]=fxTMAddObj(fxMesa, tObj, FX_TMU1, texmemsize);
+    fxMesa->stats.memTexUpload+=texmemsize;
+
+    for (i=FX_largeLodValue(ti->info),l=ti->minLevel;
+        i<=FX_smallLodValue(ti->info);
+        i++,l++) {
+      FX_grTexDownloadMipMapLevel_NoLock(GR_TMU0,
+                                        ti->tm[FX_TMU0]->startAddr,
+                                        FX_valueToLod(i),
+                                        FX_largeLodLog2(ti->info),
+                                        FX_aspectRatioLog2(ti->info),
+                                        ti->info.format,
+                                        GR_MIPMAPLEVELMASK_BOTH,
+                                        ti->mipmapLevel[l].data);
+
+      FX_grTexDownloadMipMapLevel_NoLock(GR_TMU1,
+                                        ti->tm[FX_TMU1]->startAddr,
+                                        FX_valueToLod(i),
+                                        FX_largeLodLog2(ti->info),
+                                        FX_aspectRatioLog2(ti->info),
+                                        ti->info.format,
+                                        GR_MIPMAPLEVELMASK_BOTH,
+                                        ti->mipmapLevel[l].data);
+    }
+    break;
   default:
     fprintf(stderr,"fx Driver: internal error in fxTMMoveInTM() -> wrong tmu (%d)\n",where);
     fxCloseHardware();
@@ -402,22 +461,27 @@ void fxTMReloadMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj,
   fxTexGetInfo(ti->mipmapLevel[0].width,ti->mipmapLevel[0].height,
               &lodlevel, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
 
+#ifdef FX_GLIDE3
+  lodlevel-=level;
+#else
+  lodlevel+=level;
+#endif
   switch(tmu) {
   case FX_TMU0:
   case FX_TMU1:
     FX_grTexDownloadMipMapLevel(tmu,
                                ti->tm[tmu]->startAddr,
-                               FX_valueToLod(FX_lodToValue(lodlevel)+level),
+                               FX_valueToLod(FX_lodToValue(lodlevel)),
                                FX_largeLodLog2(ti->info),
                                FX_aspectRatioLog2(ti->info),
                                ti->info.format,
                                GR_MIPMAPLEVELMASK_BOTH,
                                ti->mipmapLevel[level].data);
     break;
-  case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */
+  case FX_TMU_SPLIT:
     FX_grTexDownloadMipMapLevel(GR_TMU0,
                                ti->tm[GR_TMU0]->startAddr,
-                               FX_valueToLod(FX_lodToValue(lodlevel)+level),
+                               FX_valueToLod(FX_lodToValue(lodlevel)),
                                FX_largeLodLog2(ti->info),
                                FX_aspectRatioLog2(ti->info),
                                ti->info.format,
@@ -426,13 +490,33 @@ void fxTMReloadMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj,
     
     FX_grTexDownloadMipMapLevel(GR_TMU1,
                                ti->tm[GR_TMU1]->startAddr,
-                               FX_valueToLod(FX_lodToValue(lodlevel)+level),
+                               FX_valueToLod(FX_lodToValue(lodlevel)),
                                FX_largeLodLog2(ti->info),
                                FX_aspectRatioLog2(ti->info),
                                ti->info.format,
                                GR_MIPMAPLEVELMASK_EVEN,
                                ti->mipmapLevel[level].data);
     break;
+  case FX_TMU_BOTH:
+    FX_grTexDownloadMipMapLevel(GR_TMU0,
+                               ti->tm[GR_TMU0]->startAddr,
+                               FX_valueToLod(FX_lodToValue(lodlevel)),
+                               FX_largeLodLog2(ti->info),
+                               FX_aspectRatioLog2(ti->info),
+                               ti->info.format,
+                               GR_MIPMAPLEVELMASK_BOTH,
+                               ti->mipmapLevel[level].data);
+    
+    FX_grTexDownloadMipMapLevel(GR_TMU1,
+                               ti->tm[GR_TMU1]->startAddr,
+                               FX_valueToLod(FX_lodToValue(lodlevel)),
+                               FX_largeLodLog2(ti->info),
+                               FX_aspectRatioLog2(ti->info),
+                               ti->info.format,
+                               GR_MIPMAPLEVELMASK_BOTH,
+                               ti->mipmapLevel[level].data);
+    break;
+
   default:
     fprintf(stderr,"fx Driver: internal error in fxTMReloadMipMapLevel() -> wrong tmu (%d)\n",tmu);
     fxCloseHardware();
@@ -481,7 +565,7 @@ void fxTMReloadSubMipMapLevel(fxMesaContext fxMesa,
                                       data,
                                       yoffset,yoffset+height-1);
     break;
-  case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */
+  case FX_TMU_SPLIT:
     FX_grTexDownloadMipMapLevelPartial(GR_TMU0,
                                       ti->tm[FX_TMU0]->startAddr,
                                       FX_valueToLod(FX_lodToValue(lodlevel)+level),
@@ -502,6 +586,27 @@ void fxTMReloadSubMipMapLevel(fxMesaContext fxMesa,
                                       data,
                                       yoffset,yoffset+height-1);
     break;
+  case FX_TMU_BOTH:
+    FX_grTexDownloadMipMapLevelPartial(GR_TMU0,
+                                      ti->tm[FX_TMU0]->startAddr,
+                                      FX_valueToLod(FX_lodToValue(lodlevel)+level),
+                                      FX_largeLodLog2(ti->info),
+                                      FX_aspectRatioLog2(ti->info),
+                                      ti->info.format,
+                                      GR_MIPMAPLEVELMASK_BOTH,
+                                      data,
+                                      yoffset,yoffset+height-1);
+
+    FX_grTexDownloadMipMapLevelPartial(GR_TMU1,
+                                      ti->tm[FX_TMU1]->startAddr,
+                                      FX_valueToLod(FX_lodToValue(lodlevel)+level),
+                                      FX_largeLodLog2(ti->info),
+                                      FX_aspectRatioLog2(ti->info),
+                                      ti->info.format,
+                                      GR_MIPMAPLEVELMASK_BOTH,
+                                      data,
+                                      yoffset,yoffset+height-1);
+    break;
   default:
     fprintf(stderr,"fx Driver: internal error in fxTMReloadSubMipMapLevel() -> wrong tmu (%d)\n",tmu);
     fxCloseHardware();
@@ -525,6 +630,7 @@ void fxTMMoveOutTM(fxMesaContext fxMesa, struct gl_texture_object *tObj)
     fxTMRemoveRange(fxMesa, (int)ti->whichTMU, ti->tm[ti->whichTMU]);
     break;
   case FX_TMU_SPLIT:
+  case FX_TMU_BOTH:
     fxTMRemoveRange(fxMesa, FX_TMU0, ti->tm[FX_TMU0]);
     fxTMRemoveRange(fxMesa, FX_TMU1, ti->tm[FX_TMU1]);
     break;
@@ -554,6 +660,7 @@ void fxTMFreeTexture(fxMesaContext fxMesa, struct gl_texture_object *tObj)
   }
   switch (ti->whichTMU) {
   case FX_TMU0:
+  case FX_TMU1:
     fxTMDeleteRangeNode(fxMesa, ti->tm[ti->whichTMU]);
     break;
   case FX_TMU_SPLIT:
@@ -566,12 +673,13 @@ void fxTMFreeTexture(fxMesaContext fxMesa, struct gl_texture_object *tObj)
 
 void fxTMInit(fxMesaContext fxMesa)
 {
+  fxMesa->texBindNumber=0;
+  fxMesa->tmPool=0;
+
   fxTMUInit(fxMesa,FX_TMU0);
 
   if(fxMesa->haveTwoTMUs)
     fxTMUInit(fxMesa,FX_TMU1);
-
-  fxMesa->texBindNumber=0;
 }
 
 void fxTMClose(fxMesaContext fxMesa)
@@ -600,80 +708,11 @@ void fxTMClose(fxMesaContext fxMesa)
   }
 }
 
-void fxTMRestore_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj)
-{
-  tfxTexInfo *ti=fxTMGetTexInfo(tObj);
-  int i,l, where;
-
-  if (MESA_VERBOSE&VERBOSE_DRIVER) {
-     fprintf(stderr,"fxmesa: fxRestore(%d)\n",tObj->Name);
-  }
-
-  if (!ti->validated) {
-    fprintf(stderr,"fxDriver: internal error in fxRestore -> not validated\n");
-    fxCloseHardware();
-    exit(-1);
-  }
-
-  where=ti->whichTMU;
-  if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_TEXTURE)) {
-    fprintf(stderr,"fxmesa: reloading %x (%d) in texture memory in %d\n",
-           (GLuint)tObj, tObj->Name, where);
-  }
-
-  switch(where) {
-  case FX_TMU0:
-  case FX_TMU1:
-    for (i=FX_largeLodValue_NoLock(ti->info), l=ti->minLevel;
-        i<=FX_smallLodValue_NoLock(ti->info);
-        i++,l++)
-      if (ti->mipmapLevel[l].data)
-       FX_grTexDownloadMipMapLevel_NoLock(where,
-                                          ti->tm[where]->startAddr,
-                                          FX_valueToLod(i),
-                                          FX_largeLodLog2(ti->info),
-                                          FX_aspectRatioLog2(ti->info),
-                                          ti->info.format,
-                                          GR_MIPMAPLEVELMASK_BOTH,
-                                          ti->mipmapLevel[l].data);
-    break;
-  case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */
-    for (i=FX_largeLodValue_NoLock(ti->info),l=ti->minLevel;
-        i<=FX_smallLodValue_NoLock(ti->info);
-        i++,l++) {
-      if (ti->mipmapLevel[l].data)
-       FX_grTexDownloadMipMapLevel_NoLock(GR_TMU0,
-                                          ti->tm[FX_TMU0]->startAddr,
-                                          FX_valueToLod(i),
-                                          FX_largeLodLog2(ti->info),
-                                          FX_aspectRatioLog2(ti->info),
-                                          ti->info.format,
-                                          GR_MIPMAPLEVELMASK_ODD,
-                                          ti->mipmapLevel[l].data);
-      if (ti->mipmapLevel[l].data)
-       FX_grTexDownloadMipMapLevel_NoLock(GR_TMU1,
-                                          ti->tm[FX_TMU1]->startAddr,
-                                          FX_valueToLod(i),
-                                          FX_largeLodLog2(ti->info),
-                                          FX_aspectRatioLog2(ti->info),
-                                          ti->info.format,
-                                          GR_MIPMAPLEVELMASK_EVEN,
-                                          ti->mipmapLevel[l].data);
-    }
-    break;
-  default:
-    fprintf(stderr,"fxDriver: internal error in fxRestore -> bad tmu (%d)\n",
-           where);
-    fxCloseHardware();
-    exit(-1);
-  }
-}
-
 void
-fxTMRestoreTextures(fxMesaContext ctx) {
+fxTMRestoreTextures_NoLock(fxMesaContext ctx) {
   tfxTexInfo *ti;
   struct gl_texture_object *tObj;
-  int i;
+  int i, where;
 
   tObj=ctx->glCtx->Shared->TexObjectList;
   while (tObj) {
@@ -682,11 +721,13 @@ fxTMRestoreTextures(fxMesaContext ctx) {
       for (i=0; i<MAX_TEXTURE_UNITS; i++)
        if (ctx->glCtx->Texture.Unit[i].Current==tObj) {
          /* Force the texture onto the board, as it could be in use */
-         fxTMRestore_NoLock(ctx, tObj);
+         where=ti->whichTMU;
+         ti->whichTMU=FX_TMU_NONE;
+         fxTMMoveInTM_NoLock(ctx, tObj, where);
          break;
        }
       if (i==MAX_TEXTURE_UNITS) /* Mark the texture as off the board */
-       fxTMMoveOutTM(ctx, tObj);
+       fxTMMoveOutTM_NoLock(ctx, tObj);
     }
     tObj=tObj->Next;
   }