mirror of
https://github.com/ocornut/imgui.git
synced 2025-12-23 14:49:06 +00:00
Fonts: Fixed/improved support for legacy backend. SetTexID() writes into our ImTextureData to keep the indirection, clear TexIsBuilt.
The idea is that a legacy backend can somehow add a if (!atlas->IsBuilt()) ImGui_ImplXXXXX_CreateFontsTexture() call _after_ Render() and some features are supported.
This commit is contained in:
16
imgui.cpp
16
imgui.cpp
@@ -5178,13 +5178,16 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags(const ImVec2& mouse_pos)
|
|||||||
io.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false;
|
io.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME-NEWATLAS-V2: If we aim to support multiple atlases used by same context: how to reach/target all atlases?
|
||||||
static void ImGui::UpdateTexturesNewFrame()
|
static void ImGui::UpdateTexturesNewFrame()
|
||||||
{
|
{
|
||||||
// FIXME-NEWATLAS-V2: If we aim to support multiple atlases used by same context: how to reach/target all atlases?
|
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImFontAtlas* atlas = g.IO.Fonts;
|
ImFontAtlas* atlas = g.IO.Fonts;
|
||||||
if (g.FontAtlasOwnedByContext)
|
if (g.FontAtlasOwnedByContext)
|
||||||
|
{
|
||||||
|
atlas->RendererHasTextures = (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures) != 0;
|
||||||
ImFontAtlasUpdateNewFrame(atlas);
|
ImFontAtlasUpdateNewFrame(atlas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a single texture list
|
// Build a single texture list
|
||||||
@@ -5240,13 +5243,6 @@ void ImGui::NewFrame()
|
|||||||
|
|
||||||
CallContextHooks(&g, ImGuiContextHookType_NewFramePre);
|
CallContextHooks(&g, ImGuiContextHookType_NewFramePre);
|
||||||
|
|
||||||
// Check that font atlas was built or backend support texture reload in which case we can build now
|
|
||||||
ImFontAtlas* atlas = g.IO.Fonts;
|
|
||||||
if (!atlas->TexIsBuilt && (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures))
|
|
||||||
ImFontAtlasBuildMain(atlas);
|
|
||||||
else // Legacy backend
|
|
||||||
IM_ASSERT(atlas->TexIsBuilt && "Backend does not support ImGuiBackendFlags_RendererHasTextures, and font atlas is not built! Update backend OR make sure you called ImGui_ImplXXXX_NewFrame() function for renderer backend, which should call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8().");
|
|
||||||
|
|
||||||
// Check and assert for various common IO and Configuration mistakes
|
// Check and assert for various common IO and Configuration mistakes
|
||||||
ErrorCheckNewFrameSanityChecks();
|
ErrorCheckNewFrameSanityChecks();
|
||||||
|
|
||||||
@@ -8573,11 +8569,7 @@ void ImGui::UpdateFontsNewFrame()
|
|||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
if ((g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures) == 0)
|
if ((g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures) == 0)
|
||||||
{
|
|
||||||
g.IO.Fonts->Locked = true;
|
g.IO.Fonts->Locked = true;
|
||||||
for (ImFont* font : g.IO.Fonts->Fonts)
|
|
||||||
font->LockDisableLoading = true;
|
|
||||||
}
|
|
||||||
SetCurrentFont(GetDefaultFont());
|
SetCurrentFont(GetDefaultFont());
|
||||||
IM_ASSERT(g.Font->IsLoaded());
|
IM_ASSERT(g.Font->IsLoaded());
|
||||||
}
|
}
|
||||||
|
|||||||
29
imgui.h
29
imgui.h
@@ -3332,7 +3332,7 @@ struct ImDrawData
|
|||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] Texture API (ImTextureFormat, ImTextureStatus, ImTextureDataUpdate, ImTextureData
|
// [SECTION] Texture API (ImTextureFormat, ImTextureStatus, ImTextureRect, ImTextureData
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// We intentionally support a limited amount of texture formats to limit burden on CPU-side code and extension.
|
// We intentionally support a limited amount of texture formats to limit burden on CPU-side code and extension.
|
||||||
@@ -3517,17 +3517,20 @@ struct ImFontAtlas
|
|||||||
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 output texture data (CPU side). Saves RAM once the texture has been copied to graphics memory.
|
||||||
|
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
// Build atlas, retrieve pixel data.
|
// Legacy path for build atlas + retrieving pixel data.
|
||||||
// User is in charge of copying the pixels into graphics memory (e.g. create a texture with your engine). Then store your texture handle with SetTexID().
|
// - User is in charge of copying the pixels into graphics memory (e.g. create a texture with your engine). Then store your texture handle with SetTexID().
|
||||||
// The pitch is always = Width * BytesPerPixels (1 or 4)
|
// - The pitch is always = Width * BytesPerPixels (1 or 4)
|
||||||
// Building in RGBA32 format is provided for convenience and compatibility, but note that unless you manually manipulate or copy color data into
|
// - Building in RGBA32 format is provided for convenience and compatibility, but note that unless you manually manipulate or copy color data into
|
||||||
// the texture (e.g. when using the AddCustomRect*** api), then the RGB pixels emitted will always be white (~75% of memory/bandwidth waste.
|
// the texture (e.g. when using the AddCustomRect*** api), then the RGB pixels emitted will always be white (~75% of memory/bandwidth waste.
|
||||||
IMGUI_API bool Build(); // Build pixels data. This is called automatically for you by the GetTexData*** functions.
|
// - From 1.92 with backends supporting ImGuiBackendFlags_RendererHasTextures:
|
||||||
IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel
|
// - Calling Build(), GetTexDataAsAlpha8(), GetTexDataAsRGBA32() is not needed.
|
||||||
IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel
|
// - In backend: replace calls to ImFontAtlas::SetTexID() with calls to ImTextureData::SetTexID() after honoring texture creation.
|
||||||
void SetTexID(ImTextureID id) { TexRef._TexData = NULL; TexRef._TexID = id; } // Called by legacy backends.
|
IMGUI_API bool Build(); // Build pixels data. This is called automatically for you by the GetTexData*** functions.
|
||||||
void SetTexID(ImTextureRef id) { TexRef = id; } // Called by legacy backends.
|
IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel
|
||||||
bool IsBuilt() const { return Fonts.Size > 0 && TexIsBuilt; } // Bit ambiguous: used to detect when user didn't build texture but effectively we should check TexID != 0 except that would be backend dependent...
|
IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel
|
||||||
|
void SetTexID(ImTextureID id) { IM_ASSERT(TexRef._TexID == ImTextureID_Invalid); TexRef._TexData->TexID = id; } // Called by legacy backends. May be called before texture creation.
|
||||||
|
void SetTexID(ImTextureRef id) { IM_ASSERT(TexRef._TexID == ImTextureID_Invalid && id._TexData == NULL); TexRef._TexData->TexID = id._TexID; } // Called by legacy backends.
|
||||||
|
bool IsBuilt() const { return Fonts.Size > 0 && TexIsBuilt; } // Bit ambiguous: used to detect when user didn't build texture but effectively we should check TexID != 0 except that would be backend dependent..
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//-------------------------------------------
|
//-------------------------------------------
|
||||||
@@ -3588,7 +3591,7 @@ struct ImFontAtlas
|
|||||||
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 by ImGui::NewFrame() so 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
|
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.
|
||||||
ImVec2 TexUvScale; // = (1.0f/TexData->TexWidth, 1.0f/TexData->TexHeight)
|
ImVec2 TexUvScale; // = (1.0f/TexData->TexWidth, 1.0f/TexData->TexHeight)
|
||||||
ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel
|
ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel
|
||||||
|
|||||||
@@ -2485,6 +2485,7 @@ void ImTextureData::DestroyPixels()
|
|||||||
// - ImFontAtlas::CalcCustomRectUV()
|
// - ImFontAtlas::CalcCustomRectUV()
|
||||||
// - ImFontAtlasGetMouseCursorTexData()
|
// - ImFontAtlasGetMouseCursorTexData()
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
// - ImFontAtlasBuildMain()
|
||||||
// - ImFontAtlasBuildSetupFontLoader()
|
// - ImFontAtlasBuildSetupFontLoader()
|
||||||
// - ImFontAtlasBuildPreloadAllGlyphRanges()
|
// - ImFontAtlasBuildPreloadAllGlyphRanges()
|
||||||
// - ImFontAtlasBuildUpdatePointers()
|
// - ImFontAtlasBuildUpdatePointers()
|
||||||
@@ -2685,15 +2686,24 @@ 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.
|
||||||
void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas)
|
void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas)
|
||||||
{
|
{
|
||||||
if (atlas->TexIsBuilt && atlas->Builder->PreloadedAllGlyphsRanges)
|
// Check that font atlas was built or backend support texture reload in which case we can build now
|
||||||
|
if (atlas->RendererHasTextures)
|
||||||
{
|
{
|
||||||
ImFontAtlasBuildUpdateRendererHasTexturesFromContext(atlas);
|
atlas->TexIsBuilt = true;
|
||||||
IM_ASSERT_USER_ERROR(atlas->RendererHasTextures == false,
|
if (atlas->Builder == NULL) // This will only happen if fonts were not already loaded.
|
||||||
"Called ImFontAtlas::Build() before ImGuiBackendFlags_RendererHasTextures got set! With new backends: you don't need to call Build().");
|
ImFontAtlasBuildMain(atlas);
|
||||||
}
|
}
|
||||||
|
else // Legacy backend
|
||||||
|
{
|
||||||
|
IM_ASSERT_USER_ERROR(atlas->TexIsBuilt, "Backend does not support ImGuiBackendFlags_RendererHasTextures, and font atlas is not built! Update backend OR make sure you called ImGui_ImplXXXX_NewFrame() function for renderer backend, which should call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8().");
|
||||||
|
}
|
||||||
|
if (atlas->TexIsBuilt && atlas->Builder->PreloadedAllGlyphsRanges)
|
||||||
|
IM_ASSERT_USER_ERROR(atlas->RendererHasTextures == false, "Called ImFontAtlas::Build() before ImGuiBackendFlags_RendererHasTextures got set! With new backends: you don't need to call Build().");
|
||||||
|
|
||||||
|
// Update texture status
|
||||||
for (int tex_n = 0; tex_n < atlas->TexList.Size; tex_n++)
|
for (int tex_n = 0; tex_n < atlas->TexList.Size; tex_n++)
|
||||||
{
|
{
|
||||||
ImTextureData* tex = atlas->TexList[tex_n];
|
ImTextureData* tex = atlas->TexList[tex_n];
|
||||||
@@ -2865,6 +2875,7 @@ void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex,
|
|||||||
tex->UpdateRect.y = ImMin(tex->UpdateRect.y, req.y);
|
tex->UpdateRect.y = ImMin(tex->UpdateRect.y, req.y);
|
||||||
tex->UpdateRect.w = (unsigned short)(new_x1 - tex->UpdateRect.x);
|
tex->UpdateRect.w = (unsigned short)(new_x1 - tex->UpdateRect.x);
|
||||||
tex->UpdateRect.h = (unsigned short)(new_y1 - tex->UpdateRect.y);
|
tex->UpdateRect.h = (unsigned short)(new_y1 - tex->UpdateRect.y);
|
||||||
|
atlas->TexIsBuilt = false;
|
||||||
|
|
||||||
// No need to queue if status is _WantCreate
|
// No need to queue if status is _WantCreate
|
||||||
if (tex->Status == ImTextureStatus_OK || tex->Status == ImTextureStatus_WantUpdates)
|
if (tex->Status == ImTextureStatus_OK || tex->Status == ImTextureStatus_WantUpdates)
|
||||||
@@ -3206,6 +3217,7 @@ bool ImFontAtlasGetMouseCursorTexData(ImFontAtlas* atlas, ImGuiMouseCursor curso
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When atlas->RendererHasTexUpdates == 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!");
|
||||||
@@ -3589,6 +3601,7 @@ void ImFontAtlasBuildReloadFont(ImFontAtlas* atlas, ImFont* font)
|
|||||||
atlas->FontLoader->FontSrcInit(atlas, src);
|
atlas->FontLoader->FontSrcInit(atlas, src);
|
||||||
|
|
||||||
ImFontAtlasBuildSetupFontSpecialGlyphs(atlas, src); // Technically this is called for each source sub-font, tho 99.9% of the time the first one fills everything.
|
ImFontAtlasBuildSetupFontSpecialGlyphs(atlas, src); // Technically this is called for each source sub-font, tho 99.9% of the time the first one fills everything.
|
||||||
|
atlas->TexIsBuilt = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify external systems
|
// Notify external systems
|
||||||
@@ -3684,6 +3697,7 @@ ImTextureData* ImFontAtlasBuildAddTexture(ImFontAtlas* atlas, int w, int h)
|
|||||||
|
|
||||||
new_tex->Create(atlas->TexDesiredFormat, w, h);
|
new_tex->Create(atlas->TexDesiredFormat, w, h);
|
||||||
new_tex->Status = ImTextureStatus_WantCreate;
|
new_tex->Status = ImTextureStatus_WantCreate;
|
||||||
|
atlas->TexIsBuilt = false;
|
||||||
|
|
||||||
ImFontAtlasBuildSetTexture(atlas, new_tex);
|
ImFontAtlasBuildSetTexture(atlas, new_tex);
|
||||||
|
|
||||||
@@ -4037,12 +4051,12 @@ ImFontAtlasRect* ImFontAtlasPackGetRect(ImFontAtlas* atlas, ImFontAtlasRectId id
|
|||||||
|
|
||||||
ImFontGlyph* ImFont::BuildLoadGlyph(ImWchar codepoint)
|
ImFontGlyph* ImFont::BuildLoadGlyph(ImWchar codepoint)
|
||||||
{
|
{
|
||||||
if (LockDisableLoading)
|
ImFontAtlas* atlas = ContainerAtlas;
|
||||||
|
if (LockDisableLoading || atlas->Locked)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
//char utf8_buf[5];
|
//char utf8_buf[5];
|
||||||
//IMGUI_DEBUG_LOG("[font] BuildAddGlyph U+%04X (%s)\n", (unsigned int)codepoint, ImTextCharToUtf8(utf8_buf, (unsigned int)codepoint));
|
//IMGUI_DEBUG_LOG("[font] BuildAddGlyph U+%04X (%s)\n", (unsigned int)codepoint, ImTextCharToUtf8(utf8_buf, (unsigned int)codepoint));
|
||||||
ImFontAtlas* atlas = ContainerAtlas;
|
|
||||||
|
|
||||||
// Load from single source or all sources?
|
// Load from single source or all sources?
|
||||||
int srcs_count = (LockSingleSrcConfigIdx != -1) ? 1 : SourcesCount;
|
int srcs_count = (LockSingleSrcConfigIdx != -1) ? 1 : SourcesCount;
|
||||||
|
|||||||
Reference in New Issue
Block a user