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

+ 24 - 18
imgui_draw.cpp

@@ -2607,9 +2607,11 @@ ImFontAtlas::~ImFontAtlas()
 
 void ImFontAtlas::Clear()
 {
-    ClearInputData();
-    ClearTexData();
     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()
@@ -2647,12 +2649,14 @@ void ImFontAtlas::ClearInputData()
     Sources.clear();
 }
 
+// Clear CPU-side copy of the texture data.
 void ImFontAtlas::ClearTexData()
 {
     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()
@@ -2686,7 +2690,7 @@ static void ImFontAtlasBuildUpdateRendererHasTexturesFromContext(ImFontAtlas* at
 }
 
 // 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.
 void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count)
 {
@@ -3256,7 +3260,7 @@ bool ImFontAtlasGetMouseCursorTexData(ImFontAtlas* atlas, ImGuiMouseCursor curso
     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)
 {
     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)
 {
     ImFont* font = src->DstFont;
@@ -4910,6 +4904,14 @@ float ImFontBaked::GetCharAdvance(ImWchar c)
 }
 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* ImFont::GetFontBaked(float size)
 {
@@ -4920,18 +4922,22 @@ ImFontBaked* ImFont::GetFontBaked(float size)
     ImFontAtlas* atlas = ContainerAtlas;
     ImFontAtlasBuilder* builder = atlas->Builder;
 
+    // FIXME-BAKED: Design for picking a nearest size?
     ImGuiID baked_id = ImFontAtlasBakedGetId(FontId, size);
     ImFontBaked** p_baked_in_map = (ImFontBaked**)builder->BakedMap.GetVoidPtrRef(baked_id);
     baked = *p_baked_in_map;
     if (baked != NULL)
     {
-        // FIXME-BAKED: Design for picking a nearest size?
         IM_ASSERT(baked->Size == size && baked->ContainerFont == this && baked->BakedId == baked_id);
         baked->LastUsedFrame = builder->FrameCount;
         LastBaked = 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
     ImGuiContext& g = *GImGui;
     IM_UNUSED(g); // for IMGUI_DEBUG_LOG_FONT()