Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

GCache.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  GCache.c                                                                            */
00003 /*                                                                                      */
00004 /*  Author: John Pollard                                                                */
00005 /*  Description: Texture cache manager for glide                                        */
00006 /*                                                                                      */
00007 /*  The contents of this file are subject to the Genesis3D Public License               */
00008 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00009 /*  compliance with the License. You may obtain a copy of the License at                */
00010 /*  http://www.genesis3d.com                                                            */
00011 /*                                                                                      */
00012 /*  Software distributed under the License is distributed on an "AS IS"                 */
00013 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00014 /*  the License for the specific language governing rights and limitations              */
00015 /*  under the License.                                                                  */
00016 /*                                                                                      */
00017 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00018 /*Genesis3D Version 1.1 released November 15, 1999                            */
00019 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00020 /*                                                                                      */
00021 /****************************************************************************************/
00022 #include <Windows.h>
00023 #include <Stdio.h>
00024 #include <Assert.h>
00025 
00026 #include "GCache.h"
00027 #include "GMemMGr.h"
00028 #include "DCommon.h"
00029 #include "Glide.h"
00030 
00031 #define                                                 GCACHE_WRITELOG
00032 //#define                                                       DYNAMIC_CACHE
00033 
00034 
00035 #define GCACHE_MAX_CACHE_TYPES          128
00036 
00037 //========================================================================================================
00038 //========================================================================================================
00039 typedef struct GCache_Type
00040 {
00041         GrTexInfo       Info;
00042         int32           Log;
00043         int32           Width;                                          // Width/Height
00044         int32           Height;
00045         uint8           NumMipLevels;
00046         uint32          Size;
00047 
00048         geFloat         OneOverWidth_255;
00049         geFloat         OneOverHeight_255;
00050 
00051         GCache_Slot     *Slots;                                         // Cache slots for this Cache type
00052         int32           RefCount;                                       // How many slots are allocated 
00053         int32           UsedSlots;                                      // How many slots were used
00054 
00055 #ifdef DYNAMIC_CACHE
00056         struct GCache_Type      *PrevNext[2];           // NextPrev cache type in list
00057 #endif
00058 
00059 } GCache_Type;
00060 
00061 typedef struct GCache
00062 {
00063         char            Name[GCACHE_MAX_NAME];
00064 
00065         GMemMgr         *MemMgr;                                                        // Memory manager
00066 
00067         GCache_Type     CacheTypes[GCACHE_MAX_CACHE_TYPES];     // CacheTypes
00068 
00069         uint32          LastMemAddr;
00070 
00071         struct GCache   *SelfCheck;
00072 } GCache;
00073 
00074 typedef struct GCache_Slot
00075 {
00076 
00077         GCache_Type     *Type;
00078 
00079         uint32          MemAddr;                                        // Points to the tex mem where mem is
00080         uint32          LRU;                                            // Current LRU for cache slot
00081 
00082         void            *UserData;
00083 
00084         struct GCache_Slot      *SelfCheck;
00085 
00086 } GCache_Slot;
00087 
00088 //========================================================================================================
00089 //========================================================================================================
00090 
00091 //========================================================================================================
00092 //      GCache_Create
00093 //========================================================================================================
00094 GCache *GCache_Create(const char *Name, GMemMgr *MemMgr)
00095 {
00096         GCache          *Cache;
00097 
00098         assert(Name);
00099         assert(strlen(Name) < GCACHE_MAX_NAME);
00100         assert(MemMgr);
00101 
00102         Cache = malloc(sizeof(GCache));
00103 
00104         if (!Cache)
00105                 return NULL;
00106 
00107         memset(Cache, 0, sizeof(GCache));
00108 
00109         strcpy(Cache->Name, Name);
00110 
00111         Cache->MemMgr = MemMgr;
00112 
00113         Cache->LastMemAddr = 0xffffffff;
00114 
00115         Cache->SelfCheck = Cache;
00116 
00117         if (!GCache_Reset(Cache))
00118                 goto ExitWithError;
00119 
00120         return Cache;
00121 
00122         ExitWithError:
00123         {
00124                 if (Cache)
00125                         free(Cache);
00126 
00127                 return NULL;
00128         }
00129 }
00130 
00131 //========================================================================================================
00132 //      GCache_Destroy
00133 //========================================================================================================
00134 void GCache_Destroy(GCache *Cache)
00135 {
00136         assert(Cache);
00137 
00138         free(Cache);
00139 }
00140 
00141 //========================================================================================================
00142 //========================================================================================================
00143 geBoolean GCache_Reset(GCache *Cache)
00144 {
00145         int32                           i;
00146         GCache_Type                     *pCacheType;
00147 
00148         GCache_FreeAllSlots(Cache);
00149 
00150         for (pCacheType = Cache->CacheTypes, i=0; i<GCACHE_MAX_CACHE_TYPES; i++, pCacheType++)
00151         {
00152                 memset(pCacheType, 0, sizeof(GCache_Type));
00153 
00154                 #ifdef DYNAMIC_CACHE
00155                 // Set prev/next pointers in array
00156                         if (i > 0)
00157                                 pCacheType->PrevNext[0] = (pCacheType-1);
00158                         if (i < GCACHE_MAX_CACHE_TYPES-1)
00159                                 pCacheType->PrevNext[1] = (pCacheType+1);
00160                 #endif
00161         }
00162         
00163         return GE_TRUE;
00164 }
00165 
00166 //========================================================================================================
00167 //========================================================================================================
00168 GCache_Type *GCache_FindCacheTypeByInfo(GCache *Cache, const GrTexInfo *Info)
00169 {
00170         int32           i;
00171         GCache_Type     *pCacheType;
00172 
00173         pCacheType = Cache->CacheTypes;
00174 
00175         for (i=0; i<GCACHE_MAX_CACHE_TYPES; i++, pCacheType++)
00176         {
00177                 //uint32        Size;
00178 
00179                 if (pCacheType->RefCount == 0)                  // Nobody is using this slot yet
00180                         continue;
00181                 
00182                 if (Info->smallLod != pCacheType->Info.smallLod)
00183                         continue;
00184                 if (Info->largeLod != pCacheType->Info.largeLod)
00185                         continue;
00186                 if (Info->aspectRatio != pCacheType->Info.aspectRatio)
00187                         continue;
00188 
00189                 if (Info->format != pCacheType->Info.format)
00190                         continue;
00191 
00192                 #if 0
00193                 // Check to see if the size required to create the surface matches
00194                 Size = grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, (GrTexInfo*)Info);
00195 
00196                 //if (Size != pCacheType->Size)
00197                         continue;
00198                 #endif
00199 
00200                 return pCacheType;                                              // Found a match
00201         }
00202 
00203         return NULL;                                                            // Cache Type not found!!!
00204 }
00205 
00206 //========================================================================================================
00207 //========================================================================================================
00208 GCache_Type *GCache_InsertCacheTypeByInfo(GCache *Cache, int32 Width, int32 Height, int32 NumMipLevels, const GrTexInfo *Info)
00209 {
00210         int32           i;
00211         GCache_Type     *pCacheType;
00212 
00213         assert(NumMipLevels <= 255);
00214         assert(NumMipLevels >= 0);
00215 
00216         pCacheType = Cache->CacheTypes;
00217 
00218         for (i=0; i<GCACHE_MAX_CACHE_TYPES; i++, pCacheType++)
00219         {
00220                 if (pCacheType->RefCount == 0)          // Nobody is using this slot yet
00221                 {
00222                         assert(pCacheType->Slots == NULL);
00223                         assert(pCacheType->UsedSlots == 0);
00224                         break;
00225                 }
00226         }
00227 
00228         if (i == GCACHE_MAX_CACHE_TYPES)                        // No types left
00229                 return NULL;
00230 
00231         pCacheType->Info = *Info;
00232         pCacheType->Info.data = NULL;
00233         pCacheType->Width = Width;
00234         pCacheType->Height = Height;
00235         pCacheType->NumMipLevels = (uint8)NumMipLevels;
00236         pCacheType->Size = grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, (GrTexInfo*)Info);
00237 
00238         // Found one
00239         pCacheType->RefCount++;
00240 
00241         return pCacheType;
00242 }
00243 
00244 //========================================================================================================
00245 //      GCache_UpdateSlot
00246 //========================================================================================================
00247 geBoolean GCache_UpdateSlot(GCache *Cache, GCache_Slot *Slot, GrTexInfo *Info)
00248 {
00249         assert(GCache_SlotIsValid(Slot));
00250 
00251         grTexDownloadMipMap(GMemMgr_GetTmu(Cache->MemMgr), Slot->MemAddr, GR_MIPMAPLEVELMASK_BOTH, Info);
00252 
00253         return GE_TRUE;
00254 }
00255 
00256 //========================================================================================================
00257 //      GCache_SetTexture
00258 //========================================================================================================
00259 geBoolean GCache_SetTexture(GCache *Cache, GCache_Slot *Slot)
00260 {
00261         assert(GCache_SlotIsValid(Slot));
00262 
00263         if (Cache->LastMemAddr == Slot->MemAddr)
00264                 return GE_TRUE;
00265 
00266         grTexSource(GMemMgr_GetTmu(Cache->MemMgr), Slot->MemAddr, GR_MIPMAPLEVELMASK_BOTH, &Slot->Type->Info);
00267 
00268         Cache->LastMemAddr = Slot->MemAddr;
00269 
00270         Slot->LRU++;
00271 
00272         return GE_TRUE;
00273 }
00274 
00275 //========================================================================================================
00276 //========================================================================================================
00277 GCache_Type *GCache_TypeCreate(GCache *Cache, int32 Width, int32 Height, int32 NumMipLevels, const GrTexInfo *Info)
00278 {
00279         GCache_Type             *CacheType;
00280 
00281         CacheType = GCache_FindCacheTypeByInfo(Cache, Info);
00282 
00283         if (CacheType)
00284         {
00285                 CacheType->RefCount++;
00286                 return CacheType;
00287         }
00288 
00289         // Could not find one allready in the list, so add a new one...
00290         return GCache_InsertCacheTypeByInfo(Cache, Width, Height, NumMipLevels, Info);
00291 }
00292 
00293 //========================================================================================================
00294 //      GCache_TypeDestroy
00295 //========================================================================================================
00296 void GCache_TypeDestroy(GCache_Type *CacheType)
00297 {
00298         assert(CacheType->RefCount > 0);
00299 
00300         CacheType->RefCount--;
00301 
00302         if (CacheType->RefCount == 0)
00303         {
00304                 if (CacheType->Slots)
00305                 {
00306                         assert(CacheType->UsedSlots > 0);
00307                         free(CacheType->Slots);
00308                 }
00309                 else
00310                 {
00311                         assert(CacheType->UsedSlots == 0);
00312                 }
00313                 
00314                 CacheType->UsedSlots = 0;
00315                 CacheType->Slots = NULL;
00316         }
00317 }
00318 
00319 //========================================================================================================
00320 //      GCache_FreeAllSlots
00321 //========================================================================================================
00322 geBoolean GCache_FreeAllSlots(GCache *Cache)
00323 {
00324         int32           i;
00325         GCache_Type     *pCacheType;
00326 
00327         pCacheType = Cache->CacheTypes;
00328 
00329         for (i=0; i< GCACHE_MAX_CACHE_TYPES; i++, pCacheType++)
00330         {
00331                 assert(pCacheType->RefCount >= 0);
00332 
00333                 if (pCacheType->RefCount == 0)
00334                 {
00335                         assert(pCacheType->Slots == NULL);
00336                         assert(pCacheType->UsedSlots == 0);
00337                         continue;
00338                 }
00339 
00340                 if (pCacheType->Slots)
00341                 {
00342                         assert(pCacheType->UsedSlots > 0);
00343                         free(pCacheType->Slots);
00344                 }
00345                 else
00346                         assert(pCacheType->UsedSlots == 0);
00347 
00348                 pCacheType->Slots = NULL;
00349                 pCacheType->UsedSlots = 0;
00350         }
00351 
00352         return GE_TRUE;
00353 }
00354 
00355 //========================================================================================================
00356 //      GCache_WriteToFile
00357 //========================================================================================================
00358 geBoolean GCache_WriteToFile(GCache *Cache, const char *FileName, geBoolean Append)
00359 {
00360         int32           i;
00361         GCache_Type     *pCacheType;
00362         int32           TotalRef, TotalUsed;
00363         SYSTEMTIME      Time;
00364         FILE            *f;
00365 
00366         if (Append)
00367                 f = fopen(FileName, "a+t");
00368         else
00369                 f = fopen(FileName, "w");
00370 
00371         if (!f)
00372                 return GE_FALSE;
00373 
00374         pCacheType = Cache->CacheTypes;
00375 
00376         TotalRef = TotalUsed = 0;
00377 
00378         GetSystemTime(&Time);
00379 
00380         fprintf(f, "=======================================================\n");
00381         fprintf(f, "Date: %i/%i/%i, Time: %i:%i\n", Time.wMonth, Time.wDay, Time.wYear, Time.wHour, Time.wMinute);
00382         fprintf(f, "Cache Name: %s\n", Cache->Name);
00383         fprintf(f, "Total Memory for Cache: %6i\n", GMemMgr_GetTotalMemory(Cache->MemMgr));
00384         fprintf(f, "Free Memory for Cache: %6i\n", GMemMgr_GetFreeMemory(Cache->MemMgr));
00385         fprintf(f, "--- Slots ---\n");
00386 
00387         for (i=0; i< GCACHE_MAX_CACHE_TYPES; i++, pCacheType++)
00388         {
00389                 if (!pCacheType->RefCount)
00390                         continue;
00391 
00392                 fprintf(f, "Width: %3i, Height %3i, Mips: %2i, Ref: %4i, Used: %4i\n",
00393                         pCacheType->Width, pCacheType->Height, pCacheType->NumMipLevels, pCacheType->RefCount, pCacheType->UsedSlots);
00394 
00395                 TotalRef += pCacheType->RefCount;
00396                 TotalUsed += pCacheType->UsedSlots;
00397         }
00398 
00399         fprintf(f, "Total Ref: %4i, Total Used: %4i\n", TotalRef, TotalUsed);
00400 
00401         fclose(f);
00402 
00403         return GE_TRUE;
00404 }
00405 
00406 static  geBoolean       AppendHack = GE_FALSE;
00407 
00408 //========================================================================================================
00409 //      GCache_AdjustSlots
00410 //========================================================================================================
00411 geBoolean GCache_AdjustSlots(GCache *Cache)
00412 {
00413         GCache_Type             *pCacheType;
00414         int32                   i;
00415 
00416         GCache_FreeAllSlots(Cache);
00417 
00418         GMemMgr_Reset(Cache->MemMgr);                   // Reset the caches memory manager
00419 
00420         while(1)
00421         {
00422                 GCache_Slot     *LastSlot;
00423 
00424                 LastSlot = NULL;
00425 
00426                 pCacheType = Cache->CacheTypes;
00427 
00428                 for (i=0; i< GCACHE_MAX_CACHE_TYPES; i++, pCacheType++)
00429                 {
00430                         GCache_Slot             *pSlot;
00431                         uint32                  Size;
00432 
00433                         if (pCacheType->RefCount <= 0)
00434                         {
00435                                 assert(pCacheType->Slots == NULL);
00436                                 assert(pCacheType->UsedSlots == 0);
00437                                 continue;
00438                         }
00439 
00440                         if (pCacheType->UsedSlots >= pCacheType->RefCount)
00441                                 continue;                                       // This is all we need for this slot...
00442 
00443                         if (!pCacheType->Slots)                 // If no slots have been allocated, allocate them now...
00444                         {
00445                                 assert(pCacheType->UsedSlots == 0);
00446 
00447                                 pCacheType->Slots = malloc(sizeof(GCache_Type)*pCacheType->RefCount);
00448 
00449                                 if (!pCacheType->Slots)
00450                                         return GE_FALSE;
00451 
00452                                 memset(pCacheType->Slots, 0, sizeof(GCache_Type)*pCacheType->RefCount);
00453                         }
00454 
00455                         Size = grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &pCacheType->Info);
00456 
00457                         if (GMemMgr_GetFreeMemory(Cache->MemMgr) < Size)
00458                                 break;          // Took all available ram from memmgr.  No choice, but to stop
00459 
00460                         pSlot = &pCacheType->Slots[pCacheType->UsedSlots++];
00461                         pSlot->SelfCheck = pSlot;
00462 
00463                         pSlot->Type = pCacheType;
00464 
00465                         if (!GMemMgr_AllocMem(Cache->MemMgr, Size, &pSlot->MemAddr))
00466                         {
00467                                 pCacheType->UsedSlots--;                // Cancel last operation
00468                                 break;
00469                         }
00470 
00471                         LastSlot = pSlot;
00472                 }
00473 
00474                 if (!LastSlot)          // Nothing was allocated on that pass, so assume we are out of memory
00475                         break;
00476         }
00477 
00478         pCacheType = Cache->CacheTypes;
00479         
00480         // Go through one last time, and make sure all got allocated
00481         for (i=0; i< GCACHE_MAX_CACHE_TYPES; i++, pCacheType++)
00482         {
00483                 if (pCacheType->RefCount <= 0)
00484                 {
00485                         assert(pCacheType->Slots == NULL);
00486                         assert(pCacheType->UsedSlots == 0);
00487                         continue;
00488                 }
00489 
00490                 if (pCacheType->UsedSlots <= 0)         // Oops...
00491                         return GE_FALSE;
00492 
00493                 assert(pCacheType->Slots != NULL);
00494         }
00495 
00496 #ifdef GCACHE_WRITELOG
00497         GCache_WriteToFile(Cache, "GCache.Log", AppendHack);
00498 
00499         AppendHack = GE_TRUE;
00500 #endif
00501 
00502         return GE_TRUE;
00503 }
00504 
00505 //========================================================================================================
00506 //      GCache_SlotGetMemAddress
00507 //========================================================================================================
00508 uint32 GCache_SlotGetMemAddress(GCache_Slot *Slot)
00509 {
00510         assert(GCache_SlotIsValid(Slot));
00511 
00512         return Slot->MemAddr;
00513 }
00514 
00515 //========================================================================================================
00516 //      GCache_SlotIsValid
00517 //========================================================================================================
00518 geBoolean GCache_SlotIsValid(GCache_Slot *Slot)
00519 {
00520         if (!Slot)
00521                 return GE_FALSE;
00522 
00523         if (Slot->SelfCheck != Slot)
00524                 return GE_FALSE;
00525 
00526         return GE_TRUE;
00527 }
00528 
00529 #ifdef DYNAMIC_CACHE
00530 
00531 #define         GROW_DIR_LEFT           0
00532 #define         GROW_DIR_RIGHT          1
00533 
00534 #define         MAX_STACK                       64
00535 
00536 typedef struct
00537 {
00538         GCache_Type                     *Type;
00539         int32                           UsedSlots;
00540 } GCache_TypeStack;
00541 
00542 //========================================================================================================
00543 //      GCache_TypeGrowDir
00544 //========================================================================================================
00545 GCache_Slot *GCache_TypeGrowDir(GCache_Type *CacheType, GCache_Type *Current, int32 Dir)
00546 {
00547         uint32                          Size;
00548         int32                           UsedSlots;
00549         GCache_Type                     *Original;
00550         GCache_TypeStack        Stack[MAX_STACK], *pStack;
00551 
00552         assert(CacheType);
00553         assert(Current);
00554 
00555         Original = Current;
00556 
00557         Size = Current->Size;
00558         UsedSlots = Current->UsedSlots;
00559 
00560         pStack = Stack;
00561 
00562         // Do a test run, to see if we can make a new slot
00563         while (CacheType->Size > Size)
00564         {
00565                 // CacheType does not have enough memory, need to take more
00566 
00567                 if (pStack >= &Stack[MAX_STACK])
00568                         return NULL;            // No more stack space, oh well...
00569 
00570                 if (UsedSlots <= 1)             // Keep at least one slot used
00571                 {
00572                         pStack->Type = Current;
00573                         pStack->UsedSlots = UsedSlots;
00574                         pStack++;
00575 
00576                         Current = Current->PrevNext[Dir];
00577 
00578                         if (!Current)
00579                                 return NULL;            // Can't do it
00580 
00581                         UsedSlots = Current->UsedSlots;
00582                         continue;
00583                 }
00584 
00585                 UsedSlots--;
00586                 Size += Current->Size;
00587                 
00588                 pStack->Type = Current;
00589                 pStack->UsedSlots = UsedSlots;
00590                 pStack++;
00591         }
00592 
00593         // Go back up the stack, fixing up slots in the types we are gonna grow into...
00594         while (pStack-- > Stack)
00595         {
00596                 pStack->Type->UsedSlots = pStack->UsedSlots;
00597         }
00598         
00599         return &Original->Slots[Original->UsedSlots++];
00600 }
00601 
00602 //========================================================================================================
00603 //      GCache_TypeGrow
00604 //      Trys to grow to the left or to the right by stealing one of it's neigbors
00605 //========================================================================================================
00606 GCache_Slot *GCache_TypeGrow(GCache_Type *CacheType)
00607 {
00608         GCache_Type             **PrevNext;
00609         GCache_Slot             *Slot;
00610         int32                   Dir;
00611 
00612         PrevNext = CacheType->PrevNext;
00613 
00614         assert(PrevNext[0] || PrevNext[1]);             // At least one must be initialized
00615 
00616         if (!PrevNext[0])                                       
00617                 return GCache_TypeGrowDir(CacheType, PrevNext[1], GROW_DIR_RIGHT);
00618         if (!PrevNext[1])
00619                 return GCache_TypeGrowDir(CacheType, PrevNext[0], GROW_DIR_LEFT);
00620 
00621         // Pick the best side first (the one with the biggest texture size)
00622         if (PrevNext[GROW_DIR_LEFT]->Size > PrevNext[GROW_DIR_RIGHT]->Size)
00623                 Dir = GROW_DIR_LEFT;
00624         else
00625                 Dir = GROW_DIR_RIGHT;
00626                 
00627         Slot = GCache_TypeGrowDir(CacheType, PrevNext[Dir], Dir);
00628 
00629         if (!Slot)              // Try opposite direction
00630                 Slot = GCache_TypeGrowDir(CacheType, PrevNext[!Dir], !Dir);
00631 
00632         return Slot;
00633 }
00634 
00635 #endif
00636 
00637 //========================================================================================================
00638 //      GCache_TypeFindSlot
00639 //========================================================================================================
00640 GCache_Slot     *GCache_TypeFindSlot(GCache_Type *CacheType)
00641 {
00642         GCache_Slot             *pBestSlot, *pSlot;
00643         uint32                  BestLRU;
00644         int32                   i;
00645 
00646         assert(CacheType->Slots);
00647 
00648 #ifdef DYNAMIC_CACHE
00649         // First, try to steal a slot from one of our neigbors...
00650         // Try the biggest side first 
00651         if (pBestSlot = GCache_TypeGrow(CacheType))
00652                 goto GotIt;
00653 #endif
00654 
00655         pSlot = CacheType->Slots;
00656         pBestSlot = pSlot;
00657         BestLRU = pBestSlot->LRU;
00658 
00659         for (i=0; i< CacheType->UsedSlots; i++, pSlot++)
00660         {
00661                 if (pSlot->LRU < BestLRU)
00662                 {
00663                         pBestSlot = pSlot;
00664                         BestLRU = pSlot->LRU;
00665                 }
00666         }
00667 
00668 #ifdef DYNAMIC_CACHE
00669         GotIt:
00670 #endif
00671 
00672         pBestSlot->LRU = 0;
00673         pBestSlot->UserData = NULL;
00674 
00675         return pBestSlot;
00676 }
00677 
00678 //========================================================================================================
00679 //      GCache_SlotSetUserData
00680 //========================================================================================================
00681 void GCache_SlotSetUserData(GCache_Slot *Slot, void *UserData)
00682 {
00683         assert(GCache_SlotIsValid(Slot));
00684 
00685         Slot->UserData = UserData;
00686 }
00687 
00688 //========================================================================================================
00689 //      GCache_SlotGetUserData
00690 //========================================================================================================
00691 void *GCache_SlotGetUserData(GCache_Slot *Slot)
00692 {
00693         assert(GCache_SlotIsValid(Slot));
00694 
00695         return Slot->UserData;
00696 }
00697 
00698 //========================================================================================================
00699 //      GCache_SlotGetInfo
00700 //========================================================================================================
00701 GrTexInfo *GCache_SlotGetInfo(GCache_Slot *Slot)
00702 {
00703         assert(GCache_SlotIsValid(Slot));
00704 
00705         return &Slot->Type->Info;
00706 }
00707 
00708 //========================================================================================================
00709 //      GCache_SlotSetLRU
00710 //========================================================================================================
00711 void GCache_SlotSetLRU(GCache_Slot *Slot, uint32 LRU)
00712 {
00713         assert(GCache_SlotIsValid(Slot));
00714 
00715         Slot->LRU = LRU;
00716 }

Generated on Tue Sep 30 12:35:47 2003 for GTestAndEngine by doxygen 1.3.2