-/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */
-
/*
* Mesa 3-D graphics library
- * Version: 3.1
+ * Version: 4.0
*
- * Copyright (C) 1999 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 */
#if defined(FX)
+#include "hash.h"
#include "fxdrv.h"
-static tfxTMFreeNode *fxTMNewTMFreeNode(FxU32 start, FxU32 end)
-{
- tfxTMFreeNode *tmn;
+int texSwaps = 0;
+static FxU32 texBoundMask;
- if(!(tmn=MALLOC(sizeof(tfxTMFreeNode)))) {
- fprintf(stderr,"fx Driver: out of memory !\n");
- fxCloseHardware();
- exit(-1);
- }
+#define FX_2MB_SPLIT 0x200000
- tmn->next=NULL;
- tmn->startAddress=start;
- tmn->endAddress=end;
+static struct gl_texture_object *fxTMFindOldestObject(fxMesaContext fxMesa,
+ int tmu);
- return tmn;
-}
-/* Notice this uses grTex{Min,Max}Address directly with FX_ because it
- is only used during initialization where the lock is already held. */
-static void fxTMUInit(fxMesaContext fxMesa, int tmu)
+#ifdef TEXSANITY
+static void
+fubar()
{
- tfxTMFreeNode *tmn,*tmntmp;
- FxU32 start,end,blockstart,blockend;
-
- start=FX_grTexMinAddress(tmu);
- end=FX_grTexMaxAddress(tmu);
-
- 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");
- }
-
- fxMesa->freeTexMem[tmu]=end-start;
- fxMesa->tmFree[tmu]=NULL;
- fxMesa->tmAlloc[tmu]=NULL;
-
- blockstart=start;
- while(blockstart<=end) {
- if(blockstart+0x1fffff>end)
- blockend=end;
- else
- blockend=blockstart+0x1fffff;
-
- if(fxMesa->verbose)
- fprintf(stderr," %07u-%07u\n",(unsigned int)blockstart,(unsigned int)blockend);
-
- tmn=fxTMNewTMFreeNode(blockstart,blockend);
-
- if(fxMesa->tmFree[tmu]) {
- for(tmntmp=fxMesa->tmFree[tmu];tmntmp->next!=NULL;tmntmp=tmntmp->next){};
- tmntmp->next=tmn;
- } else
- fxMesa->tmFree[tmu]=tmn;
-
- blockstart+=0x1fffff+1;
- }
}
-void fxTMInit(fxMesaContext fxMesa)
+ /* Sanity Check */
+static void
+sanity(fxMesaContext fxMesa)
{
- fxTMUInit(fxMesa,FX_TMU0);
-
- if(fxMesa->haveTwoTMUs)
- fxTMUInit(fxMesa,FX_TMU1);
-
- fxMesa->texBindNumber=0;
+ MemRange *tmp, *prev, *pos;
+
+ prev = 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) {
+ 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;
+ }
}
+#endif
-static struct gl_texture_object *fxTMFindOldestTMBlock(fxMesaContext fxMesa,
- tfxTMAllocNode *tmalloc,
- GLuint texbindnumber)
+static MemRange *
+fxTMNewRangeNode(fxMesaContext fxMesa, FxU32 start, FxU32 end)
{
- GLuint age,oldestage,lasttimeused;
- struct gl_texture_object *oldesttexobj;
-
- (void)fxMesa;
- oldesttexobj=tmalloc->tObj;
- oldestage=0;
-
- while(tmalloc) {
- lasttimeused=((tfxTexInfo *)(tmalloc->tObj->DriverData))->tmi.lastTimeUsed;
-
- if(lasttimeused>texbindnumber)
- age=texbindnumber+(UINT_MAX-lasttimeused+1); /* TO DO: check */
- else
- age=texbindnumber-lasttimeused;
-
- if(age>=oldestage) {
- oldestage=age;
- oldesttexobj=tmalloc->tObj;
- }
-
- tmalloc=tmalloc->next;
- }
-
- return oldesttexobj;
+ MemRange *result = 0;
+
+ if (fxMesa->tmPool) {
+ result = fxMesa->tmPool;
+ fxMesa->tmPool = fxMesa->tmPool->next;
+ }
+ else {
+ if (!(result = MALLOC(sizeof(MemRange)))) {
+ fprintf(stderr, "fxTMNewRangeNode: ERROR: out of memory!\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+ }
+ result->startAddr = start;
+ result->endAddr = end;
+ return result;
}
-static GLboolean fxTMFreeOldTMBlock(fxMesaContext fxMesa, GLint tmu)
+#if 1
+#define fxTMDeleteRangeNode(fxMesa, range) \
+ do { \
+ range->next = fxMesa->tmPool; \
+ fxMesa->tmPool = range; \
+ } while (0);
+#else
+static void
+fxTMDeleteRangeNode(fxMesaContext fxMesa, MemRange * range)
{
- struct gl_texture_object *oldesttexobj;
-
- if(!fxMesa->tmAlloc[tmu])
- return GL_FALSE;
-
- oldesttexobj=fxTMFindOldestTMBlock(fxMesa,fxMesa->tmAlloc[tmu],fxMesa->texBindNumber);
-
- fxTMMoveOutTM(fxMesa,oldesttexobj);
-
- return GL_TRUE;
+ range->next = fxMesa->tmPool;
+ fxMesa->tmPool = range;
}
+#endif
-static tfxTMFreeNode *fxTMExtractTMFreeBlock(tfxTMFreeNode *tmfree, int texmemsize,
- GLboolean *success, FxU32 *startadr)
+static void
+fxTMUInit(fxMesaContext fxMesa, int tmu)
{
- int blocksize;
-
- /* TO DO: cut recursion */
+ MemRange *tmn, *last;
+ FxU32 start, end, blockstart, blockend, chunk;
- if(!tmfree) {
- *success=GL_FALSE;
- return NULL;
- }
+ start = grTexMinAddress(tmu);
+ end = grTexMaxAddress(tmu);
- blocksize=(int)tmfree->endAddress-(int)tmfree->startAddress+1;
+ chunk = (fxMesa->type >= GR_SSTTYPE_Banshee) ? (end - start) : FX_2MB_SPLIT;
- if(blocksize==texmemsize) {
- tfxTMFreeNode *nexttmfree;
+ if (fxMesa->verbose) {
+ fprintf(stderr, "Voodoo TMU%d configuration:\n", tmu);
+ }
- *success=GL_TRUE;
- *startadr=tmfree->startAddress;
+ fxMesa->freeTexMem[tmu] = end - start;
+ fxMesa->tmFree[tmu] = NULL;
- nexttmfree=tmfree->next;
- FREE(tmfree);
+ last = 0;
+ blockstart = start;
+ while (blockstart < end) {
+ if (blockstart + chunk > end)
+ blockend = end;
+ else
+ blockend = blockstart + chunk;
- return nexttmfree;
- }
+ if (fxMesa->verbose)
+ fprintf(stderr, "Voodoo %08u-%08u\n",
+ (unsigned int) blockstart, (unsigned int) blockend);
- if(blocksize>texmemsize) {
- *success=GL_TRUE;
- *startadr=tmfree->startAddress;
+ tmn = fxTMNewRangeNode(fxMesa, blockstart, blockend);
+ tmn->next = NULL;
- tmfree->startAddress+=texmemsize;
- return tmfree;
- }
+ if (last)
+ last->next = tmn;
+ else
+ fxMesa->tmFree[tmu] = tmn;
+ last = tmn;
- tmfree->next=fxTMExtractTMFreeBlock(tmfree->next,texmemsize,success,startadr);
-
- return tmfree;
+ blockstart += chunk;
+ }
}
-static tfxTMAllocNode *fxTMGetTMBlock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
- GLint tmu, int texmemsize)
+static int
+fxTMFindStartAddr(fxMesaContext fxMesa, GLint tmu, int size)
{
- tfxTMFreeNode *newtmfree;
- tfxTMAllocNode *newtmalloc;
- GLboolean success;
- FxU32 startadr;
-
- for(;;) { /* TO DO: improve performaces */
- newtmfree=fxTMExtractTMFreeBlock(fxMesa->tmFree[tmu],texmemsize,&success,&startadr);
-
- if(success) {
- fxMesa->tmFree[tmu]=newtmfree;
-
- fxMesa->freeTexMem[tmu]-=texmemsize;
-
- if(!(newtmalloc=MALLOC(sizeof(tfxTMAllocNode)))) {
- fprintf(stderr,"fx Driver: out of memory !\n");
- fxCloseHardware();
- exit(-1);
+ MemRange *prev, *tmp;
+ int result;
+ struct gl_texture_object *obj;
+
+ if (fxMesa->HaveTexUma) {
+ tmu = FX_TMU0;
+ }
+
+ while (1) {
+ prev = 0;
+ tmp = fxMesa->tmFree[tmu];
+ while (tmp) {
+ if (tmp->endAddr - tmp->startAddr >= size) { /* Fits here */
+ result = tmp->startAddr;
+ tmp->startAddr += size;
+ if (tmp->startAddr == tmp->endAddr) { /* Empty */
+ if (prev) {
+ prev->next = tmp->next;
+ }
+ else {
+ fxMesa->tmFree[tmu] = tmp->next;
+ }
+ fxTMDeleteRangeNode(fxMesa, tmp);
+ }
+ fxMesa->freeTexMem[tmu] -= size;
+ return result;
+ }
+ prev = tmp;
+ tmp = tmp->next;
}
-
- newtmalloc->next=fxMesa->tmAlloc[tmu];
- newtmalloc->startAddress=startadr;
- newtmalloc->endAddress=startadr+texmemsize-1;
- newtmalloc->tObj=tObj;
-
- fxMesa->tmAlloc[tmu]=newtmalloc;
-
- return newtmalloc;
- }
-
- if(!fxTMFreeOldTMBlock(fxMesa,tmu)) {
- fprintf(stderr,"fx Driver: internal error in fxTMGetTMBlock()\n");
- fprintf(stderr," TMU: %d Size: %d\n",tmu,texmemsize);
-
- fxCloseHardware();
- exit(-1);
- }
- }
+ /* 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, "fxTMFindStartAddr: ERROR: No space for texture\n");
+ return -1;
+ }
+ fxTMMoveOutTM(fxMesa, obj);
+ texSwaps++;
+ }
}
-void fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint where)
+int fxTMCheckStartAddr (fxMesaContext fxMesa, GLint tmu, tfxTexInfo *ti)
{
- tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
- int i,l;
- int texmemsize;
-
- if (MESA_VERBOSE&VERBOSE_DRIVER) {
- fprintf(stderr,"fxmesa: fxTMMoveInTM(%d)\n",tObj->Name);
- }
-
- fxMesa->stats.reqTexUpload++;
-
- if(!ti->validated) {
- fprintf(stderr,"fx Driver: internal error in fxTMMoveInTM() -> not validated\n");
- fxCloseHardware();
- exit(-1);
- }
-
- if(ti->tmi.isInTM)
- return;
-
- if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_TEXTURE)) {
- fprintf(stderr,"fxmesa: downloading %x (%d) in texture memory in %d\n",(GLuint)tObj,tObj->Name,where);
- }
-
- ti->tmi.whichTMU=(FxU32)where;
-
- switch(where) {
- case FX_TMU0:
- case FX_TMU1:
- texmemsize=(int)FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_BOTH,
- &(ti->info));
- ti->tmi.tm[where]=fxTMGetTMBlock(fxMesa,tObj,where,texmemsize);
- fxMesa->stats.memTexUpload+=texmemsize;
-
- for(i=FX_largeLodValue(ti->info),l=ti->minLevel;i<=FX_smallLodValue(ti->info);i++,l++)
- FX_grTexDownloadMipMapLevel_NoLock(where,
- ti->tmi.tm[where]->startAddress,
- FX_valueToLod(i),
- FX_largeLodLog2(ti->info),
- FX_aspectRatioLog2(ti->info),
- ti->info.format,
- GR_MIPMAPLEVELMASK_BOTH,
- ti->tmi.mipmapLevel[l].data);
- break;
- case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */
- texmemsize=(int)FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_ODD,
- &(ti->info));
- ti->tmi.tm[FX_TMU0]=fxTMGetTMBlock(fxMesa,tObj,FX_TMU0,texmemsize);
- fxMesa->stats.memTexUpload+=texmemsize;
-
- texmemsize=(int)FX_grTexTextureMemRequired_NoLock(GR_MIPMAPLEVELMASK_EVEN,
- &(ti->info));
- ti->tmi.tm[FX_TMU1]=fxTMGetTMBlock(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->tmi.tm[FX_TMU0]->startAddress,
- FX_valueToLod(i),
- FX_largeLodLog2(ti->info),
- FX_aspectRatioLog2(ti->info),
- ti->info.format,
- GR_MIPMAPLEVELMASK_ODD,
- ti->tmi.mipmapLevel[l].data);
+ MemRange *tmp;
+ int size;
- FX_grTexDownloadMipMapLevel_NoLock(GR_TMU1,
- ti->tmi.tm[FX_TMU1]->startAddress,
- FX_valueToLod(i),
- FX_largeLodLog2(ti->info),
- FX_aspectRatioLog2(ti->info),
- ti->info.format,
- GR_MIPMAPLEVELMASK_EVEN,
- ti->tmi.mipmapLevel[l].data);
- }
- break;
- default:
- fprintf(stderr,"fx Driver: internal error in fxTMMoveInTM() -> wrong tmu (%d)\n",where);
- fxCloseHardware();
- exit(-1);
- }
-
- fxMesa->stats.texUpload++;
-
- ti->tmi.isInTM=GL_TRUE;
-}
+ if (fxMesa->HaveTexUma) {
+ return FXTRUE;
+ }
-void fxTMMoveInTM(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint where) {
- BEGIN_BOARD_LOCK();
- fxTMMoveInTM_NoLock(fxMesa, tObj, where);
- END_BOARD_LOCK();
-}
+ size = grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
-void fxTMReloadMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint level)
-{
- tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
- GrLOD_t lodlevel;
- GLint tmu;
-
- if(!ti->validated) {
- fprintf(stderr,"fx Driver: internal error in fxTMReloadMipMapLevel() -> not validated\n");
- fxCloseHardware();
- exit(-1);
- }
-
- tmu=(int)ti->tmi.whichTMU;
- fxTMMoveInTM(fxMesa,tObj,tmu);
-
- fxTexGetInfo(ti->tmi.mipmapLevel[0].width,ti->tmi.mipmapLevel[0].height,
- &lodlevel,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
-
- switch(tmu) {
- case FX_TMU0:
- case FX_TMU1:
- FX_grTexDownloadMipMapLevel(tmu,
- ti->tmi.tm[tmu]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
- FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
- ti->info.format,GR_MIPMAPLEVELMASK_BOTH,
- ti->tmi.mipmapLevel[level].data);
- break;
- case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */
- FX_grTexDownloadMipMapLevel(GR_TMU0,
- ti->tmi.tm[GR_TMU0]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
- FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
- ti->info.format,GR_MIPMAPLEVELMASK_ODD,
- ti->tmi.mipmapLevel[level].data);
-
- FX_grTexDownloadMipMapLevel(GR_TMU1,
- ti->tmi.tm[GR_TMU1]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
- FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
- ti->info.format,GR_MIPMAPLEVELMASK_EVEN,
- ti->tmi.mipmapLevel[level].data);
- break;
- default:
- fprintf(stderr,"fx Driver: internal error in fxTMReloadMipMapLevel() -> wrong tmu (%d)\n",tmu);
- fxCloseHardware();
- exit(-1);
- }
+ tmp = fxMesa->tmFree[tmu];
+ while (tmp) {
+ if (tmp->endAddr - tmp->startAddr >= size) { /* Fits here */
+ return FXTRUE;
+ }
+ tmp = tmp->next;
+ }
+
+ return FXFALSE;
}
-void fxTMReloadSubMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj,
- GLint level, GLint yoffset, GLint height)
+static void
+fxTMRemoveRange(fxMesaContext fxMesa, GLint tmu, MemRange * range)
{
- tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
- GrLOD_t lodlevel;
- unsigned short *data;
- GLint tmu;
-
- if(!ti->validated) {
- fprintf(stderr,"fx Driver: internal error in fxTMReloadSubMipMapLevel() -> not validated\n");
- fxCloseHardware();
- exit(-1);
- }
-
- tmu=(int)ti->tmi.whichTMU;
- fxTMMoveInTM(fxMesa,tObj,tmu);
-
- fxTexGetInfo(ti->tmi.mipmapLevel[0].width,ti->tmi.mipmapLevel[0].height,
- &lodlevel,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
-
- if((ti->info.format==GR_TEXFMT_INTENSITY_8) ||
- (ti->info.format==GR_TEXFMT_P_8) ||
- (ti->info.format==GR_TEXFMT_ALPHA_8))
- data=ti->tmi.mipmapLevel[level].data+((yoffset*ti->tmi.mipmapLevel[level].width)>>1);
- else
- data=ti->tmi.mipmapLevel[level].data+yoffset*ti->tmi.mipmapLevel[level].width;
-
- switch(tmu) {
- case FX_TMU0:
- case FX_TMU1:
- FX_grTexDownloadMipMapLevelPartial(tmu,
- ti->tmi.tm[tmu]->startAddress,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;
- case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */
- FX_grTexDownloadMipMapLevelPartial(GR_TMU0,
- ti->tmi.tm[FX_TMU0]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
- FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
- ti->info.format,GR_MIPMAPLEVELMASK_ODD,
- data,
- yoffset,yoffset+height-1);
-
- FX_grTexDownloadMipMapLevelPartial(GR_TMU1,
- ti->tmi.tm[FX_TMU1]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
- FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
- ti->info.format,GR_MIPMAPLEVELMASK_EVEN,
- data,
- yoffset,yoffset+height-1);
- break;
- default:
- fprintf(stderr,"fx Driver: internal error in fxTMReloadSubMipMapLevel() -> wrong tmu (%d)\n",tmu);
- fxCloseHardware();
- exit(-1);
- }
+ MemRange *tmp, *prev;
+
+ if (fxMesa->HaveTexUma) {
+ tmu = FX_TMU0;
+ }
+
+ if (range->startAddr == range->endAddr) {
+ fxTMDeleteRangeNode(fxMesa, range);
+ return;
+ }
+ fxMesa->freeTexMem[tmu] += range->endAddr - range->startAddr;
+ prev = 0;
+ tmp = fxMesa->tmFree[tmu];
+ while (tmp) {
+ if (range->startAddr > tmp->startAddr) {
+ prev = tmp;
+ tmp = tmp->next;
+ }
+ else
+ break;
+ }
+ /* When we create the regions, we make a split at the 2MB boundary.
+ Now we have to make sure we don't join those 2MB boundary regions
+ back together again. */
+ range->next = tmp;
+ if (tmp) {
+ if (range->endAddr == tmp->startAddr
+ && tmp->startAddr & texBoundMask) {
+ /* Combine */
+ tmp->startAddr = range->startAddr;
+ fxTMDeleteRangeNode(fxMesa, range);
+ range = tmp;
+ }
+ }
+ if (prev) {
+ if (prev->endAddr == range->startAddr
+ && range->startAddr & texBoundMask) {
+ /* Combine */
+ prev->endAddr = range->endAddr;
+ prev->next = range->next;
+ fxTMDeleteRangeNode(fxMesa, range);
+ }
+ else
+ prev->next = range;
+ }
+ else {
+ fxMesa->tmFree[tmu] = range;
+ }
}
-static tfxTMAllocNode *fxTMFreeTMAllocBlock(tfxTMAllocNode *tmalloc,
- tfxTMAllocNode *tmunalloc)
+static struct gl_texture_object *
+fxTMFindOldestObject(fxMesaContext fxMesa, int tmu)
{
- if(!tmalloc)
- return NULL;
-
- if(tmalloc==tmunalloc) {
- tfxTMAllocNode *newtmalloc;
-
- newtmalloc=tmalloc->next;
- FREE(tmalloc);
-
- return newtmalloc;
- }
-
- tmalloc->next=fxTMFreeTMAllocBlock(tmalloc->next,tmunalloc);
-
- return tmalloc;
+ GLuint age, old, lasttime, bindnumber;
+ GLfloat lowestPriority;
+ struct gl_texture_object *obj, *lowestPriorityObj;
+ struct _mesa_HashTable *textures = fxMesa->glCtx->Shared->TexObjects;
+ GLuint id;
+
+ if (!_mesa_HashFirstEntry(textures))
+ return 0;
+
+ obj = NULL;
+ old = 0;
+
+ lowestPriorityObj = NULL;
+ lowestPriority = 1.0F;
+
+ bindnumber = fxMesa->texBindNumber;
+
+ 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) ||
+ fxMesa->HaveTexUma
+ )
+ ) {
+ lasttime = info->lastTimeUsed;
+
+ if (lasttime > bindnumber)
+ age = bindnumber + (UINT_MAX - lasttime + 1); /* TO DO: check wrap around */
+ else
+ age = bindnumber - lasttime;
+
+ if (age >= old) {
+ old = age;
+ obj = tmp;
+ }
+
+ /* examine priority */
+ if (tmp->Priority < lowestPriority) {
+ lowestPriority = tmp->Priority;
+ lowestPriorityObj = tmp;
+ }
+ }
+ }
+
+ 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 tfxTMFreeNode *fxTMAddTMFree(tfxTMFreeNode *tmfree, FxU32 startadr, FxU32 endadr)
+static MemRange *
+fxTMAddObj(fxMesaContext fxMesa,
+ struct gl_texture_object *tObj, GLint tmu, int texmemsize)
{
- if(!tmfree)
- return fxTMNewTMFreeNode(startadr,endadr);
-
- if((endadr+1==tmfree->startAddress) && (tmfree->startAddress & 0x1fffff)) {
- tmfree->startAddress=startadr;
-
- return tmfree;
- }
-
- if((startadr-1==tmfree->endAddress) && (startadr & 0x1fffff)) {
- tmfree->endAddress=endadr;
+ FxI32 startAddr;
+ MemRange *range;
+
+ startAddr = fxTMFindStartAddr(fxMesa, tmu, texmemsize);
+ if (startAddr < 0)
+ return 0;
+ range = fxTMNewRangeNode(fxMesa, startAddr, startAddr + texmemsize);
+ return range;
+}
- if((tmfree->next && (endadr+1==tmfree->next->startAddress) &&
- (tmfree->next->startAddress & 0x1fffff))) {
- tfxTMFreeNode *nexttmfree;
+/* External Functions */
- tmfree->endAddress=tmfree->next->endAddress;
+void
+fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
+ GLint where)
+{
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+ int i, l;
+ int texmemsize;
- nexttmfree=tmfree->next->next;
- FREE(tmfree->next);
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxTMMoveInTM_NoLock(%d)\n", tObj->Name);
+ }
- tmfree->next=nexttmfree;
- }
+ fxMesa->stats.reqTexUpload++;
+ if (!ti->validated) {
+ fprintf(stderr, "fxTMMoveInTM_NoLock: INTERNAL ERROR: not validated\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ 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 (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;
+
+ switch (where) {
+ case FX_TMU0:
+ case FX_TMU1:
+ 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[0][l];
+ grTexDownloadMipMapLevel(where,
+ ti->tm[where]->startAddr,
+ FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH,
+ texImage->Data);
+ }
+ break;
+ case FX_TMU_SPLIT:
+ texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_ODD, &(ti->info));
+ ti->tm[FX_TMU0] = fxTMAddObj(fxMesa, tObj, FX_TMU0, texmemsize);
+ fxMesa->stats.memTexUpload += texmemsize;
+
+ 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[0][l];
+
+ grTexDownloadMipMapLevel(GR_TMU0,
+ ti->tm[FX_TMU0]->startAddr,
+ FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_ODD,
+ texImage->Data);
+
+ grTexDownloadMipMapLevel(GR_TMU1,
+ ti->tm[FX_TMU1]->startAddr,
+ FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_EVEN,
+ texImage->Data);
+ }
+ break;
+ case FX_TMU_BOTH:
+ texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
+ ti->tm[FX_TMU0] = fxTMAddObj(fxMesa, tObj, FX_TMU0, texmemsize);
+ fxMesa->stats.memTexUpload += texmemsize;
+
+ /*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[0][l];
+ grTexDownloadMipMapLevel(GR_TMU0,
+ ti->tm[FX_TMU0]->startAddr,
+ FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH,
+ texImage->Data);
+
+ grTexDownloadMipMapLevel(GR_TMU1,
+ ti->tm[FX_TMU1]->startAddr,
+ FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH,
+ texImage->Data);
+ }
+ break;
+ default:
+ fprintf(stderr, "fxTMMoveInTM_NoLock: INTERNAL ERROR: wrong tmu (%d)\n", where);
+ fxCloseHardware();
+ exit(-1);
+ }
- return tmfree;
- }
+ fxMesa->stats.texUpload++;
- if(startadr<tmfree->startAddress) {
- tfxTMFreeNode *newtmfree;
+ ti->isInTM = GL_TRUE;
+}
- newtmfree=fxTMNewTMFreeNode(startadr,endadr);
- newtmfree->next=tmfree;
- return newtmfree;
- }
+void
+fxTMMoveInTM(fxMesaContext fxMesa, struct gl_texture_object *tObj,
+ GLint where)
+{
+ BEGIN_BOARD_LOCK();
+ fxTMMoveInTM_NoLock(fxMesa, tObj, where);
+ END_BOARD_LOCK();
+}
- tmfree->next=fxTMAddTMFree(tmfree->next,startadr,endadr);
- return tmfree;
+void
+fxTMReloadMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj,
+ GLint level)
+{
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+ GrLOD_t lodlevel;
+ GLint tmu;
+ 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, "fxTMReloadMipMapLevel: INTERNAL ERROR: not validated\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ tmu = (int) ti->whichTMU;
+ fxMesa->stats.reqTexUpload++;
+ fxMesa->stats.texUpload++;
+
+ lodlevel = ti->info.largeLodLog2 - (level - ti->minLevel);
+
+ switch (tmu) {
+ case FX_TMU0:
+ case FX_TMU1:
+ grTexDownloadMipMapLevel(tmu,
+ ti->tm[tmu]->startAddr,
+ lodlevel,
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH, texImage->Data);
+ break;
+ case FX_TMU_SPLIT:
+ grTexDownloadMipMapLevel(GR_TMU0,
+ ti->tm[GR_TMU0]->startAddr,
+ lodlevel,
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_ODD, texImage->Data);
+
+ grTexDownloadMipMapLevel(GR_TMU1,
+ ti->tm[GR_TMU1]->startAddr,
+ lodlevel,
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_EVEN, texImage->Data);
+ break;
+ case FX_TMU_BOTH:
+ grTexDownloadMipMapLevel(GR_TMU0,
+ ti->tm[GR_TMU0]->startAddr,
+ lodlevel,
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH, texImage->Data);
+
+ grTexDownloadMipMapLevel(GR_TMU1,
+ ti->tm[GR_TMU1]->startAddr,
+ lodlevel,
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH, texImage->Data);
+ break;
+
+ default:
+ fprintf(stderr, "fxTMReloadMipMapLevel: INTERNAL ERROR: wrong tmu (%d)\n", tmu);
+ fxCloseHardware();
+ exit(-1);
+ }
}
-static void fxTMFreeTMBlock(fxMesaContext fxMesa, GLint tmu, tfxTMAllocNode *tmalloc)
+void
+fxTMReloadSubMipMapLevel(fxMesaContext fxMesa,
+ struct gl_texture_object *tObj,
+ GLint level, GLint yoffset, GLint height)
{
- FxU32 startadr,endadr;
-
- startadr=tmalloc->startAddress;
- endadr=tmalloc->endAddress;
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+ GrLOD_t lodlevel;
+ unsigned short *data;
+ GLint tmu;
+ struct gl_texture_image *texImage = tObj->Image[0][level];
+ tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
- fxMesa->tmAlloc[tmu]=fxTMFreeTMAllocBlock(fxMesa->tmAlloc[tmu],tmalloc);
+ assert(mml);
- fxMesa->tmFree[tmu]=fxTMAddTMFree(fxMesa->tmFree[tmu],startadr,endadr);
+ if (!ti->validated) {
+ fprintf(stderr, "fxTMReloadSubMipMapLevel: INTERNAL ERROR: not validated\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ tmu = (int) ti->whichTMU;
+ fxTMMoveInTM(fxMesa, tObj, tmu);
+
+ fxTexGetInfo(mml->width, mml->height,
+ &lodlevel, NULL, NULL, NULL, NULL, NULL);
+
+ if ((ti->info.format == GR_TEXFMT_INTENSITY_8) ||
+ (ti->info.format == GR_TEXFMT_P_8) ||
+ (ti->info.format == GR_TEXFMT_ALPHA_8))
+ data = (GLushort *) texImage->Data + ((yoffset * mml->width) >> 1);
+ else
+ data = (GLushort *) texImage->Data + yoffset * mml->width;
+
+ switch (tmu) {
+ case FX_TMU0:
+ case FX_TMU1:
+ grTexDownloadMipMapLevelPartial(tmu,
+ ti->tm[tmu]->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;
+ case FX_TMU_SPLIT:
+ 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_ODD, data,
+ yoffset, yoffset + height - 1);
- fxMesa->freeTexMem[tmu]+=endadr-startadr+1;
-}
+ 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_EVEN, data,
+ yoffset, yoffset + height - 1);
+ break;
+ case FX_TMU_BOTH:
+ 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);
-void fxTMMoveOutTM(fxMesaContext fxMesa, struct gl_texture_object *tObj)
-{
- tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
-
- if (MESA_VERBOSE&VERBOSE_DRIVER) {
- fprintf(stderr,"fxmesa: fxTMMoveOutTM(%x (%d))\n",(GLuint)tObj,tObj->Name);
- }
-
- if(!ti->tmi.isInTM)
- return;
-
- switch(ti->tmi.whichTMU) {
- case FX_TMU0:
- case FX_TMU1:
- fxTMFreeTMBlock(fxMesa,(int)ti->tmi.whichTMU,ti->tmi.tm[ti->tmi.whichTMU]);
- break;
- case FX_TMU_SPLIT:
- fxTMFreeTMBlock(fxMesa,FX_TMU0,ti->tmi.tm[FX_TMU0]);
- fxTMFreeTMBlock(fxMesa,FX_TMU1,ti->tmi.tm[FX_TMU1]);
- break;
- default:
- fprintf(stderr,"fx Driver: internal error in fxTMMoveOutTM()\n");
- fxCloseHardware();
- exit(-1);
- }
-
- ti->tmi.whichTMU=FX_TMU_NONE;
- ti->tmi.isInTM=GL_FALSE;
+ 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, "fxTMReloadSubMipMapLevel: INTERNAL ERROR: wrong tmu (%d)\n", tmu);
+ fxCloseHardware();
+ exit(-1);
+ }
}
-void fxTMFreeTexture(fxMesaContext fxMesa, struct gl_texture_object *tObj)
+void
+fxTMMoveOutTM(fxMesaContext fxMesa, struct gl_texture_object *tObj)
{
- tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
- int i;
-
- fxTMMoveOutTM(fxMesa,tObj);
-
- for(i=0;i<MAX_TEXTURE_LEVELS;i++) {
- if(ti->tmi.mipmapLevel[i].used &&
- ti->tmi.mipmapLevel[i].translated)
- FREE(ti->tmi.mipmapLevel[i].data);
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxTMMoveOutTM(%p (%d))\n", (void *)tObj, tObj->Name);
+ }
+
+ if (!ti->isInTM)
+ return;
+
+ switch (ti->whichTMU) {
+ case FX_TMU0:
+ case FX_TMU1:
+ 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;
+ default:
+ fprintf(stderr, "fxTMMoveOutTM: INTERNAL ERROR: bad TMU (%ld)\n", ti->whichTMU);
+ fxCloseHardware();
+ exit(-1);
+ }
- (void)ti->tmi.mipmapLevel[i].data;
- }
+ ti->isInTM = GL_FALSE;
+ ti->whichTMU = FX_TMU_NONE;
}
-void fxTMFreeAllFreeNode(tfxTMFreeNode *fn)
+void
+fxTMFreeTexture(fxMesaContext fxMesa, struct gl_texture_object *tObj)
{
- if(!fn)
- return;
-
- if(fn->next)
- fxTMFreeAllFreeNode(fn->next);
-
- FREE(fn);
+ 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[0][i];
+ if (texImage) {
+ if (texImage->DriverData) {
+ FREE(texImage->DriverData);
+ texImage->DriverData = NULL;
+ }
+ }
+ }
+ switch (ti->whichTMU) {
+ case FX_TMU0:
+ case FX_TMU1:
+ fxTMDeleteRangeNode(fxMesa, ti->tm[ti->whichTMU]);
+ break;
+ case FX_TMU_SPLIT:
+ case FX_TMU_BOTH:
+ fxTMDeleteRangeNode(fxMesa, ti->tm[FX_TMU0]);
+ fxTMDeleteRangeNode(fxMesa, ti->tm[FX_TMU1]);
+ break;
+ }
}
-void fxTMFreeAllAllocNode(tfxTMAllocNode *an)
+void
+fxTMInit(fxMesaContext fxMesa)
{
- if(!an)
- return;
+ fxMesa->texBindNumber = 0;
+ fxMesa->tmPool = 0;
- if(an->next)
- fxTMFreeAllAllocNode(an->next);
+ if (fxMesa->HaveTexUma) {
+ grEnable(GR_TEXTURE_UMA_EXT);
+ }
- FREE(an);
-}
+ fxTMUInit(fxMesa, FX_TMU0);
-void fxTMClose(fxMesaContext fxMesa)
-{
- fxTMFreeAllFreeNode(fxMesa->tmFree[FX_TMU0]);
- fxTMFreeAllAllocNode(fxMesa->tmAlloc[FX_TMU0]);
- fxMesa->tmFree[FX_TMU0] = NULL;
- fxMesa->tmAlloc[FX_TMU0] = NULL;
- if(fxMesa->haveTwoTMUs) {
- fxTMFreeAllFreeNode(fxMesa->tmFree[FX_TMU1]);
- fxTMFreeAllAllocNode(fxMesa->tmAlloc[FX_TMU1]);
- fxMesa->tmFree[FX_TMU1] = NULL;
- fxMesa->tmAlloc[FX_TMU1] = NULL;
- }
+ if (!fxMesa->HaveTexUma && fxMesa->haveTwoTMUs)
+ fxTMUInit(fxMesa, FX_TMU1);
+
+ texBoundMask = (fxMesa->type >= GR_SSTTYPE_Banshee) ? -1 : (FX_2MB_SPLIT - 1);
}
-void fxTMRestore_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj)
+void
+fxTMClose(fxMesaContext fxMesa)
{
- tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
- 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->tmi.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->tmi.mipmapLevel[l].data)
- FX_grTexDownloadMipMapLevel_NoLock(where,
- ti->tmi.tm[where]->startAddress,
- FX_valueToLod(i),
- FX_largeLodLog2(ti->info),
- FX_aspectRatioLog2(ti->info),
- ti->info.format,
- GR_MIPMAPLEVELMASK_BOTH,
- ti->tmi.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->tmi.mipmapLevel[l].data)
- FX_grTexDownloadMipMapLevel_NoLock(GR_TMU0,
- ti->tmi.tm[FX_TMU0]->startAddress,
- FX_valueToLod(i),
- FX_largeLodLog2(ti->info),
- FX_aspectRatioLog2(ti->info),
- ti->info.format,
- GR_MIPMAPLEVELMASK_ODD,
- ti->tmi.mipmapLevel[l].data);
- if (ti->tmi.mipmapLevel[l].data)
- FX_grTexDownloadMipMapLevel_NoLock(GR_TMU1,
- ti->tmi.tm[FX_TMU1]->startAddress,
- FX_valueToLod(i),
- FX_largeLodLog2(ti->info),
- FX_aspectRatioLog2(ti->info),
- ti->info.format,
- GR_MIPMAPLEVELMASK_EVEN,
- ti->tmi.mipmapLevel[l].data);
- }
- break;
- default:
- fprintf(stderr,"fxDriver: internal error in fxRestore -> bad tmu (%d)\n",
- where);
- fxCloseHardware();
- exit(-1);
- }
+ MemRange *tmp, *next;
+
+ tmp = fxMesa->tmPool;
+ while (tmp) {
+ next = tmp->next;
+ FREE(tmp);
+ tmp = next;
+ }
+ tmp = fxMesa->tmFree[FX_TMU0];
+ while (tmp) {
+ next = tmp->next;
+ FREE(tmp);
+ tmp = next;
+ }
+ if (fxMesa->haveTwoTMUs) {
+ tmp = fxMesa->tmFree[FX_TMU1];
+ while (tmp) {
+ next = tmp->next;
+ FREE(tmp);
+ tmp = next;
+ }
+ }
}
void
-fxTMRestoreTextures(fxMesaContext ctx) {
- tfxTexInfo *ti;
- struct gl_texture_object *tObj;
- int i;
-
- tObj=ctx->glCtx->Shared->TexObjectList;
- while (tObj) {
- ti=(tfxTexInfo*)tObj->DriverData;
- if (ti && ti->tmi.isInTM) {
- 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);
- break;
- }
- if (i==MAX_TEXTURE_UNITS) /* Mark the texture as off the board */
- fxTMMoveOutTM(ctx, tObj);
- }
- tObj=tObj->Next;
- }
- ctx->lastUnitsMode=0;
- fxSetupTexture_NoLock(ctx->glCtx);
+fxTMRestoreTextures_NoLock(fxMesaContext ctx)
+{
+ 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) {
+ 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 */
+ 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);
+ }
+ }
}
#else
* Need this to provide at least one external definition.
*/
-int gl_fx_dummy_function_texman(void)
+extern int gl_fx_dummy_function_texman(void);
+int
+gl_fx_dummy_function_texman(void)
{
- return 0;
+ return 0;
}
-#endif /* FX */
+#endif /* FX */