Selaa lähdekoodia

Fonts: fixed support for multiple atlases.

Moved FontAtlasOwnedByContext to OwnerContext

# Conflicts:
#	imgui.cpp
#	imgui_internal.h
ocornut 3 kuukautta sitten
vanhempi
commit
91ed6e67b4
3 muutettua tiedostoa jossa 59 lisäystä ja 37 poistoa
  1. 55 36
      imgui.cpp
  2. 1 0
      imgui.h
  3. 3 1
      imgui_internal.h

+ 55 - 36
imgui.cpp

@@ -3962,13 +3962,13 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     InputTextState.Ctx = this;
 
     Initialized = false;
-    FontAtlasOwnedByContext = shared_font_atlas ? false : true;
     Font = NULL;
     FontBaked = NULL;
     FontSize = FontSizeBeforeScaling = FontScale = CurrentDpiScale = 0.0f;
     FontRasterizerDensity = 1.0f;
     IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
-    IO.Fonts->RefCount++;
+    if (shared_font_atlas == NULL)
+        IO.Fonts->OwnerContext = this;
     Time = 0.0f;
     FrameCount = 0;
     FrameCountEnded = FrameCountRendered = -1;
@@ -4226,8 +4226,9 @@ void ImGui::Initialize()
 
     // ImDrawList/ImFontAtlas are designed to function without ImGui, and 99% of it works without an ImGui context.
     // But this link allows us to facilitate/handle a few edge cases better.
+    ImFontAtlas* atlas = g.IO.Fonts;
     g.DrawListSharedData.Context = &g;
-    ImFontAtlasAddDrawListSharedData(g.IO.Fonts, &g.DrawListSharedData);
+    RegisterFontAtlas(atlas);
 
     g.Initialized = true;
 }
@@ -4240,17 +4241,15 @@ void ImGui::Shutdown()
     IM_ASSERT_USER_ERROR(g.IO.BackendRendererUserData == NULL, "Forgot to shutdown Renderer backend?");
 
     // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame)
-    if (ImFontAtlas* atlas = g.IO.Fonts)
+    for (ImFontAtlas* atlas : g.FontAtlases)
     {
-        ImFontAtlasRemoveDrawListSharedData(atlas, &g.DrawListSharedData);
-        atlas->RefCount--;
-        if (g.FontAtlasOwnedByContext)
+        UnregisterFontAtlas(atlas);
+        if (atlas->OwnerContext == &g)
         {
             atlas->Locked = false;
             IM_DELETE(atlas);
         }
     }
-    g.IO.Fonts = NULL;
     g.DrawListSharedData.TempBuffer.clear();
 
     // Cleanup of other data are conditional on actually having initialized Dear ImGui.
@@ -4412,7 +4411,8 @@ void ImGui::GcCompactTransientMiscBuffers()
     g.MultiSelectTempDataStacked = 0;
     g.MultiSelectTempData.clear_destruct();
     TableGcCompactSettings();
-    g.IO.Fonts->CompactCache();
+    for (ImFontAtlas* atlas : g.FontAtlases)
+        atlas->CompactCache();
 }
 
 // Free up/compact internal window buffers, we can use this when a window becomes unused.
@@ -5210,29 +5210,27 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags(const ImVec2& mouse_pos)
 static void ImGui::UpdateTexturesNewFrame()
 {
     ImGuiContext& g = *GImGui;
-    ImFontAtlas* atlas = g.IO.Fonts;
-    if (g.FontAtlasOwnedByContext)
-    {
-        atlas->RendererHasTextures = (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures) != 0;
-        ImFontAtlasUpdateNewFrame(atlas, g.FrameCount);
-    }
+    for (ImFontAtlas* atlas : g.FontAtlases)
+        if (atlas->OwnerContext == &g)
+        {
+            atlas->RendererHasTextures = (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures) != 0;
+            ImFontAtlasUpdateNewFrame(atlas, g.FrameCount);
+        }
 }
 
 // Build a single texture list
-// We want to avoid user reading from atlas->TexList[] in order to facilitate better support for multiple atlases.
 static void ImGui::UpdateTexturesEndFrame()
 {
     ImGuiContext& g = *GImGui;
-    ImFontAtlas* atlas = g.IO.Fonts;
     g.PlatformIO.Textures.resize(0);
-    g.PlatformIO.Textures.reserve(atlas->TexList.Size);
-    for (ImTextureData* tex : atlas->TexList)
-    {
-        // We provide this information so backends can decide whether to destroy textures.
-        // This means in practice that if N imgui contexts are created with a shared atlas, we assume all of them have a backend initialized.
-        tex->RefCount = (unsigned short)atlas->RefCount;
-        g.PlatformIO.Textures.push_back(tex);
-    }
+    for (ImFontAtlas* atlas : g.FontAtlases)
+        for (ImTextureData* tex : atlas->TexList)
+        {
+            // We provide this information so backends can decide whether to destroy textures.
+            // This means in practice that if N imgui contexts are created with a shared atlas, we assume all of them have a backend initialized.
+            tex->RefCount = (unsigned short)atlas->RefCount;
+            g.PlatformIO.Textures.push_back(tex);
+        }
 }
 
 // Called once a frame. Followed by SetCurrentFont() which sets up the remaining data.
@@ -5810,8 +5808,8 @@ void ImGui::EndFrame()
     UpdateTexturesEndFrame();
 
     // Unlock font atlas
-    ImFontAtlas* atlas = g.IO.Fonts;
-    atlas->Locked = false;
+    for (ImFontAtlas* atlas : g.FontAtlases)
+        atlas->Locked = false;
 
     // Clear Input data for next frame
     g.IO.MousePosPrev = g.IO.MousePos;
