cleanup and some changes towards GL_ARB_point_sprite (two-zero)
[mesa.git] / src / mesa / drivers / glide / fxtexman.c
index 2e989a04b4105b5c9cc2e9eecc79bc83db33743a..d83c7e3a6259547e5f0fd8004593a54885e6becd 100644 (file)
@@ -1,9 +1,8 @@
-
 /*
  * Mesa 3-D graphics library
- * Version:  3.3
+ * Version:  4.0
  *
- * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the
- * terms stated above.
- *
- * Thank you for your contribution, David!
- *
- * Please make note of the above copyright/license statement.  If you
- * contributed code or bug fixes to this code under the previous (GNU
- * Library) license and object to the new license, your code will be
- * removed at your request.  Please see the Mesa docs/COPYRIGHT file
- * for more information.
- *
- * Additional Mesa/3Dfx driver developers:
- *   Daryll Strauss <daryll@precisioninsight.com>
- *   Keith Whitwell <keith@precisioninsight.com>
- *
- * See fxapi.h for more revision/author details.
  */
 
+/* Authors:
+ *    David Bucciarelli
+ *    Brian Paul
+ *    Daryll Strauss
+ *    Keith Whitwell
+ *    Daniel Borca
+ *    Hiroshi Morii
+ */
 
 /* fxtexman.c - 3Dfx VooDoo texture memory functions */
 
@@ -54,6 +43,7 @@
 #include "fxdrv.h"
 
 int texSwaps = 0;
+static FxU32 texBoundMask;
 
 #define FX_2MB_SPLIT 0x200000
 
@@ -125,7 +115,7 @@ fxTMNewRangeNode(fxMesaContext fxMesa, FxU32 start, FxU32 end)
    }
    else {
       if (!(result = MALLOC(sizeof(MemRange)))) {
-        fprintf(stderr, "fxDriver: out of memory!\n");
+        fprintf(stderr, "fxTMNewRangeNode: ERROR: out of memory!\n");
         fxCloseHardware();
         exit(-1);
       }
@@ -135,30 +125,34 @@ fxTMNewRangeNode(fxMesaContext fxMesa, FxU32 start, FxU32 end)
    return result;
 }
 
+#if 1
+#define fxTMDeleteRangeNode(fxMesa, range) \
+   do {                                    \
+       range->next = fxMesa->tmPool;       \
+       fxMesa->tmPool = range;             \
+   } while (0);
+#else
 static void
 fxTMDeleteRangeNode(fxMesaContext fxMesa, MemRange * range)
 {
    range->next = fxMesa->tmPool;
    fxMesa->tmPool = range;
 }
