Browse Source

Fonts: clarify ClearTexData() as not supported with dynamic atlases.

ocornut 7 months ago
parent
commit
80404fae30
3 changed files with 30 additions and 22 deletions
  1. 4 2
      imgui.cpp
  2. 2 2
      imgui.h
  3. 24 18
      imgui_draw.cpp

+ 4 - 2
imgui.cpp

@@ -5785,7 +5785,8 @@ void ImGui::EndFrame()
     UpdateTexturesEndFrame();
     UpdateTexturesEndFrame();
 
 
     // Unlock font atlas
     // Unlock font atlas
-    g.IO.Fonts->Locked = false;
+    ImFontAtlas* atlas = g.IO.Fonts;
+    atlas->Locked = false;
 
 
     // Clear Input data for next frame
     // Clear Input data for next frame
     g.IO.MousePosPrev = g.IO.MousePos;
     g.IO.MousePosPrev = g.IO.MousePos;
@@ -8575,8 +8576,9 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)
 void ImGui::UpdateFontsNewFrame()
 void ImGui::UpdateFontsNewFrame()
 {
 {
     ImGuiContext& g = *GImGui;
     ImGuiContext& g = *GImGui;
+    ImFontAtlas* atlas = g.IO.Fonts;
     if ((g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures) == 0)
     if ((g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures) == 0)
-        g.IO.Fonts->Locked = true;
+        atlas->Locked = true;
     SetCurrentFont(GetDefaultFont(), GetDefaultFont()->Sources[0].SizePixels);
     SetCurrentFont(GetDefaultFont(), GetDefaultFont()->Sources[0].SizePixels);
     IM_ASSERT(g.Font->IsLoaded());
     IM_ASSERT(g.Font->IsLoaded());
 }
 }

+ 2 - 2
imgui.h

@@ -3517,7 +3517,7 @@ struct ImFontAtlas
     // As we are transitioning toward a new font system, we expect to obsolete those soon:
     // As we are transitioning toward a new font system, we expect to obsolete those soon:
     IMGUI_API void              ClearInputData();           // [OBSOLETE] Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
     IMGUI_API void              ClearInputData();           // [OBSOLETE] Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
     IMGUI_API void              ClearFonts();               // [OBSOLETE] Clear input+output font data (same as ClearInputData() + glyphs storage, UV coordinates).
     IMGUI_API void              ClearFonts();               // [OBSOLETE] Clear input+output font data (same as ClearInputData() + glyphs storage, UV coordinates).
-    IMGUI_API void              ClearTexData();             // [OBSOLETE] Clear output texture data (CPU side). Saves RAM once the texture has been copied to graphics memory.
+    IMGUI_API void              ClearTexData();             // [OBSOLETE] Clear CPU-side copy of the texture data. Saves RAM once the texture has been copied to graphics memory.
 
 
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
     // Legacy path for build atlas + retrieving pixel data.
     // Legacy path for build atlas + retrieving pixel data.
@@ -3592,7 +3592,7 @@ struct ImFontAtlas
     ImTextureRef                TexRef;             // User data to refer to the latest texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure.
     ImTextureRef                TexRef;             // User data to refer to the latest texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure.
     ImTextureData*              TexData;            // Current texture
     ImTextureData*              TexData;            // Current texture
     ImVector<ImTextureData*>    TexList;            // Texture list (most often TexList.Size == 1). TexData is always == TexList.back(). DO NOT USE DIRECTLY, USE GetDrawData().Textures[]/GetPlatformIO().Textures[] instead!
     ImVector<ImTextureData*>    TexList;            // Texture list (most often TexList.Size == 1). TexData is always == TexList.back(). DO NOT USE DIRECTLY, USE GetDrawData().Textures[]/GetPlatformIO().Textures[] instead!
