separate "low res loaded on startup" and "low res loaded on demand" banner modes
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
#include "global.h"
|
||||
|
||||
#include "arch/arch.h"
|
||||
#include "Foreach.h"
|
||||
#include "RageDisplay.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageSurface_Load.h"
|
||||
#include "BannerCache.h"
|
||||
#include "SongCacheIndex.h"
|
||||
#include "Sprite.h"
|
||||
#include "PrefsManager.h"
|
||||
#include "RageDisplay.h"
|
||||
@@ -46,17 +48,66 @@ BannerCache *BANNERCACHE;
|
||||
|
||||
|
||||
static map<CString,RageSurface *> g_BannerPathToImage;
|
||||
static int g_iDemandRefcount = 0;
|
||||
|
||||
CString BannerCache::GetBannerCachePath( CString BannerPath )
|
||||
{
|
||||
/* Use GetHashForString, not ForFile, since we don't want to spend time
|
||||
* checking the file size and date. */
|
||||
return ssprintf( CACHE_DIR "Banners/%u", GetHashForString(BannerPath) );
|
||||
return SongCacheIndex::GetCacheFilePath( "Banners", BannerPath );
|
||||
}
|
||||
|
||||
/* If in on-demand mode, load all cached banners. This must be fast, so
|
||||
* cache files will not be created if they don't exist; that should be done
|
||||
* by CacheBanner or LoadBanner on startup. */
|
||||
void BannerCache::Demand()
|
||||
{
|
||||
++g_iDemandRefcount;
|
||||
if( g_iDemandRefcount > 1 )
|
||||
return;
|
||||
|
||||
if( PREFSMAN->m_iBannerCache != PrefsManager::BNCACHE_LOW_RES_LOAD_ON_DEMAND )
|
||||
return;
|
||||
|
||||
FOREACH_Child( &BannerData, p )
|
||||
{
|
||||
CString sBannerPath = p->m_sName;
|
||||
|
||||
if( g_BannerPathToImage.find(sBannerPath) != g_BannerPathToImage.end() )
|
||||
continue; /* already loaded */
|
||||
|
||||
const CString CachePath = GetBannerCachePath(sBannerPath);
|
||||
RageSurface *img = RageSurfaceUtils::LoadSurface( CachePath );
|
||||
if( img == NULL )
|
||||
{
|
||||
continue; /* doesn't exist */
|
||||
}
|
||||
|
||||
g_BannerPathToImage[sBannerPath] = img;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release banners loaded on demand. */
|
||||
void BannerCache::Undemand()
|
||||
{
|
||||
--g_iDemandRefcount;
|
||||
if( g_iDemandRefcount != 0 )
|
||||
return;
|
||||
|
||||
if( PREFSMAN->m_iBannerCache != PrefsManager::BNCACHE_LOW_RES_LOAD_ON_DEMAND )
|
||||
return;
|
||||
|
||||
UnloadAllBanners();
|
||||
}
|
||||
|
||||
/* If in a low-res banner mode, load a low-res banner into memory, creating
|
||||
* the cache file if necessary. Unlike CacheBanner(), the original file will
|
||||
* not be examined unless the cached banner doesn't exist, so the banner will
|
||||
* not be updated if the original file changes, for efficiency. */
|
||||
void BannerCache::LoadBanner( CString BannerPath )
|
||||
{
|
||||
if( PREFSMAN->m_iBannerCache != PrefsManager::BNCACHE_LOW_RES || BannerPath == "" )
|
||||
if( BannerPath == "" )
|
||||
return; // nothing to do
|
||||
if( PREFSMAN->m_iBannerCache != PrefsManager::BNCACHE_LOW_RES_PRELOAD &&
|
||||
PREFSMAN->m_iBannerCache != PrefsManager::BNCACHE_LOW_RES_LOAD_ON_DEMAND )
|
||||
return;
|
||||
|
||||
/* Load it. */
|
||||
@@ -205,6 +256,7 @@ struct BannerTexture: public RageTexture
|
||||
}
|
||||
};
|
||||
|
||||
/* If a banner is cached, get its ID for use. */
|
||||
RageTextureID BannerCache::LoadCachedBanner( CString BannerPath )
|
||||
{
|
||||
RageTextureID ID( GetBannerCachePath(BannerPath) );
|
||||
@@ -272,11 +324,12 @@ static inline int closest( int num, int n1, int n2 )
|
||||
return n1;
|
||||
}
|
||||
|
||||
/* We write the cache even if we won't use it, so we don't have to recache everything
|
||||
* if the memory or settings change. */
|
||||
/* Create or update the banner cache file as necessary. If in preload mode,
|
||||
* load the cache file, too. (This is done at startup.) */
|
||||
void BannerCache::CacheBanner( CString BannerPath )
|
||||
{
|
||||
if( PREFSMAN->m_iBannerCache != PrefsManager::BNCACHE_LOW_RES )
|
||||
if( PREFSMAN->m_iBannerCache != PrefsManager::BNCACHE_LOW_RES_PRELOAD &&
|
||||
PREFSMAN->m_iBannerCache != PrefsManager::BNCACHE_LOW_RES_LOAD_ON_DEMAND )
|
||||
return;
|
||||
|
||||
CHECKPOINT_M( BannerPath );
|
||||
@@ -293,12 +346,16 @@ void BannerCache::CacheBanner( CString BannerPath )
|
||||
if( BannerData.GetValue( BannerPath, "FullHash", CurFullHash ) &&
|
||||
CurFullHash == FullHash )
|
||||
{
|
||||
/* It's identical. Just load it. */
|
||||
LoadBanner( BannerPath );
|
||||
/* It's identical. Just load it, if in preload. */
|
||||
if( PREFSMAN->m_iBannerCache == PrefsManager::BNCACHE_LOW_RES_PRELOAD )
|
||||
LoadBanner( BannerPath );
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* The cache file doesn't exist, or is out of date. Cache it. This
|
||||
* will also load the cache into memory if in PRELOAD. */
|
||||
CacheBannerInternal( BannerPath );
|
||||
}
|
||||
|
||||
@@ -412,16 +469,16 @@ void BannerCache::CacheBannerInternal( CString BannerPath )
|
||||
const CString CachePath = GetBannerCachePath(BannerPath);
|
||||
RageSurfaceUtils::SaveSurface( img, CachePath );
|
||||
|
||||
if( PREFSMAN->m_iBannerCache == PrefsManager::BNCACHE_LOW_RES )
|
||||
/* If an old image is loaded, free it. */
|
||||
if( g_BannerPathToImage.find(BannerPath) != g_BannerPathToImage.end() )
|
||||
{
|
||||
/* If an old image is loaded, free it. */
|
||||
if( g_BannerPathToImage.find(BannerPath) != g_BannerPathToImage.end() )
|
||||
{
|
||||
RageSurface *oldimg = g_BannerPathToImage[BannerPath];
|
||||
delete oldimg;
|
||||
g_BannerPathToImage.erase(BannerPath);
|
||||
}
|
||||
RageSurface *oldimg = g_BannerPathToImage[BannerPath];
|
||||
delete oldimg;
|
||||
g_BannerPathToImage.erase(BannerPath);
|
||||
}
|
||||
|
||||
if( PREFSMAN->m_iBannerCache == PrefsManager::BNCACHE_LOW_RES_PRELOAD )
|
||||
{
|
||||
/* Keep it; we're just going to load it anyway. */
|
||||
g_BannerPathToImage[BannerPath] = img;
|
||||
}
|
||||
|
||||
@@ -22,10 +22,12 @@ public:
|
||||
~BannerCache();
|
||||
|
||||
RageTextureID LoadCachedBanner( CString BannerPath );
|
||||
|
||||
void CacheBanner( CString BannerPath );
|
||||
void UncacheBanner( CString BannerPath );
|
||||
void LoadBanner( CString BannerPath );
|
||||
|
||||
void Demand();
|
||||
void Undemand();
|
||||
|
||||
void OutputStats() const;
|
||||
};
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ PrefsManager::PrefsManager() :
|
||||
m_bTexturePreload ( Options, "TexturePreload", false ),
|
||||
m_bDelayedScreenLoad ( Options, "DelayedScreenLoad", false ),
|
||||
m_bDelayedModelDelete ( Options, "DelayedModelDelete", false ),
|
||||
m_iBannerCache ( Options, "BannerCache", BNCACHE_LOW_RES ),
|
||||
m_iBannerCache ( Options, "BannerCache", BNCACHE_LOW_RES_PRELOAD ),
|
||||
m_bPalettedBannerCache ( Options, "PalettedBannerCache", false ),
|
||||
m_bFastLoad ( Options, "FastLoad", true ),
|
||||
|
||||
|
||||
@@ -43,7 +43,10 @@ public:
|
||||
Preference<bool> m_bTexturePreload;
|
||||
Preference<bool> m_bDelayedScreenLoad;
|
||||
Preference<bool> m_bDelayedModelDelete;
|
||||
enum { BNCACHE_OFF, BNCACHE_LOW_RES, BNCACHE_FULL };
|
||||
enum { BNCACHE_OFF,
|
||||
BNCACHE_LOW_RES_PRELOAD, // preload low-res on start
|
||||
BNCACHE_LOW_RES_LOAD_ON_DEMAND, // preload low-res on screen load
|
||||
BNCACHE_FULL };
|
||||
Preference<int> m_iBannerCache;
|
||||
Preference<bool> m_bPalettedBannerCache;
|
||||
Preference<bool> m_bFastLoad;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "PlayerState.h"
|
||||
#include "Command.h"
|
||||
#include "CommonMetrics.h"
|
||||
#include "BannerCache.h"
|
||||
|
||||
const int NUM_SCORE_DIGITS = 9;
|
||||
|
||||
@@ -89,6 +90,9 @@ void ScreenSelectMusic::Init()
|
||||
if( GAMESTATE->m_PlayMode == PLAY_MODE_INVALID )
|
||||
RageException::Throw( "The PlayMode has not been set. A theme must set the PlayMode before loading ScreenSelectMusic." );
|
||||
|
||||
/* Load low-res banners, if needed. */
|
||||
BANNERCACHE->Demand();
|
||||
|
||||
m_MusicWheel.Load();
|
||||
|
||||
// pop'n music has this under the songwheel...
|
||||
@@ -341,6 +345,7 @@ void ScreenSelectMusic::Init()
|
||||
ScreenSelectMusic::~ScreenSelectMusic()
|
||||
{
|
||||
LOG->Trace( "ScreenSelectMusic::~ScreenSelectMusic()" );
|
||||
BANNERCACHE->Undemand();
|
||||
|
||||
}
|
||||
|
||||
@@ -681,18 +686,25 @@ void ScreenSelectMusic::CheckBackgroundRequests()
|
||||
if( g_bBannerWaiting )
|
||||
{
|
||||
float HighQualTime = m_Banner.GetFadeSeconds();
|
||||
if( g_StartedLoadingAt.Ago() < HighQualTime )
|
||||
return;
|
||||
|
||||
CString sPath;
|
||||
if( g_StartedLoadingAt.Ago() >= HighQualTime && m_BackgroundLoader.IsCacheFileFinished(g_sBannerPath, sPath) )
|
||||
if( TEXTUREMAN->IsTextureRegistered( Sprite::SongBannerTexture(g_sBannerPath) ) )
|
||||
{
|
||||
g_bBannerWaiting = false;
|
||||
RageTimer foo;
|
||||
m_Banner.Load( sPath );
|
||||
|
||||
m_BackgroundLoader.FinishedWithCachedFile( g_sBannerPath );
|
||||
/* If the file is already loaded into a texture, it's finished,
|
||||
* and we only do this to honor the HighQualTime value. */
|
||||
sPath = g_sBannerPath;
|
||||
}
|
||||
else
|
||||
return;
|
||||
{
|
||||
if( !m_BackgroundLoader.IsCacheFileFinished( g_sBannerPath, sPath ) )
|
||||
return;
|
||||
m_BackgroundLoader.FinishedWithCachedFile( g_sBannerPath );
|
||||
}
|
||||
|
||||
g_bBannerWaiting = false;
|
||||
m_Banner.Load( sPath );
|
||||
}
|
||||
|
||||
/* Nothing else is going. Start the music, if we havn't yet. */
|
||||
@@ -1679,7 +1691,12 @@ void ScreenSelectMusic::AfterMusicChange()
|
||||
LOG->Trace("LoadFromCachedBanner(%s)",g_sBannerPath .c_str());
|
||||
if( m_Banner.LoadFromCachedBanner( g_sBannerPath ) )
|
||||
{
|
||||
m_BackgroundLoader.CacheFile( g_sBannerPath );
|
||||
/* If the high-res banner is already loaded, just
|
||||
* delay before loading it, so the low-res one has
|
||||
* time to fade in. */
|
||||
if( !TEXTUREMAN->IsTextureRegistered( Sprite::SongBannerTexture(g_sBannerPath) ) )
|
||||
m_BackgroundLoader.CacheFile( g_sBannerPath );
|
||||
|
||||
g_bBannerWaiting = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ CString Song::GetBackgroundAtBeat( float fBeat ) const
|
||||
|
||||
CString Song::GetCacheFilePath() const
|
||||
{
|
||||
return ssprintf( CACHE_DIR "Songs/%u", GetHashForString(m_sSongDir) );
|
||||
return SongCacheIndex::GetCacheFilePath( "Songs", m_sSongDir );
|
||||
}
|
||||
|
||||
/* Get a path to the SM containing data for this song. It might
|
||||
|
||||
@@ -29,6 +29,13 @@
|
||||
|
||||
SongCacheIndex *SONGINDEX;
|
||||
|
||||
CString SongCacheIndex::GetCacheFilePath( const CString &sGroup, const CString &sPath )
|
||||
{
|
||||
/* Use GetHashForString, not ForFile, since we don't want to spend time
|
||||
* checking the file size and date. */
|
||||
return ssprintf( "%s/%s/%u", CACHE_DIR, sGroup.c_str(), GetHashForString(sPath) );
|
||||
}
|
||||
|
||||
SongCacheIndex::SongCacheIndex()
|
||||
{
|
||||
ReadCacheIndex();
|
||||
|
||||
@@ -11,6 +11,7 @@ class SongCacheIndex
|
||||
public:
|
||||
SongCacheIndex();
|
||||
~SongCacheIndex();
|
||||
static CString GetCacheFilePath( const CString &sGroup, const CString &sPath );
|
||||
|
||||
void ReadCacheIndex();
|
||||
void AddCacheIndex( const CString &path, unsigned hash );
|
||||
|
||||
@@ -355,7 +355,7 @@ static void CheckSettings()
|
||||
/* Preloaded banners takes about 9k per song. Although it's smaller than the
|
||||
* actual song data, it still adds up with a lot of songs. Disable it for 64-meg
|
||||
* systems. */
|
||||
PREFSMAN->m_iBannerCache = LowMemory ? PrefsManager::BNCACHE_OFF:PrefsManager::BNCACHE_LOW_RES;
|
||||
PREFSMAN->m_iBannerCache = LowMemory ? PrefsManager::BNCACHE_OFF:PrefsManager::BNCACHE_LOW_RES_PRELOAD;
|
||||
|
||||
PREFSMAN->SaveGlobalPrefsToDisk();
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user