+#endif
 
 static void
 fxTMUInit(fxMesaContext fxMesa, int tmu)
 {
    MemRange *tmn, *last;
-   FxU32 start, end, blockstart, blockend;
+   FxU32 start, end, blockstart, blockend, chunk;
 
-   start = FX_grTexMinAddress(tmu);
-   end = FX_grTexMaxAddress(tmu);
+   start = grTexMinAddress(tmu);
+   end = grTexMaxAddress(tmu);
 
+   chunk = (fxMesa->type >= GR_SSTTYPE_Banshee) ? (end - start) : FX_2MB_SPLIT;
+       
    if (fxMesa->verbose) {
-      fprintf(stderr, "Voodoo %s configuration:",
-             (tmu == FX_TMU0) ? "TMU0" : "TMU1");
-      fprintf(stderr, "Voodoo  Lower texture memory address (%u)\n",
-             (unsigned int) start);
-      fprintf(stderr, "Voodoo  Higher texture memory address (%u)\n",
-             (unsigned int) end);
-      fprintf(stderr, "Voodoo  Splitting Texture memory in 2b blocks:\n");
+      fprintf(stderr, "Voodoo TMU%d configuration:\n", tmu);
    }
 
    fxMesa->freeTexMem[tmu] = end - start;
@@ -167,17 +161,18 @@ fxTMUInit(fxMesaContext fxMesa, int tmu)
    last = 0;
    blockstart = start;
    while (blockstart < end) {
-      if (blockstart + FX_2MB_SPLIT > end)
+      if (blockstart + chunk > end)
         blockend = end;
       else
-        blockend = blockstart + FX_2MB_SPLIT;
+        blockend = blockstart + chunk;
 
       if (fxMesa->verbose)
-        fprintf(stderr, "Voodoo    %07u-%07u\n",
+        fprintf(stderr, "Voodoo   %08u-%08u\n",
                 (unsigned int) blockstart, (unsigned int) blockend);
 
       tmn = fxTMNewRangeNode(fxMesa, blockstart, blockend);
-      tmn->next = 0;
+      tmn->next = NULL;
+
 
       if (last)
         last->next = tmn;
@@ -185,7 +180,7 @@ fxTMUInit(fxMesaContext fxMesa, int tmu)
         fxMesa->tmFree[tmu] = tmn;
       last = tmn;
 
-      blockstart += FX_2MB_SPLIT;
+      blockstart += chunk;
    }
 }
 
@@ -196,6 +191,10 @@ fxTMFindStartAddr(fxMesaContext fxMesa, GLint tmu, int size)
    int result;
    struct gl_texture_object *obj;
 
+   if (fxMesa->HaveTexUma) {
+      tmu = FX_TMU0;
+   }
+
    while (1) {
       prev = 0;
       tmp = fxMesa->tmFree[tmu];
@@ -219,9 +218,12 @@ fxTMFindStartAddr(fxMesaContext fxMesa, GLint tmu, int size)
         tmp = tmp->next;
       }
       /* No free space. Discard oldest */
+      if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+        fprintf(stderr, "fxTMFindStartAddr: No free space. Discard oldest\n");
+      }
       obj = fxTMFindOldestObject(fxMesa, tmu);
       if (!obj) {
-        fprintf(stderr, "fx Driver: No space for texture\n");
+        fprintf(stderr, "fxTMFindStartAddr: ERROR: No space for texture\n");
         return -1;
       }
       fxTMMoveOutTM(fxMesa, obj);
@@ -229,11 +231,38 @@ fxTMFindStartAddr(fxMesaContext fxMesa, GLint tmu, int size)
    }
 }
 
