X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fglide%2Ffxtexman.c;h=940c8fd0b97d92c9d065b6b8753ae2a61a0193aa;hb=646ed82e6b2c092c6db364bf87d6881f39e83eec;hp=97577fca26afb87300c7874318fe4480b200e385;hpb=5a95679e58b3861eae5b276a1ff0b508f409f066;p=mesa.git diff --git a/src/mesa/drivers/glide/fxtexman.c b/src/mesa/drivers/glide/fxtexman.c index 97577fca26a..940c8fd0b97 100644 --- a/src/mesa/drivers/glide/fxtexman.c +++ b/src/mesa/drivers/glide/fxtexman.c @@ -1,10 +1,8 @@ -/* -*- 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"), @@ -22,26 +20,16 @@ * 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 - * Keith Whitwell - * - * 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 */ @@ -52,654 +40,821 @@ #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(startadrstartAddress) { - 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;itmi.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; iglCtx->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 @@ -709,9 +864,11 @@ fxTMRestoreTextures(fxMesaContext ctx) { * 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 */