-    bool                        Locked;             // Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert.
+    bool                        Locked;             // Marked as locked during ImGui::NewFrame()..EndFrame() scope if TexUpdates are not supported. Any attempt to modify the atlas will assert.
     bool                        RendererHasTextures;// Copy of (BackendFlags & ImGuiBackendFlags_RendererHasTextures) from supporting context.
     bool                        RendererHasTextures;// Copy of (BackendFlags & ImGuiBackendFlags_RendererHasTextures) from supporting context.
     bool                        TexIsBuilt;         // Set when texture was built matching current font input. Mostly useful for legacy IsBuilt() call.
     bool                        TexIsBuilt;         // Set when texture was built matching current font input. Mostly useful for legacy IsBuilt() call.
     bool                        TexPixelsUseColors; // Tell whether our texture data is known to use colors (rather than just alpha channel), in order to help backend select a format or conversion process.
     bool                        TexPixelsUseColors; // Tell whether our texture data is known to use colors (rather than just alpha channel), in order to help backend select a format or conversion process.

+ 24 - 18
imgui_draw.cpp

@@ -2607,9 +2607,11 @@ ImFontAtlas::~ImFontAtlas()
 
 
 void ImFontAtlas::Clear()
 void ImFontAtlas::Clear()
 {
 {
-    ClearInputData();
-    ClearTexData();
     ClearFonts();
     ClearFonts();
+    bool backup_renderer_has_textures = RendererHasTextures;
+    RendererHasTextures = false; // Full Clear() is supported, but ClearTexData() only isn't.
+    ClearTexData();
+    RendererHasTextures = backup_renderer_has_textures;
 }
 }
 
 
 void ImFontAtlas::ClearCache()
 void ImFontAtlas::ClearCache()
@@ -2647,12 +2649,14 @@ void ImFontAtlas::ClearInputData()
     Sources.clear();
     Sources.clear();
 }
 }
 
 
+// Clear CPU-side copy of the texture data.
 void ImFontAtlas::ClearTexData()
 void ImFontAtlas::ClearTexData()
 {
 {
     IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
     IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
-    TexList.clear();
-    IM_DELETE(TexData);
-    TexData = NULL;
+    IM_ASSERT(RendererHasTextures == false && "Not supported for dynamic atlases, but you may call Clear().");
+    for (ImTextureData* tex : TexList)
+        tex->DestroyPixels();
+    //Locked = true; // Hoped to be able to lock this down but some reload patterns may not be happy with it.
 }
 }
 
 
 void ImFontAtlas::ClearFonts()
 void ImFontAtlas::ClearFonts()
@@ -2686,7 +2690,7 @@ static void ImFontAtlasBuildUpdateRendererHasTexturesFromContext(ImFontAtlas* at
 }
 }
 
 
 // Called by NewFrame(). When multiple context own the atlas, only the first one calls this.
 // Called by NewFrame(). When multiple context own the atlas, only the first one calls this.