+int fxTMCheckStartAddr (fxMesaContext fxMesa, GLint tmu, tfxTexInfo *ti)
+{
+ MemRange *prev, *tmp;
+ int size;
+ struct gl_texture_object *obj;
+
+ if (fxMesa->HaveTexUma) {
+    return FXTRUE;
+ }
+
+ size = grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
+
+ tmp = fxMesa->tmFree[tmu];
+ while (tmp) {
+       if (tmp->endAddr - tmp->startAddr >= size) { /* Fits here */
+          return FXTRUE;
+       }
+       tmp = tmp->next;
+ }
+
+ return FXFALSE;
+}
+
 static void
 fxTMRemoveRange(fxMesaContext fxMesa, GLint tmu, MemRange * range)
 {
    MemRange *tmp, *prev;
 
+   if (fxMesa->HaveTexUma) {
+      tmu = FX_TMU0;
+   }
+
    if (range->startAddr == range->endAddr) {
       fxTMDeleteRangeNode(fxMesa, range);
       return;
@@ -255,7 +284,7 @@ fxTMRemoveRange(fxMesaContext fxMesa, GLint tmu, MemRange * range)
    range->next = tmp;
    if (tmp) {
       if (range->endAddr == tmp->startAddr
-         && tmp->startAddr & (FX_2MB_SPLIT - 1)) {
+         && tmp->startAddr & texBoundMask) {
         /* Combine */
         tmp->startAddr = range->startAddr;
         fxTMDeleteRangeNode(fxMesa, range);
@@ -264,7 +293,7 @@ fxTMRemoveRange(fxMesaContext fxMesa, GLint tmu, MemRange * range)
    }
    if (prev) {
       if (prev->endAddr == range->startAddr
-         && range->startAddr & (FX_2MB_SPLIT - 1)) {
+         && range->startAddr & texBoundMask) {
         /* Combine */
         prev->endAddr = range->endAddr;
         prev->next = range->next;
@@ -282,22 +311,30 @@ static struct gl_texture_object *
 fxTMFindOldestObject(fxMesaContext fxMesa, int tmu)
 {
    GLuint age, old, lasttime, bindnumber;
+   GLfloat lowestPriority;
    tfxTexInfo *info;
-   struct gl_texture_object *obj, *tmp;
+   struct gl_texture_object *obj, *tmp, *lowestPriorityObj;
 
    tmp = fxMesa->glCtx->Shared->TexObjectList;
    if (!tmp)
       return 0;
-   obj = 0;
+   obj = NULL;
    old = 0;
 
+   lowestPriorityObj = NULL;
+   lowestPriority = 1.0F;
+
    bindnumber = fxMesa->texBindNumber;
    while (tmp) {
       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) ||
+          fxMesa->HaveTexUma
+         )
+        ) {
         lasttime = info->lastTimeUsed;
 
         if (lasttime > bindnumber)
@@ -309,17 +346,37 @@ fxTMFindOldestObject(fxMesaContext fxMesa, int tmu)
            old = age;
            obj = tmp;
         }
+
+         /* examine priority */
+         if (tmp->Priority < lowestPriority) {
+            lowestPriority = tmp->Priority;
+            lowestPriorityObj = tmp;
+         }
       }
       tmp = tmp->Next;
    }
-   return obj;
+
+   if (lowestPriorityObj != NULL) {
+       if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+          fprintf(stderr, "fxTMFindOldestObject: %d pri=%f\n", lowestPriorityObj->Name, lowestPriority);
+       }
+       return lowestPriorityObj;
+   }
+   else {
+       if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+          if (obj != NULL) {
+             fprintf(stderr, "fxTMFindOldestObject: %d age=%d\n", obj->Name, old);
+          }
+       }
+       return obj;
+   }
 }
 
 static MemRange *
 fxTMAddObj(fxMesaContext fxMesa,
           struct gl_texture_object *tObj, GLint tmu, int texmemsize)
 {
-   FxU32 startAddr;
+   FxI32 startAddr;
    MemRange *range;
 
    startAddr = fxTMFindStartAddr(fxMesa, tmu, texmemsize);
@@ -339,15 +396,14 @@ fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
    int i, l;
    int texmemsize;
 
-   if (MESA_VERBOSE & VERBOSE_DRIVER) {
-      fprintf(stderr, "fxmesa: fxTMMoveInTM(%d)\n", tObj->Name);
+   if (TDFX_DEBUG & VERBOSE_DRIVER) {
+      fprintf(stderr, "fxTMMoveInTM_NoLock(%d)\n", tObj->Name);
    }
 
    fxMesa->stats.reqTexUpload++;
 
    if (!ti->validated) {
-      fprintf(stderr,
-             "fx Driver: internal error in fxTMMoveInTM() -> not validated\n");
+      fprintf(stderr, "fxTMMoveInTM_NoLock: INTERNAL ERROR: not validated\n");
       fxCloseHardware();
       exit(-1);
    }
@@ -364,9 +420,9 @@ fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
       }
    }
 
