From 48770fb2a06190744ec7d3832cf0354edd6ee0ce Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Tue, 10 Jun 2003 19:24:00 +0000 Subject: [PATCH] Make texture policies explicit. Never keep banner textures loaded. We'll be using enough memory with the preloads, and it's not needed. --- stepmania/src/Banner.cpp | 1 + stepmania/src/RageTexture.cpp | 2 + stepmania/src/RageTexture.h | 4 +- stepmania/src/RageTextureManager.cpp | 97 +++++++++++++++++++++++----- stepmania/src/RageTextureManager.h | 10 +-- 5 files changed, 91 insertions(+), 23 deletions(-) diff --git a/stepmania/src/Banner.cpp b/stepmania/src/Banner.cpp index 67b9093b6c..ebcd0ad699 100644 --- a/stepmania/src/Banner.cpp +++ b/stepmania/src/Banner.cpp @@ -44,6 +44,7 @@ bool Banner::Load( RageTextureID ID ) m_fPercentScrolling = 0; m_bScrolling = false; + TEXTUREMAN->VolatileTexture( ID ); return CroppedSprite::Load( ID ); }; diff --git a/stepmania/src/RageTexture.cpp b/stepmania/src/RageTexture.cpp index f09c51ab09..bdb1519dda 100644 --- a/stepmania/src/RageTexture.cpp +++ b/stepmania/src/RageTexture.cpp @@ -83,6 +83,8 @@ RageTexture::RageTexture( RageTextureID name ): // LOG->Trace( "RageTexture::RageTexture()" ); m_iRefCount = 1; + m_Policy = TEX_DEFAULT; + m_bWasUsed = false; // SetActualID(); m_iSourceWidth = m_iSourceHeight = 0; diff --git a/stepmania/src/RageTexture.h b/stepmania/src/RageTexture.h index ee12e9b1bb..553d356138 100644 --- a/stepmania/src/RageTexture.h +++ b/stepmania/src/RageTexture.h @@ -83,8 +83,10 @@ public: const RectF *GetTextureCoordRect( int frameNo ) const; int GetNumFrames() const { return m_iFramesWide*m_iFramesHigh; } + /* Used by RageTextureManager: */ + enum TexPolicy { TEX_DEFAULT, TEX_CACHED, TEX_VOLATILE } m_Policy; int m_iRefCount; - bool m_bCacheThis; + bool m_bWasUsed; /* The ID that we were asked to load: */ const RageTextureID &GetID() const { return m_ID; } diff --git a/stepmania/src/RageTextureManager.cpp b/stepmania/src/RageTextureManager.cpp index 5eefc4ee17..e651c26580 100644 --- a/stepmania/src/RageTextureManager.cpp +++ b/stepmania/src/RageTextureManager.cpp @@ -10,17 +10,38 @@ ----------------------------------------------------------------------------- */ - -//----------------------------------------------------------------------------- -// Includes -//----------------------------------------------------------------------------- +/* Texture policies: + * + * Default: When DelayedDelete is off, delete unused textures immediately. + * When on, only delete textures when we change themes, on DoDelayedDelete(). + * This is what you get if you call LoadTexture() on a texture that isn't + * loaded. + * + * Cached: When DelayedDelete is off, delete unused textures when we change screens. + * When on, treat as Default. This is used to precache textures that aren't + * loaded immediately; use CacheTexture. + * + * Volatile: Delete unused textures once they've been used at least once. Ignore + * DelayedDelete. + * + * This is for banners. We don't want to load all low-quality banners in + * memory at once, since it might be ten megs of textures, and we don't + * *have* to, since we can reload them very quickly. We don't want to keep + * high quality textures in memory, either, although it's unlikely that a + * player could actually view all banners long enough to transition to them + * all in the course of one song select screen. + * + * If a texture is already loaded with a different policy, loading it again with + * Default is normal; keep the original policy. Other cases generally shouldn't + * happen, so warn and keep the original policy. + */ + #include "RageTextureManager.h" #include "RageBitmapTexture.h" #include "arch/MovieTexture/MovieTexture.h" #include "RageUtil.h" #include "RageLog.h" #include "RageException.h" -#include RageTextureManager* TEXTUREMAN = NULL; @@ -34,9 +55,6 @@ static CString GetExtension(const CString &fn) } -//----------------------------------------------------------------------------- -// constructor/destructor -//----------------------------------------------------------------------------- RageTextureManager::RageTextureManager() { } @@ -94,7 +112,7 @@ void RageTextureManager::RegisterTexture( RageTextureID ID, RageTexture *pTextur } // Load and unload textures from disk. -RageTexture* RageTextureManager::LoadTexture( RageTextureID ID ) +RageTexture* RageTextureManager::LoadTextureInternal( RageTextureID ID ) { Checkpoint( ssprintf( "RageTextureManager::LoadTexture(%s).", ID.filename.c_str() ) ); @@ -127,10 +145,32 @@ RageTexture* RageTextureManager::LoadTexture( RageTextureID ID ) return pTexture; } +/* Load a normal texture. Use this call to actually use a texture. */ +RageTexture* RageTextureManager::LoadTexture( RageTextureID ID ) +{ + RageTexture* pTexture = LoadTextureInternal( ID ); + if( pTexture ) + pTexture->m_bWasUsed = true; + return pTexture; +} + void RageTextureManager::CacheTexture( RageTextureID ID ) { - RageTexture* pTexture = LoadTexture( ID ); - pTexture->m_bCacheThis |= true; + RageTexture* pTexture = LoadTextureInternal( ID ); + if( pTexture->m_Policy == RageTexture::TEX_DEFAULT ) + pTexture->m_Policy = RageTexture::TEX_CACHED; + else if( pTexture->m_Policy != RageTexture::TEX_CACHED ) + LOG->Warn( "RageTextureManager::CacheTexture(%s): texture is %i, which?", ID.filename.c_str()); + UnloadTexture( pTexture ); +} + +void RageTextureManager::VolatileTexture( RageTextureID ID ) +{ + RageTexture* pTexture = LoadTextureInternal( ID ); + if( pTexture->m_Policy == RageTexture::TEX_DEFAULT ) + pTexture->m_Policy = RageTexture::TEX_VOLATILE; + else if( pTexture->m_Policy != RageTexture::TEX_VOLATILE ) + LOG->Warn( "RageTextureManager::VolatileTexture(%s): texture is %i, which?", ID.filename.c_str()); UnloadTexture( pTexture ); } @@ -153,10 +193,12 @@ void RageTextureManager::UnloadTexture( RageTexture *t ) if( t->IsAMovie() ) bDeleteThis = true; - /* If m_bDelayedDelete, keep all textures around until we GC. If m_bCacheThis, - * keep this individual texture, even if m_bDelayedDelete is off. (Would - * "m_bDelayedDelete" be clearer as "m_bCacheAll"?) */ - if( !m_bDelayedDelete && !t->m_bCacheThis ) + /* Delete normal textures immediately unless m_bDelayedDelete is is on. */ + if( t->m_Policy == RageTexture::TEX_DEFAULT && !m_bDelayedDelete ) + bDeleteThis = true; + + /* Delete volatile textures after they've been used at least once. */ + if( t->m_bWasUsed ) bDeleteThis = true; if( bDeleteThis ) @@ -200,8 +242,29 @@ void RageTextureManager::GarbageCollect( GCType type ) continue; /* Can't unload textures that are still referenced. */ bool bDeleteThis = false; - if( type==cached_textures && !m_bDelayedDelete ) - bDeleteThis = true; + if( type==screen_changed ) + { + switch( t->m_Policy ) + { + case RageTexture::TEX_DEFAULT: + /* If m_bDelayedDelete, wait until delayed_delete. If !m_bDelayedDelete, + * it should have been deleted when it reached no references, but we + * might have just changed the preference. */ + if( !m_bDelayedDelete ) + bDeleteThis = true; + break; + case RageTexture::TEX_CACHED: + if( !m_bDelayedDelete ) + bDeleteThis = true; + break; + case RageTexture::TEX_VOLATILE: + bDeleteThis = true; + break; + default: ASSERT(0); + } + } + + /* This happens when we change themes; free all textures. */ if( type==delayed_delete ) bDeleteThis = true; diff --git a/stepmania/src/RageTextureManager.h b/stepmania/src/RageTextureManager.h index a70eb5a067..92959116a1 100644 --- a/stepmania/src/RageTextureManager.h +++ b/stepmania/src/RageTextureManager.h @@ -15,9 +15,6 @@ #include -//----------------------------------------------------------------------------- -// RageTextureManager Class Declarations -//----------------------------------------------------------------------------- class RageTextureManager { public: @@ -29,6 +26,7 @@ public: bool IsTextureRegistered( RageTextureID ID ) const; void RegisterTexture( RageTextureID ID, RageTexture *p ); void CacheTexture( RageTextureID ID ); + void VolatileTexture( RageTextureID ID ); void UnloadTexture( RageTexture *t ); void ReloadAll(); @@ -38,7 +36,7 @@ public: int GetMaxTextureResolution() { return m_iMaxTextureResolution; }; // call this between Screens - void DeleteCachedTextures() { GarbageCollect(cached_textures); } + void DeleteCachedTextures() { GarbageCollect(screen_changed); } // call this on switch theme void DoDelayedDelete() { GarbageCollect(delayed_delete); } @@ -50,13 +48,15 @@ public: protected: void DeleteTexture( RageTexture *t ); - enum GCType { cached_textures, delayed_delete }; + enum GCType { screen_changed, delayed_delete }; void GarbageCollect( GCType type ); int m_iTextureColorDepth; bool m_bDelayedDelete; int m_iMaxTextureResolution; + RageTexture* LoadTextureInternal( RageTextureID ID ); + std::map m_mapPathToTexture; };