SM5SVN 9419e1e: Only unload fonts if not used by the next screen. [shakesoda]

This commit is contained in:
AJ Kelly
2010-12-21 13:26:09 -06:00
parent 43dd10b1f6
commit 0964d8dc9a
5 changed files with 62 additions and 39 deletions
+5
View File
@@ -13,6 +13,11 @@ _____________________________________________________________________________
sm-ssc v1.2 | 201012xx sm-ssc v1.2 | 201012xx
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
20101221
--------
* SM5SVN r28586: Only unload fonts if not used by the next screen. [shakesoda]
* [ScreenSelectMaster] Fix DoSwitchAnyways to actually work again.
20101220 20101220
-------- --------
* [Actor] Add bezier (_fallback/02 Actor.lua) [FSX] * [Actor] Add bezier (_fallback/02 Actor.lua) [FSX]
+7 -6
View File
@@ -223,9 +223,7 @@ int Font::GetLineHeightInSourcePixels( const wstring &szLine ) const
Font::Font() Font::Font()
{ {
//LOG->Trace( "Font::LoadFromFontName(%s)", sASCIITexturePath.c_str() ); m_iRefCount = 0;
m_iRefCount = 1;
m_pDefault = NULL; m_pDefault = NULL;
m_bRightToLeft = false; m_bRightToLeft = false;
// [sm-ssc] don't show strokes by default // [sm-ssc] don't show strokes by default
@@ -239,6 +237,7 @@ Font::~Font()
void Font::Unload() void Font::Unload()
{ {
LOG->Trace("Font:Unload '%s'",path.c_str());
for( unsigned i = 0; i < m_apPages.size(); ++i ) for( unsigned i = 0; i < m_apPages.size(); ++i )
delete m_apPages[i]; delete m_apPages[i];
m_apPages.clear(); m_apPages.clear();
@@ -656,6 +655,8 @@ void Font::Load( const RString &sIniPath, RString sChars )
{ {
ASSERT_M( !GetExtension(sIniPath).CompareNoCase("ini"), sIniPath ); ASSERT_M( !GetExtension(sIniPath).CompareNoCase("ini"), sIniPath );
LOG->Trace( "Font: Loading new font '%s'",sIniPath.c_str());
// Check for recursion (recursive imports). // Check for recursion (recursive imports).
for( unsigned i = 0; i < LoadStack.size(); ++i ) for( unsigned i = 0; i < LoadStack.size(); ++i )
{ {
@@ -725,9 +726,9 @@ void Font::Load( const RString &sIniPath, RString sChars )
continue; continue;
} }
Font subfont; Font *subfont=FONT->LoadFont(path,"");
subfont.Load(path, ""); MergeFont(*subfont);
MergeFont(subfont); FONT->UnloadFont(subfont);
} }
} }
+26 -12
View File
@@ -22,7 +22,9 @@ FontManager::~FontManager()
{ {
const FontName &fn = i->first; const FontName &fn = i->first;
Font* pFont = i->second; Font* pFont = i->second;
if(pFont->m_iRefCount>0) {
LOG->Trace( "FONT LEAK: '%s', RefCount = %d.", fn.first.c_str(), pFont->m_iRefCount ); LOG->Trace( "FONT LEAK: '%s', RefCount = %d.", fn.first.c_str(), pFont->m_iRefCount );
}
delete pFont; delete pFont;
} }
} }
@@ -38,6 +40,7 @@ void FontManager::ReloadFonts()
Font* FontManager::LoadFont( const RString &sFontOrTextureFilePath, RString sChars ) Font* FontManager::LoadFont( const RString &sFontOrTextureFilePath, RString sChars )
{ {
Font *pFont;
// Convert the path to lowercase so that we don't load duplicates. // Convert the path to lowercase so that we don't load duplicates.
// Really, this does not solve the duplicate problem. We could have two copies // Really, this does not solve the duplicate problem. We could have two copies
// of the same bitmap if there are equivalent but different paths // of the same bitmap if there are equivalent but different paths
@@ -48,15 +51,16 @@ Font* FontManager::LoadFont( const RString &sFontOrTextureFilePath, RString sCha
map<FontName, Font*>::iterator p = g_mapPathToFont.find( NewName ); map<FontName, Font*>::iterator p = g_mapPathToFont.find( NewName );
if( p != g_mapPathToFont.end() ) if( p != g_mapPathToFont.end() )
{ {
Font *pFont=p->second; pFont=p->second;
pFont->m_iRefCount++; }
return pFont; else {
pFont= new Font;
pFont->Load(sFontOrTextureFilePath, sChars);
g_mapPathToFont[NewName] = pFont;
} }
Font *f = new Font; ++pFont->m_iRefCount;
f->Load(sFontOrTextureFilePath, sChars); return pFont;
g_mapPathToFont[NewName] = f;
return f;
} }
Font *FontManager::CopyFont( Font *pFont ) Font *FontManager::CopyFont( Font *pFont )
@@ -75,19 +79,29 @@ void FontManager::UnloadFont( Font *fp )
if(i->second != fp) if(i->second != fp)
continue; continue;
ASSERT_M(fp->m_iRefCount>0,"Attempting to unload a font with zero ref count!");
i->second->m_iRefCount--; i->second->m_iRefCount--;
if( fp->m_iRefCount == 0 )
{
delete i->second; // free the texture
g_mapPathToFont.erase( i ); // and remove the key in the map
}
return; return;
} }
FAIL_M( ssprintf("Unloaded an unknown font (%p)", fp) ); FAIL_M( ssprintf("Unloaded an unknown font (%p)", fp) );
} }
void FontManager::PruneFonts() {
for( std::map<FontName, Font*>::iterator i = g_mapPathToFont.begin();i != g_mapPathToFont.end();) {
Font *fp=i->second;
if(fp->m_iRefCount==0) {
delete fp;
g_mapPathToFont.erase(i);
i = g_mapPathToFont.end();
} else {
++i;
}
}
}
/* /*
* (c) 2001-2003 Chris Danford, Glenn Maynard * (c) 2001-2003 Chris Danford, Glenn Maynard
* All rights reserved. * All rights reserved.
+1
View File
@@ -15,6 +15,7 @@ public:
Font* LoadFont( const RString &sFontOrTextureFilePath, RString sChars = "" ); Font* LoadFont( const RString &sFontOrTextureFilePath, RString sChars = "" );
Font *CopyFont( Font *pFont ); Font *CopyFont( Font *pFont );
void UnloadFont( Font *fp ); void UnloadFont( Font *fp );
void PruneFonts();
/* Warning: This reloads fonts completely, so all BitmapTexts need to be /* Warning: This reloads fonts completely, so all BitmapTexts need to be
* reset, too. If this isn't done, best case they end up with old font * reset, too. If this isn't done, best case they end up with old font
+13 -11
View File
@@ -67,6 +67,7 @@
#include "SongManager.h" #include "SongManager.h"
#include "RageTextureManager.h" #include "RageTextureManager.h"
#include "ThemeManager.h" #include "ThemeManager.h"
#include "FontManager.h"
#include "Screen.h" #include "Screen.h"
#include "ScreenDimensions.h" #include "ScreenDimensions.h"
#include "Foreach.h" #include "Foreach.h"
@@ -75,6 +76,7 @@
ScreenManager* SCREENMAN = NULL; // global and accessable from anywhere in our program ScreenManager* SCREENMAN = NULL; // global and accessable from anywhere in our program
static Preference<bool> g_bDelayedScreenLoad( "DelayedScreenLoad", false ); static Preference<bool> g_bDelayedScreenLoad( "DelayedScreenLoad", false );
static Preference<bool> g_bPruneFonts( "PruneFonts", true );
// Screen registration // Screen registration
static map<RString,CreateScreenFn> *g_pmapRegistrees = NULL; static map<RString,CreateScreenFn> *g_pmapRegistrees = NULL;
@@ -566,6 +568,11 @@ void ScreenManager::PrepareScreen( const RString &sScreenName )
} }
} }
// Prune any unused fonts now that we have had a chance to reference the fonts
if(g_bPruneFonts) {
FONT->PruneFonts();
}
TEXTUREMAN->DiagnosticOutput(); TEXTUREMAN->DiagnosticOutput();
} }
@@ -660,19 +667,17 @@ void ScreenManager::LoadDelayedScreen()
* cleanup, so it doesn't get deleted by cleanup. */ * cleanup, so it doesn't get deleted by cleanup. */
bool bLoaded = ActivatePreparedScreenAndBackground( sScreenName ); bool bLoaded = ActivatePreparedScreenAndBackground( sScreenName );
vector<Actor*> apActorsToDelete; bool deletePrepared=g_setGroupedScreens.find(sScreenName) == g_setGroupedScreens.end();
if( g_setGroupedScreens.find(sScreenName) == g_setGroupedScreens.end() )
{
/* It's time to delete all old prepared screens. Depending on DelayedScreenLoad, /* It's time to delete all old prepared screens. Depending on DelayedScreenLoad,
* we can either delete the screens before or after we load the new screen. * we can either delete the screens before or after we load the new screen.
* Either way, we must remove them from the prepared list before we prepare * Either way, we must remove them from the prepared list before we prepare
* new screens. * new screens.
* If DelayedScreenLoad is true, delete them now; this lowers memory * If DelayedScreenLoad is true, delete them now; this lowers memory
* requirements, but results in redundant loads as we unload common data. */ * requirements, but results in redundant loads as we unload common data. */
if( g_bDelayedScreenLoad ) if( deletePrepared && g_bDelayedScreenLoad ) {
DeletePreparedScreens(); DeletePreparedScreens();
else deletePrepared=false;
GrabPreparedActors( apActorsToDelete );
} }
// If the screen wasn't already prepared, load it. // If the screen wasn't already prepared, load it.
@@ -689,12 +694,9 @@ void ScreenManager::LoadDelayedScreen()
ASSERT( bLoaded ); ASSERT( bLoaded );
} }
if( !apActorsToDelete.empty() ) if( deletePrepared )
{ {
BeforeDeleteScreen(); DeletePreparedScreens();
FOREACH( Actor*, apActorsToDelete, a )
SAFE_DELETE( *a );
AfterDeleteScreen();
} }
MESSAGEMAN->Broadcast( Message_ScreenChanged ); MESSAGEMAN->Broadcast( Message_ScreenChanged );