-   if (MESA_VERBOSE & (VERBOSE_DRIVER | VERBOSE_TEXTURE)) {
-      fprintf(stderr, "fxmesa: downloading %x (%d) in texture memory in %d\n",
-             (GLuint) tObj, tObj->Name, where);
+   if (TDFX_DEBUG & (VERBOSE_DRIVER | VERBOSE_TEXTURE)) {
+      fprintf(stderr, "fxTMMoveInTM_NoLock: downloading %p (%d) in texture memory in %d\n",
+                     (void *)tObj, tObj->Name, where);
    }
 
    ti->whichTMU = (FxU32) where;
@@ -374,16 +430,14 @@ fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
    switch (where) {
    case FX_TMU0:
    case FX_TMU1:
-      texmemsize =
-        (int) FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_BOTH,
-                                                &(ti->info));
+      texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
       ti->tm[where] = fxTMAddObj(fxMesa, tObj, where, texmemsize);
       fxMesa->stats.memTexUpload += texmemsize;
 
       for (i = FX_largeLodValue(ti->info), l = ti->minLevel;
           i <= FX_smallLodValue(ti->info); i++, l++) {
-        struct gl_texture_image *texImage = tObj->Image[l];
-        FX_grTexDownloadMipMapLevel_NoLock(where,
+        struct gl_texture_image *texImage = tObj->Image[0][l];
+        grTexDownloadMipMapLevel(where,
                                            ti->tm[where]->startAddr,
                                            FX_valueToLod(i),
                                            FX_largeLodLog2(ti->info),
@@ -394,23 +448,19 @@ fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
       }
       break;
    case FX_TMU_SPLIT:
-      texmemsize =
-        (int) FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_ODD,
-                                                &(ti->info));
+      texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_ODD, &(ti->info));
       ti->tm[FX_TMU0] = fxTMAddObj(fxMesa, tObj, FX_TMU0, texmemsize);
       fxMesa->stats.memTexUpload += texmemsize;
 
-      texmemsize =
-        (int) FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_EVEN,
-                                                &(ti->info));
+      texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_EVEN, &(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++) {
-        struct gl_texture_image *texImage = tObj->Image[l];
+        struct gl_texture_image *texImage = tObj->Image[0][l];
 
-        FX_grTexDownloadMipMapLevel_NoLock(GR_TMU0,
+        grTexDownloadMipMapLevel(GR_TMU0,
                                            ti->tm[FX_TMU0]->startAddr,
                                            FX_valueToLod(i),
                                            FX_largeLodLog2(ti->info),
@@ -419,7 +469,7 @@ fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
                                            GR_MIPMAPLEVELMASK_ODD,
                                            texImage->Data);
 
-        FX_grTexDownloadMipMapLevel_NoLock(GR_TMU1,
+        grTexDownloadMipMapLevel(GR_TMU1,
                                            ti->tm[FX_TMU1]->startAddr,
                                            FX_valueToLod(i),
                                            FX_largeLodLog2(ti->info),
@@ -430,22 +480,18 @@ fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
       }
       break;
    case FX_TMU_BOTH:
-      texmemsize =
-        (int) FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_BOTH,
-                                                &(ti->info));
+      texmemsize = (int)grTexTextureMemRequired(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));
+      /*texmemsize = (int)grTexTextureMemRequired(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++) {
-        struct gl_texture_image *texImage = tObj->Image[l];
-        FX_grTexDownloadMipMapLevel_NoLock(GR_TMU0,
+        struct gl_texture_image *texImage = tObj->Image[0][l];
+        grTexDownloadMipMapLevel(GR_TMU0,
                                            ti->tm[FX_TMU0]->startAddr,
                                            FX_valueToLod(i),
                                            FX_largeLodLog2(ti->info),
@@ -454,7 +500,7 @@ fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
                                            GR_MIPMAPLEVELMASK_BOTH,
                                            texImage->Data);
 
-        FX_grTexDownloadMipMapLevel_NoLock(GR_TMU1,
+        grTexDownloadMipMapLevel(GR_TMU1,
                                            ti->tm[FX_TMU1]->startAddr,
                                            FX_valueToLod(i),
                                            FX_largeLodLog2(ti->info),
@@ -465,9 +511,7 @@ fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
       }
       break;
    default:
-      fprintf(stderr,
-             "fx Driver: internal error in fxTMMoveInTM() -> wrong tmu (%d)\n",
-             where);
+      fprintf(stderr, "fxTMMoveInTM_NoLock: INTERNAL ERROR: wrong tmu (%d)\n", where);
       fxCloseHardware();
       exit(-1);
    }
@@ -495,69 +539,71 @@ fxTMReloadMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj,
    tfxTexInfo *ti = fxTMGetTexInfo(tObj);
    GrLOD_t lodlevel;
    GLint tmu;
-   struct gl_texture_image *texImage = tObj->Image[level];
+   struct gl_texture_image *texImage = tObj->Image[0][level];
    tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
 
+   if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+      fprintf(stderr, "fxTMReloadMipMapLevel(%p (%d), %d)\n", (void *)tObj, tObj->Name, level);
+   }
+
    assert(mml);
+   assert(mml->width > 0);
+   assert(mml->height > 0);
+   assert(mml->glideFormat > 0);
+   assert(ti->isInTM);
 
    if (!ti->validated) {
-      fprintf(stderr,
-             "fx Driver: internal error in fxTMReloadMipMapLevel() -> not validated\n");
+      fprintf(stderr, "fxTMReloadMipMapLevel: INTERNAL ERROR: not validated\n");
       fxCloseHardware();
       exit(-1);
    }
 
    tmu = (int) ti->whichTMU;
-   fxTMMoveInTM(fxMesa, tObj, tmu);
+   fxMesa->stats.reqTexUpload++;
+   fxMesa->stats.texUpload++;
 
-   fxTexGetInfo(mml->width, mml->height,
-               &lodlevel, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+   lodlevel =  ti->info.largeLodLog2 - (level - ti->minLevel);
 
-#ifdef FX_GLIDE3
-   lodlevel -= level;
-#else
-   lodlevel += level;
-#endif
    switch (tmu) {
    case FX_TMU0:
    case FX_TMU1:
-      FX_grTexDownloadMipMapLevel(tmu,
+      grTexDownloadMipMapLevel(tmu,
                                  ti->tm[tmu]->startAddr,
-                                 FX_valueToLod(FX_lodToValue(lodlevel)),
+                                 lodlevel,
                                  FX_largeLodLog2(ti->info),
                                  FX_aspectRatioLog2(ti->info),
                                  ti->info.format,
                                  GR_MIPMAPLEVELMASK_BOTH, texImage->Data);
       break;
    case FX_TMU_SPLIT:
-      FX_grTexDownloadMipMapLevel(GR_TMU0,
+      grTexDownloadMipMapLevel(GR_TMU0,
                                  ti->tm[GR_TMU0]->startAddr,
-                                 FX_valueToLod(FX_lodToValue(lodlevel)),
+                                 lodlevel,
                                  FX_largeLodLog2(ti->info),
                                  FX_aspectRatioLog2(ti->info),
                                  ti->info.format,
                                  GR_MIPMAPLEVELMASK_ODD, texImage->Data);
 
-      FX_grTexDownloadMipMapLevel(GR_TMU1,
+      grTexDownloadMipMapLevel(GR_TMU1,
                                  ti->tm[GR_TMU1]->startAddr,
-                                 FX_valueToLod(FX_lodToValue(lodlevel)),
+                                 lodlevel,
                                  FX_largeLodLog2(ti->info),
                                  FX_aspectRatioLog2(ti->info),
                                  ti->info.format,
                                  GR_MIPMAPLEVELMASK_EVEN, texImage->Data);
       break;
    case FX_TMU_BOTH:
-      FX_grTexDownloadMipMapLevel(GR_TMU0,
+      grTexDownloadMipMapLevel(GR_TMU0,
                                  ti->tm[GR_TMU0]->startAddr,
-                                 FX_valueToLod(FX_lodToValue(lodlevel)),
+                                 lodlevel,
                                  FX_largeLodLog2(ti->info),
                                  FX_aspectRatioLog2(ti->info),
                                  ti->info.format,
                                  GR_MIPMAPLEVELMASK_BOTH, texImage->Data);
 
-      FX_grTexDownloadMipMapLevel(GR_TMU1,
+      grTexDownloadMipMapLevel(GR_TMU1,
                                  ti->tm[GR_TMU1]->startAddr,
-                                 FX_valueToLod(FX_lodToValue(lodlevel)),
+                                 lodlevel,
                                  FX_largeLodLog2(ti->info),
                                  FX_aspectRatioLog2(ti->info),
                                  ti->info.format,
@@ -565,9 +611,7 @@ fxTMReloadMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj,
       break;
 
    default:
-      fprintf(stderr,
-             "fx Driver: internal error in fxTMReloadMipMapLevel() -> wrong tmu (%d)\n",
-             tmu);
+      fprintf(stderr, "fxTMReloadMipMapLevel: INTERNAL ERROR: wrong tmu (%d)\n", tmu);
       fxCloseHardware();
       exit(-1);
    }
@@ -582,14 +626,13 @@ fxTMReloadSubMipMapLevel(fxMesaContext fxMesa,
    GrLOD_t lodlevel;
    unsigned short *data;
    GLint tmu;
-   struct gl_texture_image *texImage = tObj->Image[level];
+   struct gl_texture_image *texImage = tObj->Image[0][level];
    tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
 
    assert(mml);
 
    if (!ti->validated) {
-      fprintf(stderr,
-             "fx Driver: internal error in fxTMReloadSubMipMapLevel() -> not validated\n");
+      fprintf(stderr, "fxTMReloadSubMipMapLevel: INTERNAL ERROR: not validated\n");
       fxCloseHardware();
       exit(-1);
    }
@@ -598,7 +641,7 @@ fxTMReloadSubMipMapLevel(fxMesaContext fxMesa,
    fxTMMoveInTM(fxMesa, tObj, tmu);
 
    fxTexGetInfo(mml->width, mml->height,
-               &lodlevel, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+               &lodlevel, NULL, NULL, NULL, NULL, NULL);
 
    if ((ti->info.format == GR_TEXFMT_INTENSITY_8) ||
        (ti->info.format == GR_TEXFMT_P_8) ||
@@ -610,7 +653,7 @@ fxTMReloadSubMipMapLevel(fxMesaContext fxMesa,
    switch (tmu) {
    case FX_TMU0:
    case FX_TMU1:
-      FX_grTexDownloadMipMapLevelPartial(tmu,
+      grTexDownloadMipMapLevelPartial(tmu,
                                         ti->tm[tmu]->startAddr,
                                         FX_valueToLod(FX_lodToValue(lodlevel)
                                                       + level),
@@ -621,7 +664,7 @@ fxTMReloadSubMipMapLevel(fxMesaContext fxMesa,
                                         yoffset, yoffset + height - 1);
       break;
    case FX_TMU_SPLIT:
-      FX_grTexDownloadMipMapLevelPartial(GR_TMU0,
+      grTexDownloadMipMapLevelPartial(GR_TMU0,
                                         ti->tm[FX_TMU0]->startAddr,
                                         FX_valueToLod(FX_lodToValue(lodlevel)
                                                       + level),
@@ -631,7 +674,7 @@ fxTMReloadSubMipMapLevel(fxMesaContext fxMesa,
                                         GR_MIPMAPLEVELMASK_ODD, data,
                                         yoffset, yoffset + height - 1);
 
-      FX_grTexDownloadMipMapLevelPartial(GR_TMU1,
+      grTexDownloadMipMapLevelPartial(GR_TMU1,
                                         ti->tm[FX_TMU1]->startAddr,
                                         FX_valueToLod(FX_lodToValue(lodlevel)
                                                       + level),
@@ -642,7 +685,7 @@ fxTMReloadSubMipMapLevel(fxMesaContext fxMesa,
                                         yoffset, yoffset + height - 1);
       break;
    case FX_TMU_BOTH:
-      FX_grTexDownloadMipMapLevelPartial(GR_TMU0,
+      grTexDownloadMipMapLevelPartial(GR_TMU0,
                                         ti->tm[FX_TMU0]->startAddr,
                                         FX_valueToLod(FX_lodToValue(lodlevel)
                                                       + level),
@@ -652,7 +695,7 @@ fxTMReloadSubMipMapLevel(fxMesaContext fxMesa,
                                         GR_MIPMAPLEVELMASK_BOTH, data,
                                         yoffset, yoffset + height - 1);
 
-      FX_grTexDownloadMipMapLevelPartial(GR_TMU1,
+      grTexDownloadMipMapLevelPartial(GR_TMU1,
                                         ti->tm[FX_TMU1]->startAddr,
                                         FX_valueToLod(FX_lodToValue(lodlevel)
                                                       + level),
@@ -663,9 +706,7 @@ fxTMReloadSubMipMapLevel(fxMesaContext fxMesa,
                                         yoffset, yoffset + height - 1);
       break;
    default:
-      fprintf(stderr,
-             "fx Driver: internal error in fxTMReloadSubMipMapLevel() -> wrong tmu (%d)\n",
-             tmu);
+      fprintf(stderr, "fxTMReloadSubMipMapLevel: INTERNAL ERROR: wrong tmu (%d)\n", tmu);
       fxCloseHardware();
       exit(-1);
    }
@@ -676,9 +717,8 @@ fxTMMoveOutTM(fxMesaContext fxMesa, struct gl_texture_object *tObj)
 {
    tfxTexInfo *ti = fxTMGetTexInfo(tObj);
 
-   if (MESA_VERBOSE & VERBOSE_DRIVER) {
-      fprintf(stderr, "fxmesa: fxTMMoveOutTM(%x (%d))\n", (GLuint) tObj,
-             tObj->Name);
+   if (TDFX_DEBUG & VERBOSE_DRIVER) {
+      fprintf(stderr, "fxTMMoveOutTM(%p (%d))\n", (void *)tObj, tObj->Name);
    }
 
    if (!ti->isInTM)
@@ -695,7 +735,7 @@ fxTMMoveOutTM(fxMesaContext fxMesa, struct gl_texture_object *tObj)
       fxTMRemoveRange(fxMesa, FX_TMU1, ti->tm[FX_TMU1]);
       break;
    default:
-      fprintf(stderr, "fx Driver: internal error in fxTMMoveOutTM()\n");
+      fprintf(stderr, "fxTMMoveOutTM: INTERNAL ERROR: bad TMU (%ld)\n", ti->whichTMU);
       fxCloseHardware();
       exit(-1);
    }
@@ -710,17 +750,19 @@ fxTMFreeTexture(fxMesaContext fxMesa, struct gl_texture_object *tObj)
    tfxTexInfo *ti = fxTMGetTexInfo(tObj);
    int i;
 
+   if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+      fprintf(stderr, "fxTMFreeTexture(%p (%d))\n", (void *)tObj, tObj->Name);
+   }
+
    fxTMMoveOutTM(fxMesa, tObj);
 
    for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
-      struct gl_texture_image *texImage = tObj->Image[i];
-      if (texImage->Data) {
-        FREE(texImage->Data);
-        texImage->Data = NULL;
-      }
-      if (texImage->DriverData) {
-        FREE(texImage->DriverData);
-        texImage->DriverData = NULL;
+      struct gl_texture_image *texImage = tObj->Image[0][i];
+      if (texImage) {
+         if (texImage->DriverData) {
+            FREE(texImage->DriverData);
+            texImage->DriverData = NULL;
+         }
       }
    }
    switch (ti->whichTMU) {
@@ -742,10 +784,16 @@ fxTMInit(fxMesaContext fxMesa)
    fxMesa->texBindNumber = 0;
    fxMesa->tmPool = 0;
 
+   if (fxMesa->HaveTexUma) {
+      grEnable(GR_TEXTURE_UMA_EXT);
+   }
+
    fxTMUInit(fxMesa, FX_TMU0);
 
-   if (fxMesa->haveTwoTMUs)
+   if (!fxMesa->HaveTexUma && fxMesa->haveTwoTMUs)
       fxTMUInit(fxMesa, FX_TMU1);
+
+   texBoundMask = (fxMesa->type >= GR_SSTTYPE_Banshee) ? -1 : (FX_2MB_SPLIT - 1);
 }
 
 void