Merge branch 'master' into gallium-texture-transfer
[mesa.git] / src / mesa / drivers / glide / fxtexman.c
index b03122f8c1ba88c04dced11e9a013157feca179d..940c8fd0b97d92c9d065b6b8753ae2a61a0193aa 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id: fxtexman.c,v 1.15 2001/09/23 16:50:01 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
  * Version:  4.0
@@ -29,6 +27,8 @@
  *    Brian Paul
  *    Daryll Strauss
  *    Keith Whitwell
+ *    Daniel Borca
+ *    Hiroshi Morii
  */
 
 /* fxtexman.c - 3Dfx VooDoo texture memory functions */
 
 #if defined(FX)
 
+#include "hash.h"
 #include "fxdrv.h"
 
 int texSwaps = 0;
+static FxU32 texBoundMask;
 
 #define FX_2MB_SPLIT 0x200000
 
@@ -114,7 +116,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);
       }
@@ -124,30 +126,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;
@@ -156,17 +162,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;
@@ -174,7 +181,7 @@ fxTMUInit(fxMesaContext fxMesa, int tmu)
         fxMesa->tmFree[tmu] = tmn;
       last = tmn;
 
-      blockstart += FX_2MB_SPLIT;
+      blockstart += chunk;
    }
 }
 
@@ -185,6 +192,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];
@@ -208,9 +219,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);
@@ -218,11 +232,37 @@ fxTMFindStartAddr(fxMesaContext fxMesa, GLint tmu, int size)
    }
 }
 
+int fxTMCheckStartAddr (fxMesaContext fxMesa, GLint tmu, tfxTexInfo *ti)
+{
+ MemRange *tmp;
+ int size;
+
+ 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;
@@ -244,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);
@@ -253,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;
@@ -271,22 +311,36 @@ static struct gl_texture_object *
 fxTMFindOldestObject(fxMesaContext fxMesa, int tmu)
 {
    GLuint age, old, lasttime, bindnumber;
-   tfxTexInfo *info;
-   struct gl_texture_object *obj, *tmp;
+   GLfloat lowestPriority;
+   struct gl_texture_object *obj, *lowestPriorityObj;
+   struct _mesa_HashTable *textures = fxMesa->glCtx->Shared->TexObjects;
+   GLuint id;
 
-   tmp = fxMesa->glCtx->Shared->TexObjectList;
-   if (!tmp)
+   if (!_mesa_HashFirstEntry(textures))
       return 0;
-   obj = 0;
+
+   obj = NULL;
    old = 0;
 
+   lowestPriorityObj = NULL;
+   lowestPriority = 1.0F;
+
    bindnumber = fxMesa->texBindNumber;
-   while (tmp) {
-      info = fxTMGetTexInfo(tmp);
+
+   for (id = _mesa_HashFirstEntry(textures);
+        id;
+        id = _mesa_HashNextEntry(textures, id)) {
+      struct gl_texture_object *tmp
+         = (struct gl_texture_object *) _mesa_HashLookup(textures, id);
+      tfxTexInfo *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)
@@ -298,17 +352,36 @@ 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);
@@ -328,15 +401,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);
    }
@@ -353,9 +425,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;
@@ -363,16 +435,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),
@@ -383,23 +453,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),
@@ -408,7 +474,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),
@@ -419,22 +485,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),
@@ -443,7 +505,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),
@@ -454,9 +516,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);
    }
@@ -484,72 +544,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,
@@ -557,9 +616,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);
    }
@@ -574,14 +631,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);
    }
@@ -590,7 +646,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) ||
@@ -602,7 +658,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),
@@ -613,7 +669,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),
@@ -623,7 +679,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),
@@ -634,7 +690,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),
@@ -644,7 +700,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),
@@ -655,9 +711,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);
    }
@@ -668,9 +722,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)
@@ -687,7 +740,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);
    }
@@ -702,15 +755,15 @@ 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];
+      struct gl_texture_image *texImage = tObj->Image[0][i];
       if (texImage) {
-         if (texImage->Data) {
-            FREE(texImage->Data);
-            texImage->Data = NULL;
-         }
          if (texImage->DriverData) {
             FREE(texImage->DriverData);
             texImage->DriverData = NULL;
@@ -736,10 +789,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
@@ -772,26 +831,29 @@ fxTMClose(fxMesaContext fxMesa)
 void
 fxTMRestoreTextures_NoLock(fxMesaContext ctx)
 {
-   tfxTexInfo *ti;
-   struct gl_texture_object *tObj;
-   int i, where;
-
-   tObj = ctx->glCtx->Shared->TexObjectList;
-   while (tObj) {
-      ti = fxTMGetTexInfo(tObj);
+   struct _mesa_HashTable *textures = ctx->glCtx->Shared->TexObjects;
+   GLuint id;
+
+   for (id = _mesa_HashFirstEntry(textures);
+        id;
+        id = _mesa_HashNextEntry(textures, id)) {
+      struct gl_texture_object *tObj
+         = (struct gl_texture_object *) _mesa_HashLookup(textures, id);
+      tfxTexInfo *ti = fxTMGetTexInfo(tObj);
       if (ti && ti->isInTM) {
-        for (i = 0; i < MAX_TEXTURE_UNITS; i++)
+         int i;
+        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 */
-              where = ti->whichTMU;
+              int where = ti->whichTMU;
               fxTMMoveOutTM_NoLock(ctx, tObj);
               fxTMMoveInTM_NoLock(ctx, tObj, where);
               break;
            }
+         }
         if (i == MAX_TEXTURE_UNITS)    /* Mark the texture as off the board */
            fxTMMoveOutTM_NoLock(ctx, tObj);
       }
-      tObj = tObj->Next;
    }
 }