@@ -5890,7 +5888,8 @@ void ImGui::Render()
 
 #ifndef IMGUI_DISABLE_DEBUG_TOOLS
     if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures)
-        ImFontAtlasDebugLogTextureRequests(g.IO.Fonts);
+        for (ImFontAtlas* atlas : g.FontAtlases)
+            ImFontAtlasDebugLogTextureRequests(atlas);
 #endif
 
     CallContextHooks(&g, ImGuiContextHookType_RenderPost);
@@ -8596,9 +8595,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)
-        atlas->Locked = true;
+        for (ImFontAtlas* atlas : g.FontAtlases)
+            atlas->Locked = true;
 
     // We do this really unusual thing of calling *push_front()*, the reason behind that we want to support the PushFont()/NewFrame()/PopFont() idiom.
     ImFontStackData font_stack_data = { ImGui::GetDefaultFont(), ImGui::GetDefaultFont()->DefaultSize };
@@ -8614,6 +8613,25 @@ void ImGui::UpdateFontsEndFrame()
     PopFont();
 }
 
+void ImGui::RegisterFontAtlas(ImFontAtlas* atlas)
+{
+    ImGuiContext& g = *GImGui;
+    if (g.FontAtlases.Size == 0)
+        IM_ASSERT(atlas == g.IO.Fonts);
+    atlas->RefCount++;
+    g.FontAtlases.push_back(atlas);
+    ImFontAtlasAddDrawListSharedData(atlas, &g.DrawListSharedData);
+}
+
+void ImGui::UnregisterFontAtlas(ImFontAtlas* atlas)
+{
+    ImGuiContext& g = *GImGui;
+    IM_ASSERT(atlas->RefCount > 0);
+    ImFontAtlasRemoveDrawListSharedData(atlas, &g.DrawListSharedData);
+    g.FontAtlases.find_erase(atlas);
+    atlas->RefCount--;
+}
+
 // Use ImDrawList::_SetTexture(), making our shared g.FontStack[] authoritative against window-local ImDrawList.
 // - Whereas ImDrawList::PushTexture()/PopTexture() is not to be used across Begin() calls.
 // - Note that we don't propagate current texture id when e.g. Begin()-ing into a new window, we never really did...
@@ -8670,6 +8688,7 @@ void ImGui::UpdateCurrentFontSize()
 void ImGui::SetFontRasterizerDensity(float rasterizer_density)
 {
     ImGuiContext& g = *GImGui;
+    IM_ASSERT(g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures);
     if (g.FontRasterizerDensity == rasterizer_density)
         return;
     g.FontRasterizerDensity = rasterizer_density;
@@ -16104,12 +16123,12 @@ void ImGui::ShowMetricsWindow(bool* p_open)
     }
 
     // Details for Fonts
-    ImFontAtlas* atlas = g.IO.Fonts;
-    if (TreeNode("Fonts", "Fonts (%d), Textures (%d)", atlas->Fonts.Size, atlas->TexList.Size))
-    {
-        ShowFontAtlas(atlas);
-        TreePop();
-    }
+    for (ImFontAtlas* atlas : g.FontAtlases)
+        if (TreeNode((void*)atlas, "Fonts (%d), Textures (%d)", atlas->Fonts.Size, atlas->TexList.Size))
+        {
+            ShowFontAtlas(atlas);
+            TreePop();
+        }
 
     // Details for Popups
     if (TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size))

+ 1 - 0
imgui.h

@@ -3684,6 +3684,7 @@ struct ImFontAtlas
     void*                       FontLoaderData;     // Font backend opaque storage
     unsigned int                FontBuilderFlags;   // [FIXME: Should be called FontLoaderFlags] Shared flags (for all fonts) for font loader. THIS IS BUILD IMPLEMENTATION DEPENDENT (e.g. . Per-font override is also available in ImFontConfig.
     int                         RefCount;           // Number of contexts using this atlas
+    ImGuiContext*               OwnerContext;       // Context which own the atlas will be in charge of updating and destroying it.
 
     // [Obsolete]
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS

+ 3 - 1
imgui_internal.h

@@ -2132,10 +2132,10 @@ struct ImGuiContextHook
 struct ImGuiContext
 {
     bool                    Initialized;
-    bool                    FontAtlasOwnedByContext;            // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
     ImGuiIO                 IO;
     ImGuiPlatformIO         PlatformIO;
     ImGuiStyle              Style;
+    ImVector<ImFontAtlas*>  FontAtlases;                        // List of font atlases used by the context (generally only contains g.IO.Fonts aka the main font atlas)
     ImFont*                 Font;                               // == FontStack.back().Font
     ImFontBaked*            FontBaked;                          // == Font->GetFontBaked(FontSize)
     float                   FontSize;                           // == FontSizeBeforeScaling * io.FontGlobalScale * font->Scale * g.CurrentWindow->FontWindowScale. Current text height.
@@ -3108,6 +3108,8 @@ namespace ImGui
     IMGUI_API void          SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags);
 
     // Fonts, drawing
+    IMGUI_API void          RegisterFontAtlas(ImFontAtlas* atlas);
+    IMGUI_API void          UnregisterFontAtlas(ImFontAtlas* atlas);
     IMGUI_API void          SetCurrentFont(ImFont* font, float font_size);
     IMGUI_API void          SetFontRasterizerDensity(float rasterizer_density);
     inline float            GetFontRasterizerDensity() { return GImGui->FontRasterizerDensity; }