Basic work to support deep color channels:
[mesa.git] / src / mesa / drivers / glide / fxtexman.c
index 770f095ab8cb9edad63e7bb0b6488b4b3022d496..2ffaeadd7e0ef6fb4d07cf92d692eb0744d9512f 100644 (file)
@@ -2,9 +2,9 @@
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.1
+ * Version:  3.3
  *
- * Copyright (C) 1999  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
 
 #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,"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");
   }
 
   fxMesa->freeTexMem[tmu]=end-start;
@@ -147,7 +162,7 @@ static void fxTMUInit(fxMesaContext fxMesa, int tmu)
     else blockend=blockstart+FX_2MB_SPLIT;
 
     if(fxMesa->verbose)
-      fprintf(stderr,"    %07u-%07u\n",
+      fprintf(stderr,"Voodoo    %07u-%07u\n",
              (unsigned int)blockstart,(unsigned int)blockend);
 
     tmn=fxTMNewRangeNode(fxMesa, blockstart, blockend);
@@ -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;
@@ -545,15 +651,15 @@ void fxTMFreeTexture(fxMesaContext fxMesa, struct gl_texture_object *tObj)
 
   fxTMMoveOutTM(fxMesa, tObj);
 
-  for(i=0; i<MAX_TEXTURE_LEVELS; i++) {
-    if (ti->mipmapLevel[i].used &&
-       ti->mipmapLevel[i].translated)
+  for (i=0; i<MAX_TEXTURE_LEVELS; i++) {
+    if (ti->mipmapLevel[i].data) {
       FREE(ti->mipmapLevel[i].data);
-
-    (void)ti->mipmapLevel[i].data;
+      ti->mipmapLevel[i].data = NULL;
+    }
   }
   switch (ti->whichTMU) {
   case FX_TMU0:
+  case FX_TMU1:
     fxTMDeleteRangeNode(fxMesa, ti->tm[ti->whichTMU]);
     break;
   case FX_TMU_SPLIT:
@@ -566,12 +672,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 +707,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 +720,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;
+         fxTMMoveOutTM_NoLock(ctx, tObj);
+         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;
   }