⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fxtexman.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Mesa 3-D graphics library * Version:  4.0 * * 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"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL * 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. *//* Authors: *    David Bucciarelli *    Brian Paul *    Daryll Strauss *    Keith Whitwell *    Daniel Borca *    Hiroshi Morii *//* fxtexman.c - 3Dfx VooDoo texture memory functions */#ifdef HAVE_CONFIG_H#include "conf.h"#endif#if defined(FX)#include "hash.h"#include "fxdrv.h"int texSwaps = 0;static FxU32 texBoundMask;#define FX_2MB_SPLIT 0x200000static struct gl_texture_object *fxTMFindOldestObject(fxMesaContext fxMesa,						      int tmu);#ifdef TEXSANITYstatic voidfubar(){}  /* Sanity Check */static voidsanity(fxMesaContext fxMesa){   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;   }}#endifstatic MemRange *fxTMNewRangeNode(fxMesaContext fxMesa, FxU32 start, FxU32 end){   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;}#if 1#define fxTMDeleteRangeNode(fxMesa, range) \   do {                                    \       range->next = fxMesa->tmPool;       \       fxMesa->tmPool = range;             \   } while (0);#elsestatic voidfxTMDeleteRangeNode(fxMesaContext fxMesa, MemRange * range){   range->next = fxMesa->tmPool;   fxMesa->tmPool = range;}#endifstatic voidfxTMUInit(fxMesaContext fxMesa, int tmu){   MemRange *tmn, *last;   FxU32 start, end, blockstart, blockend, chunk;   start = grTexMinAddress(tmu);   end = grTexMaxAddress(tmu);   chunk = (fxMesa->type >= GR_SSTTYPE_Banshee) ? (end - start) : FX_2MB_SPLIT;   if (fxMesa->verbose) {      fprintf(stderr, "Voodoo TMU%d configuration:\n", tmu);   }   fxMesa->freeTexMem[tmu] = end - start;   fxMesa->tmFree[tmu] = NULL;   last = 0;   blockstart = start;   while (blockstart < end) {      if (blockstart + chunk > end)	 blockend = end;      else	 blockend = blockstart + chunk;      if (fxMesa->verbose)	 fprintf(stderr, "Voodoo   %08u-%08u\n",		 (unsigned int) blockstart, (unsigned int) blockend);      tmn = fxTMNewRangeNode(fxMesa, blockstart, blockend);      tmn->next = NULL;      if (last)	 last->next = tmn;      else	 fxMesa->tmFree[tmu] = tmn;      last = tmn;      blockstart += chunk;   }}static intfxTMFindStartAddr(fxMesaContext fxMesa, GLint tmu, int size){   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;      }      /* 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++;   }}int fxTMCheckStartAddr (fxMesaContext fxMesa, GLint tmu, tfxTexInfo *ti){ MemRange *tmp; int size; if (fxMesa->HaveTexUma) {    return FXTRUE; } size = grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info)); tmp = fxMesa->tmFree[tmu]; while (tmp) {       if (tmp->endAddr - tmp->startAddr >= size) { /* Fits here */          return FXTRUE;       }       tmp = tmp->next; } return FXFALSE;}static voidfxTMRemoveRange(fxMesaContext fxMesa, GLint tmu, MemRange * range){   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 struct gl_texture_object *fxTMFindOldestObject(fxMesaContext fxMesa, int tmu){   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 MemRange *fxTMAddObj(fxMesaContext fxMesa,	   struct gl_texture_object *tObj, GLint tmu, int texmemsize){   FxI32 startAddr;   MemRange *range;   startAddr = fxTMFindStartAddr(fxMesa, tmu, texmemsize);   if (startAddr < 0)      return 0;   range = fxTMNewRangeNode(fxMesa, startAddr, startAddr + texmemsize);   return range;}/* External Functions */voidfxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj,		    GLint where){   tfxTexInfo *ti = fxTMGetTexInfo(tObj);   int i, l;   int texmemsize;   if (TDFX_DEBUG & VERBOSE_DRIVER) {      fprintf(stderr, "fxTMMoveInTM_NoLock(%d)\n", tObj->Name);   }   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));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -