From 3566be5b0bb5e03b7efb147edd3a771eea852c35 Mon Sep 17 00:00:00 2001 From: danij Date: Sat, 16 Jul 2011 15:04:44 +0100 Subject: [PATCH] Began refactoring the management of abstract fonts and their namespaces to allow partially clearing the font database. Fixed: After a GL_TotalReset we need to choose system fonts again and then resize the console history buffer to suit. --- doomsday/engine/portable/include/fonts.h | 34 ++++- doomsday/engine/portable/src/dd_main.c | 10 +- doomsday/engine/portable/src/fonts.c | 137 ++++++++++++++++--- doomsday/engine/portable/src/gl_main.c | 13 +- doomsday/engine/portable/src/gl_texmanager.c | 7 +- 5 files changed, 171 insertions(+), 30 deletions(-) diff --git a/doomsday/engine/portable/include/fonts.h b/doomsday/engine/portable/include/fonts.h index 9c2c90cf20..91a785ed73 100644 --- a/doomsday/engine/portable/include/fonts.h +++ b/doomsday/engine/portable/include/fonts.h @@ -22,6 +22,14 @@ * Boston, MA 02110-1301 USA */ +/** + * Runtime fonts are not loaded until precached or actually needed. + * They may be cleared, in which case they will be reloaded when needed. + * + * System fonts are loaded at startup and remain in memory all the time. + * After clearing they must be manually reloaded. + */ + #ifndef LIBDENG_FONTS_H #define LIBDENG_FONTS_H @@ -38,8 +46,30 @@ void Fonts_Init(void); /// Shutdown this module. void Fonts_Shutdown(void); -/// Mark all fonts as requiring a full update. Called during engine/renderer reset. -void Fonts_Update(void); +void Fonts_Clear(void); + +void Fonts_ClearRuntimeFonts(void); + +void Fonts_ClearSystemFonts(void); + +/** + * To be called during engine/gl-subsystem reset to release all resources + * acquired from the GL subsystem (v-buffers, d-lists, textures, etc...) + * for fonts. + * \note Called automatically by this subsystem prior to module shutdown. + */ +void Fonts_ReleaseRuntimeGLResources(void); +void Fonts_ReleaseSystemGLResources(void); +void Fonts_ReleaseGLResourcesByNamespace(fontnamespaceid_t namespaceId); + +/** + * To be called during a texture/font-renderer reset to release all texture + * memory acquired from the GL subsystem for fonts. + * \note Called automatically by this subsystem prior to module shutdown. + */ +void Fonts_ReleaseRuntimeGLTextures(void); +void Fonts_ReleaseSystemGLTextures(void); +void Fonts_ReleaseGLTexturesByNamespace(fontnamespaceid_t namespaceId); /// @return Number of known font bindings in all namespaces. uint Fonts_Count(void); diff --git a/doomsday/engine/portable/src/dd_main.c b/doomsday/engine/portable/src/dd_main.c index 2795c7883e..c391bd16e6 100644 --- a/doomsday/engine/portable/src/dd_main.c +++ b/doomsday/engine/portable/src/dd_main.c @@ -1050,7 +1050,6 @@ boolean DD_ChangeGame2(gameinfo_t* info, boolean allowReload) GL_PurgeDeferredTasks(); GL_ClearTextureMemory(); - UI_ReleaseTextures(); GL_SetFilter(false); // If a game is presently loaded; unload it. @@ -1096,6 +1095,7 @@ boolean DD_ChangeGame2(gameinfo_t* info, boolean allowReload) R_DestroyColorPalettes(); GL_DestroyRuntimeTextures(); + Fonts_ClearRuntimeFonts(); Sfx_InitLogical(); P_InitThinkerLists(0x1|0x2); @@ -1123,7 +1123,8 @@ boolean DD_ChangeGame2(gameinfo_t* info, boolean allowReload) FI_Shutdown(); titleFinale = 0; // If the title finale was in progress it isn't now. - Fonts_Shutdown(); + + /// \fixme Materials database should not be shutdown during a reload. Materials_Shutdown(); VERBOSE( @@ -1139,7 +1140,6 @@ boolean DD_ChangeGame2(gameinfo_t* info, boolean allowReload) if(!exchangeEntryPoints(GameInfo_PluginId(info))) { - Fonts_Init(); Materials_Initialize(); FI_Init(); P_PtcInit(); @@ -1151,7 +1151,6 @@ boolean DD_ChangeGame2(gameinfo_t* info, boolean allowReload) // This is now the current game. currentGameInfoIndex = gameInfoIndex(info); - Fonts_Init(); Materials_Initialize(); FI_Init(); P_PtcInit(); @@ -1408,7 +1407,7 @@ int DD_Main(void) Sys_Init(); - // Initialize the subsystems and load resources needed for busy mode. + // Initialize the subsystems needed prior to entering busy mode. Fonts_Init(); if(!isDedicated) { @@ -1688,7 +1687,6 @@ static int DD_StartupWorker(void* parm) // Get the material manager up and running. Con_SetProgress(90); GL_EarlyInitTextureManager(); - Fonts_Init(); Materials_Initialize(); Con_SetProgress(140); diff --git a/doomsday/engine/portable/src/fonts.c b/doomsday/engine/portable/src/fonts.c index ec594ebb8f..ef01a644c1 100644 --- a/doomsday/engine/portable/src/fonts.c +++ b/doomsday/engine/portable/src/fonts.c @@ -337,6 +337,8 @@ void Fonts_Init(void) if(inited) return; // Already been here. + VERBOSE( Con_Message("Initializing Fonts collection...\n") ) + fonts = NULL; bindings = NULL; bindingsCount = 0; @@ -357,11 +359,35 @@ void Fonts_Shutdown(void) if(!inited) return; + Fonts_ReleaseRuntimeGLResources(); + Fonts_ReleaseSystemGLResources(); + destroyBindings(); destroyFonts(); inited = false; } +void Fonts_ClearRuntimeFonts(void) +{ + errorIfNotInited("Fonts::ClearRuntimeFonts"); + Fonts_ReleaseRuntimeGLResources(); + //destroyFonts(FN_GAME); +#pragma message("!!!Fonts::ClearRuntimeFonts not yet implemented!!!") +} + +void Fonts_ClearSystemFonts(void) +{ + errorIfNotInited("Fonts::ClearSystemFonts"); + Fonts_ReleaseSystemGLResources(); +#pragma message("!!!Fonts::ClearSystemFonts not yet implemented!!!") +} + +void Fonts_Clear(void) +{ + Fonts_ClearRuntimeFonts(); + Fonts_ClearSystemFonts(); +} + uint Fonts_Count(void) { if(inited) @@ -720,15 +746,77 @@ dduri_t* Fonts_GetUri(font_t* font) return uri; } -void Fonts_Update(void) +void Fonts_ReleaseGLTexturesByNamespace(fontnamespaceid_t namespaceId) +{ + errorIfNotInited("Fonts::ReleaseGLTexturesByNamespace"); + + if(namespaceId != FN_ANY && !VALID_FONTNAMESPACEID(namespaceId)) + Con_Error("Fonts::ReleaseGLTexturesByNamespace: Invalid namespace %i.", (int) namespaceId); + + if(novideo || isDedicated) + return; + + { fontlist_node_t* node; + for(node = fonts; node; node = node->next) + { + font_t* font = node->font; + + if(!(namespaceId == FN_ANY || !Font_BindId(font))) + { + fontbind_t* fb = bindByIndex(Font_BindId(font)); + if(fb && FontBind_Namespace(fb) != namespaceId) + continue; + } + + switch(Font_Type(font)) + { + case FT_BITMAP: + BitmapFont_DeleteGLTexture(node->font); + break; + case FT_BITMAPCOMPOSITE: + BitmapCompositeFont_DeleteGLTextures(node->font); + break; + default: + Con_Error("Fonts::ReleaseGLTexturesByNamespace: Invalid font type %i.", (int) Font_Type(font)); + exit(1); // Unreachable. + } + }} +} + +void Fonts_ReleaseRuntimeGLTextures(void) +{ + errorIfNotInited("Fonts::ReleaseRuntimeGLTextures"); + Fonts_ReleaseGLTexturesByNamespace(FN_GAME); +} + +void Fonts_ReleaseSystemGLTextures(void) { - if(!inited || novideo || isDedicated) + errorIfNotInited("Fonts::ReleaseSystemGLTextures"); + Fonts_ReleaseGLTexturesByNamespace(FN_SYSTEM); +} + +void Fonts_ReleaseGLResourcesByNamespace(fontnamespaceid_t namespaceId) +{ + errorIfNotInited("Fonts::ReleaseGLResourcesByNamespace"); + + if(namespaceId != FN_ANY && !VALID_FONTNAMESPACEID(namespaceId)) + Con_Error("Fonts::ReleaseGLResourcesByNamespace: Invalid namespace %i.", (int) namespaceId); + + if(novideo || isDedicated) return; { fontlist_node_t* node; for(node = fonts; node; node = node->next) { font_t* font = node->font; + + if(!(namespaceId == FN_ANY || !Font_BindId(font))) + { + fontbind_t* fb = bindByIndex(Font_BindId(font)); + if(fb && FontBind_Namespace(fb) != namespaceId) + continue; + } + switch(Font_Type(font)) { case FT_BITMAP: @@ -740,12 +828,24 @@ void Fonts_Update(void) BitmapCompositeFont_DeleteGLDisplayLists(node->font); break; default: - Con_Error("Fonts::Update: Invalid font type %i.", (int) Font_Type(font)); + Con_Error("Fonts::ReleaseGLResourcesByNamespace: Invalid font type %i.", (int) Font_Type(font)); exit(1); // Unreachable. } }} } +void Fonts_ReleaseRuntimeGLResources(void) +{ + errorIfNotInited("Fonts::ReleaseRuntimeTextures"); + Fonts_ReleaseGLTexturesByNamespace(FN_GAME); +} + +void Fonts_ReleaseSystemGLResources(void) +{ + errorIfNotInited("Fonts::ReleaseSystemTextures"); + Fonts_ReleaseGLTexturesByNamespace(FN_SYSTEM); +} + int Fonts_Ascent(font_t* font) { Fonts_Prepare(font); @@ -833,12 +933,19 @@ static void printFontInfo(const fontbind_t* fb, boolean printNamespace) if(printNamespace) Con_Printf("%s:", Str_Text(nameForFontNamespaceId(FontBind_Namespace(fb)))); Con_Printf("%s\" %s ", Str_Text(FontBind_Name(fb)), Font_Type(font) == FT_BITMAP? "bitmap" : "bitmap_composite"); - Con_Printf("(ascent:%i, descent:%i, leading:%i", Fonts_Ascent(font), Fonts_Descent(font), Fonts_Leading(font)); - if(Font_Type(font) == FT_BITMAP && BitmapFont_GLTextureName(font)) + if(Font_IsPrepared(font)) { - Con_Printf(", texWidth:%i, texHeight:%i", BitmapFont_TextureWidth(font), BitmapFont_TextureHeight(font)); + Con_Printf("(ascent:%i, descent:%i, leading:%i", Fonts_Ascent(font), Fonts_Descent(font), Fonts_Leading(font)); + if(Font_Type(font) == FT_BITMAP && BitmapFont_GLTextureName(font)) + { + Con_Printf(", texWidth:%i, texHeight:%i", BitmapFont_TextureWidth(font), BitmapFont_TextureHeight(font)); + } + Con_Printf(")\n"); + } + else + { + Con_Printf("\n"); } - Con_Printf(")\n"); } static fontbind_t** collectFontBinds(fontnamespaceid_t namespaceId, @@ -925,16 +1032,14 @@ static size_t printFonts2(fontnamespaceid_t namespaceId, const char* like) } // Print the result index key. - if(VALID_FONTNAMESPACEID(namespaceId)) + Con_Printf(" uid: \"%s\" font-type", VALID_FONTNAMESPACEID(namespaceId)? "font-name" : ":font-name"); + // Fonts may be prepared only if GL is inited thus if we can't prepare, we can't list property values. + if(GL_IsInited()) { - Con_Printf(" uid: \"name\" font-type (:, ...)\n"); - Con_FPrintf(CBLF_RULER, ""); - } - else - { // Any namespace. - Con_Printf(" uid: \"(namespace:)name\" font-type (:, ...)\n"); - Con_FPrintf(CBLF_RULER, ""); + Con_Printf(" (:, ...)"); } + Con_Printf("\n"); + Con_FPrintf(CBLF_RULER, ""); // Sort and print the index. qsort(foundFonts, count, sizeof(*foundFonts), compareFontBindByName); @@ -974,6 +1079,6 @@ D_CMD(ListFonts) Con_Printf("Unknown font namespace \"%s\".\n", argv[1]); return false; } - printFonts(namespaceId, (argc > 2? argv[2] : (argc > 1 && namespaceId == FN_ANY? argv[1] : NULL))); + printFonts(namespaceId, (argc > 2? argv[2] : (argc > 1 && !VALID_FONTNAMESPACEID(namespaceId)? argv[1] : NULL))); return true; } diff --git a/doomsday/engine/portable/src/gl_main.c b/doomsday/engine/portable/src/gl_main.c index 1dc83a350a..a43ea9e9ca 100644 --- a/doomsday/engine/portable/src/gl_main.c +++ b/doomsday/engine/portable/src/gl_main.c @@ -506,7 +506,9 @@ void GL_InitRefresh(void) { GL_InitTextureManager(); GL_LoadSystemTextures(); - GL_LoadSystemFonts(); + + // Register/create Texture objects for the system textures. + R_InitSystemTextures(); } /** @@ -521,6 +523,8 @@ void GL_ShutdownRefresh(void) R_DestroyFlareTextures(); R_DestroyShinyTextures(); R_DestroyMaskTextures(); + R_DestroySystemTextures(); + R_DestroyColorPalettes(); } @@ -759,6 +763,9 @@ void GL_TotalReset(void) GL_ResetTextureManager(); GL_ReleaseReservedNames(); + Fonts_ReleaseRuntimeGLResources(); + Fonts_ReleaseSystemGLResources(); + #if _DEBUG Z_CheckHeap(); #endif @@ -775,6 +782,10 @@ void GL_TotalRestore(void) // Getting back up and running. GL_ReserveNames(); GL_Init2DState(); + + // Choose fonts again. + R_LoadSystemFonts(); + Con_ResizeHistoryBuffer(); { gamemap_t* map = P_GetCurrentMap(); diff --git a/doomsday/engine/portable/src/gl_texmanager.c b/doomsday/engine/portable/src/gl_texmanager.c index 7c1466fdcb..27c3f1b267 100644 --- a/doomsday/engine/portable/src/gl_texmanager.c +++ b/doomsday/engine/portable/src/gl_texmanager.c @@ -1585,7 +1585,6 @@ void GL_LoadSystemTextures(void) } Rend_ParticleLoadSystemTextures(); - R_InitSystemTextures(); } void GL_ReleaseSystemTextures(void) @@ -1607,9 +1606,8 @@ void GL_ReleaseSystemTextures(void) Materials_ReleaseGLTextures(MN_SYSTEM_NAME); UI_ReleaseTextures(); - Rend_ParticleReleaseSystemTextures(); - R_DestroySystemTextures(); + Fonts_ReleaseSystemGLTextures(); } void GL_ReleaseRuntimeTextures(void) @@ -1636,6 +1634,7 @@ void GL_ReleaseRuntimeTextures(void) GL_ReleaseTexturesForRawImages(); Rend_ParticleReleaseExtraTextures(); + Fonts_ReleaseRuntimeGLTextures(); } void GL_ClearTextureMemory(void) @@ -3207,7 +3206,6 @@ static int doTexReset(void* parm) /// \todo re-upload ALL textures currently in use. GL_LoadSystemTextures(); - GL_LoadSystemFonts(); Rend_ParticleLoadExtraTextures(); R_SkyUpdate(); @@ -3226,7 +3224,6 @@ void GL_TexReset(void) boolean useBusyMode = !Con_IsBusy(); GL_ClearTextureMemory(); - Fonts_Update(); Con_Printf("All DGL textures deleted.\n"); if(useBusyMode)