-// If you are calling this yourself, ensure atlas->RendererHasTexUpdates is et.
+// If you are calling this yourself, ensure atlas->RendererHasTextures is set.
 // 'frame_count' needs to be provided because we can gc/prioritize baked fonts based on their age.
 // 'frame_count' needs to be provided because we can gc/prioritize baked fonts based on their age.
 void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count)
 void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count)
 {
 {
@@ -3256,7 +3260,7 @@ bool ImFontAtlasGetMouseCursorTexData(ImFontAtlas* atlas, ImGuiMouseCursor curso
     return true;
     return true;
 }
 }
 
 
-// When atlas->RendererHasTexUpdates == true, this is only called if no font were loaded.
+// When atlas->RendererHasTextures = true, this is only called if no font were loaded.
 void ImFontAtlasBuildMain(ImFontAtlas* atlas)
 void ImFontAtlasBuildMain(ImFontAtlas* atlas)
 {
 {
     IM_ASSERT(!atlas->Locked && "Cannot modify a locked ImFontAtlas!");
     IM_ASSERT(!atlas->Locked && "Cannot modify a locked ImFontAtlas!");
@@ -3481,16 +3485,6 @@ static void ImFontAtlasBuildUpdateLinesTexData(ImFontAtlas* atlas, bool add_and_
 
 
 //-----------------------------------------------------------------------------------------------------------------------------
 //-----------------------------------------------------------------------------------------------------------------------------
 
 
-ImGuiID ImFontAtlasBakedGetId(ImGuiID font_id, float baked_size)
-{
-    struct { ImGuiID FontId; float BakedSize; } hashed_data;
-    hashed_data.FontId = font_id;
-    hashed_data.BakedSize = baked_size;
-    return ImHashData(&hashed_data, sizeof(hashed_data));
-}
-
-//-----------------------------------------------------------------------------------------------------------------------------
-
 bool ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontConfig* src)
 bool ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontConfig* src)
 {
 {
     ImFont* font = src->DstFont;
     ImFont* font = src->DstFont;
@@ -4910,6 +4904,14 @@ float ImFontBaked::GetCharAdvance(ImWchar c)
 }
 }
 IM_MSVC_RUNTIME_CHECKS_RESTORE
 IM_MSVC_RUNTIME_CHECKS_RESTORE
 
 
+ImGuiID ImFontAtlasBakedGetId(ImGuiID font_id, float baked_size)
+{
+    struct { ImGuiID FontId; float BakedSize; } hashed_data;
+    hashed_data.FontId = font_id;
+    hashed_data.BakedSize = baked_size;
+    return ImHashData(&hashed_data, sizeof(hashed_data));
+}
+
 // ImFontBaked pointers are valid for the entire frame but shall never be kept between frames.
 // ImFontBaked pointers are valid for the entire frame but shall never be kept between frames.
 ImFontBaked* ImFont::GetFontBaked(float size)
 ImFontBaked* ImFont::GetFontBaked(float size)
 {
 {
@@ -4920,18 +4922,22 @@ ImFontBaked* ImFont::GetFontBaked(float size)
     ImFontAtlas* atlas = ContainerAtlas;
     ImFontAtlas* atlas = ContainerAtlas;
     ImFontAtlasBuilder* builder = atlas->Builder;
     ImFontAtlasBuilder* builder = atlas->Builder;
 
 
+    // FIXME-BAKED: Design for picking a nearest size?
     ImGuiID baked_id = ImFontAtlasBakedGetId(FontId, size);
     ImGuiID baked_id = ImFontAtlasBakedGetId(FontId, size);
     ImFontBaked** p_baked_in_map = (ImFontBaked**)builder->BakedMap.GetVoidPtrRef(baked_id);
     ImFontBaked** p_baked_in_map = (ImFontBaked**)builder->BakedMap.GetVoidPtrRef(baked_id);
     baked = *p_baked_in_map;
     baked = *p_baked_in_map;
     if (baked != NULL)
     if (baked != NULL)
     {
     {
-        // FIXME-BAKED: Design for picking a nearest size?
         IM_ASSERT(baked->Size == size && baked->ContainerFont == this && baked->BakedId == baked_id);
         IM_ASSERT(baked->Size == size && baked->ContainerFont == this && baked->BakedId == baked_id);
         baked->LastUsedFrame = builder->FrameCount;
         baked->LastUsedFrame = builder->FrameCount;
         LastBaked = baked;
         LastBaked = baked;
         return baked;
         return baked;
     }
     }
 
 
+    // FIXME-BAKED: If atlas is locked, find closest match
+    if (atlas->Locked)
+        IM_ASSERT(!atlas->Locked && "Cannot use dynamic font size with a locked ImFontAtlas!"); // Locked because rendering backend does not support ImGuiBackendFlags_RendererHasTextures!
+
     // Create new
     // Create new
     ImGuiContext& g = *GImGui;
     ImGuiContext& g = *GImGui;
     IM_UNUSED(g); // for IMGUI_DEBUG_LOG_FONT()
     IM_UNUSED(g); // for IMGUI_DEBUG_LOG_FONT()