From 12b797755501ae8eced5f6fb33105d8ddc1d1cbc Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 28 May 2026 19:19:11 +0200 Subject: [PATCH 01/18] Tweak CalcTextSize() awkward width rounding/ceiling code to reduce floating-point imprecisions altering the result by 1 even at relatively small width. (#791) + apply same fudge factor to less important roundings. ceilf() is still measurable e.g. ballpark +0.5 for 200k calls. --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 9 ++++----- imgui_draw.cpp | 2 +- imgui_widgets.cpp | 6 +++--- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 46ee7cdc4..1c5535835 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,8 @@ Other Changes: - Fonts: - Added `IMGUI_DISABLE_DEFAULT_FONT_BITMAP`/`IMGUI_DISABLE_DEFAULT_FONT_VECTOR` to disable embedding either fonts separately. (#9407) + - Tweak CalcTextSize() awkward width rounding/ceiling code to reduce floating-point + imprecisions altering the result by 1 even at relatively small width. (#791) - DrawList: - Minor optimization to AddLine(), AddLineH(), AddLineV() functions. (#4091) - Demo: diff --git a/imgui.cpp b/imgui.cpp index ecd3bc1c6..735deb9d4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6199,11 +6199,10 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL); // Round - // FIXME: This has been here since Dec 2015 (7b0bf230) but down the line we want this out. - // FIXME: Investigate using ceilf or e.g. - // - https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c - // - https://embarkstudios.github.io/rust-gpu/api/src/libm/math/ceilf.rs.html - text_size.x = IM_TRUNC(text_size.x + 0.99999f); + // FIXME: This has been here since Dec 2015 (7b0bf230 then 4622fa4b6) but down the line we want this out. See #791. + // Investigate using ceilf or e.g. https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c, https://embarkstudios.github.io/rust-gpu/api/src/libm/math/ceilf.rs.html + // The problem is that ceilf() has a measurable cost. Not high, but measurable! + text_size.x = IM_TRUNC(text_size.x + 0.999f); return text_size; } diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 093f0f140..b112f471d 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -656,7 +656,7 @@ void ImDrawList::_OnChangedVtxOffset() int ImDrawList::_CalcCircleAutoSegmentCount(float radius) const { // Automatic segment count - const int radius_idx = (int)(radius + 0.999999f); // ceil to never reduce accuracy + const int radius_idx = (int)(radius + 0.999f); // ceil to never reduce accuracy if (radius_idx >= 0 && radius_idx < IM_COUNTOF(_Data->CircleSegmentCounts)) return _Data->CircleSegmentCounts[radius_idx]; // Use cached value else diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3807f1f00..a98cb6936 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1748,14 +1748,14 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end const float separator_thickness = style.SeparatorTextBorderSize; const ImVec2 min_size(label_size.x + extra_w + padding.x * 2.0f, ImMax(label_size.y + padding.y * 2.0f, separator_thickness)); const ImRect bb(pos, ImVec2(window->WorkRect.Max.x, pos.y + min_size.y)); - const float text_baseline_y = ImTrunc((bb.GetHeight() - label_size.y) * style.SeparatorTextAlign.y + 0.99999f); //ImMax(padding.y, ImTrunc((style.SeparatorTextSize - label_size.y) * 0.5f)); + const float text_baseline_y = ImTrunc((bb.GetHeight() - label_size.y) * style.SeparatorTextAlign.y + 0.999f); //ImMax(padding.y, ImTrunc((style.SeparatorTextSize - label_size.y) * 0.5f)); ItemSize(min_size, text_baseline_y); if (!ItemAdd(bb, id)) return; const float sep1_x1 = pos.x; const float sep2_x2 = bb.Max.x; - const float seps_y = ImTrunc((bb.Min.y + bb.Max.y) * 0.5f + 0.99999f); + const float seps_y = ImTrunc((bb.Min.y + bb.Max.y) * 0.5f + 0.999f); const float label_avail_w = ImMax(0.0f, sep2_x2 - sep1_x1 - padding.x * 2.0f); const ImVec2 label_pos(pos.x + padding.x + ImMax(0.0f, (label_avail_w - label_size.x - extra_w) * style.SeparatorTextAlign.x), pos.y + text_baseline_y); // FIXME-ALIGN @@ -8952,7 +8952,7 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get // Tooltip on hover if (hovered && inner_bb.Contains(g.IO.MousePos)) { - const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f); + const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.999f); const int v_idx = (int)(t * item_count); IM_ASSERT(v_idx >= 0 && v_idx < values_count); From 75f985998b0b0759470a46cd02e73d1c675487fa Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 29 May 2026 15:59:44 +0200 Subject: [PATCH 02/18] Using custom ceilf inline impl in ImGui::CalcTextSize(). Amend 7b0bf230, 4622fa4b6, 12b7977. (#791) --- imgui.cpp | 7 +++---- imgui.h | 2 +- imgui_internal.h | 1 + 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 735deb9d4..28fc2aa3c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6199,10 +6199,9 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL); // Round - // FIXME: This has been here since Dec 2015 (7b0bf230 then 4622fa4b6) but down the line we want this out. See #791. - // Investigate using ceilf or e.g. https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c, https://embarkstudios.github.io/rust-gpu/api/src/libm/math/ceilf.rs.html - // The problem is that ceilf() has a measurable cost. Not high, but measurable! - text_size.x = IM_TRUNC(text_size.x + 0.999f); + // (see 7b0bf230, 4622fa4b6, #791 for details about this.) + // FIXME: Add a way to disable this. + text_size.x = ImCeilFast(text_size.x); return text_size; } diff --git a/imgui.h b/imgui.h index cc80fc80f..2aa8cb0d7 100644 --- a/imgui.h +++ b/imgui.h @@ -30,7 +30,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.92.9 WIP" -#define IMGUI_VERSION_NUM 19281 +#define IMGUI_VERSION_NUM 19282 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 diff --git a/imgui_internal.h b/imgui_internal.h index 70f2bad39..4b9e18dd1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -531,6 +531,7 @@ inline float ImFloor(float f) { return inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2(ImFloor(v.x), ImFloor(v.y)); } inline float ImTrunc64(float f) { return (float)(ImS64)(f); } inline float ImRound64(float f) { return (float)(ImS64)(f + 0.5f); } // FIXME: Positive values only. +inline float ImCeilFast(float f) { int i = (int)f; return (float)(i + (f > (float)i)); } // Consider using the the bit-hack version (search for "0x1p120f"). inline int ImModPositive(int a, int b) { return (a + b) % b; } inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } From 1d33ea939f702e0fb1b4201f1032ee63993ba3e4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 29 May 2026 18:10:29 +0200 Subject: [PATCH 03/18] DrawList: added ImDrawListFlags_NoTextPixelSnap to disable snapping of AddText() coordinates for a given scope. (#3437, #9417, #2291) This may evolve into a per-call ImDrawFlags option as well. + clip_rect.Max.y early out may be applied before truncation. --- docs/CHANGELOG.txt | 10 ++++++---- imgui.h | 1 + imgui_draw.cpp | 20 +++++++++++++++----- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1c5535835..932ebe129 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,15 +50,17 @@ Other Changes: - Clicking on a window's empty-space to move/focus a window checks for lack of queued focus request. (#9382) - InputText: - - Added style.InputTextCursorSize to configure cursor/caret thickness. (#7031, #9409) - This is automatically scaled by style.ScaleAllSizes(). + - Added `style.InputTextCursorSize` to configure cursor/caret thickness. (#7031, #9409) + This is automatically scaled by `style.ScaleAllSizes()`. - Fonts: - Added `IMGUI_DISABLE_DEFAULT_FONT_BITMAP`/`IMGUI_DISABLE_DEFAULT_FONT_VECTOR` to disable embedding either fonts separately. (#9407) - - Tweak CalcTextSize() awkward width rounding/ceiling code to reduce floating-point + - Tweak `CalcTextSize()` awkward width rounding/ceiling code to reduce floating-point imprecisions altering the result by 1 even at relatively small width. (#791) - DrawList: - - Minor optimization to AddLine(), AddLineH(), AddLineV() functions. (#4091) + - Minor optimization to `AddLine()`, `AddLineH()`, `AddLineV()` functions. (#4091) + - Added `ImDrawListFlags_NoTextPixelSnap` to disable snapping of AddText() + coordinates for a given scope. (#3437, #9417, #2291) - Demo: - Extract 'Widgets->Tree Nodes->Selectable Nodes' out of the 'Advanced' demo for clarity (manual reimplementation of basic selection). diff --git a/imgui.h b/imgui.h index 2aa8cb0d7..050237048 100644 --- a/imgui.h +++ b/imgui.h @@ -3279,6 +3279,7 @@ enum ImDrawListFlags_ ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). ImDrawListFlags_AntiAliasedFill = 1 << 2, // Enable anti-aliased edge around filled shapes (rounded rectangles, circles). ImDrawListFlags_AllowVtxOffset = 1 << 3, // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled. + ImDrawListFlags_NoTextPixelSnap = 1 << 4, // [Internal] Disable automatically snapping AddText() calls to pixel boundaries. }; // Draw command list diff --git a/imgui_draw.cpp b/imgui_draw.cpp index b112f471d..a78a35ac0 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -5764,8 +5764,13 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, Im if (glyph->Colored) col |= ~IM_COL32_A_MASK; float scale = (size >= 0.0f) ? (size / baked->Size) : 1.0f; - float x = IM_TRUNC(pos.x); - float y = IM_TRUNC(pos.y); + float x = pos.x; + float y = pos.y; + if ((draw_list->Flags & ImDrawListFlags_NoTextPixelSnap) == 0) + { + x = IM_TRUNC(x); + y = IM_TRUNC(y); + } float x1 = x + glyph->X0 * scale; float x2 = x + glyph->X1 * scale; @@ -5797,12 +5802,17 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, Im // DO NOT CALL DIRECTLY THIS WILL CHANGE WILDLY IN 2026. Use ImDrawList::AddText(). void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, ImDrawTextFlags flags) { - // Align to be pixel perfect begin: - float x = IM_TRUNC(pos.x); - float y = IM_TRUNC(pos.y); + // Align to be pixel perfect + float x = pos.x; + float y = pos.y; if (y > clip_rect.w) return; + if ((draw_list->Flags & ImDrawListFlags_NoTextPixelSnap) == 0) + { + x = IM_TRUNC(x); + y = IM_TRUNC(y); + } if (!text_end) text_end = text_begin + ImStrlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. From cac16b0d1691e6985dbfbd7e773b00259af45dd7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 29 May 2026 18:39:17 +0200 Subject: [PATCH 04/18] DrawList: rename ImDrawListFlags_NoTextPixelSnap -> ImDrawListFlags_TextNoPixelSnap. (#3437, #9417, #2291) Amend 1d33ea9 --- docs/CHANGELOG.txt | 2 +- imgui.h | 2 +- imgui_draw.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 932ebe129..55803f333 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -59,7 +59,7 @@ Other Changes: imprecisions altering the result by 1 even at relatively small width. (#791) - DrawList: - Minor optimization to `AddLine()`, `AddLineH()`, `AddLineV()` functions. (#4091) - - Added `ImDrawListFlags_NoTextPixelSnap` to disable snapping of AddText() + - Added `ImDrawListFlags_TextNoPixelSnap` to disable snapping of AddText() coordinates for a given scope. (#3437, #9417, #2291) - Demo: - Extract 'Widgets->Tree Nodes->Selectable Nodes' out of the 'Advanced' diff --git a/imgui.h b/imgui.h index 050237048..84c991727 100644 --- a/imgui.h +++ b/imgui.h @@ -3279,7 +3279,7 @@ enum ImDrawListFlags_ ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). ImDrawListFlags_AntiAliasedFill = 1 << 2, // Enable anti-aliased edge around filled shapes (rounded rectangles, circles). ImDrawListFlags_AllowVtxOffset = 1 << 3, // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled. - ImDrawListFlags_NoTextPixelSnap = 1 << 4, // [Internal] Disable automatically snapping AddText() calls to pixel boundaries. + ImDrawListFlags_TextNoPixelSnap = 1 << 4, // [Internal] Disable automatically snapping AddText() calls to pixel boundaries. }; // Draw command list diff --git a/imgui_draw.cpp b/imgui_draw.cpp index a78a35ac0..090efb4d2 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -5766,7 +5766,7 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, Im float scale = (size >= 0.0f) ? (size / baked->Size) : 1.0f; float x = pos.x; float y = pos.y; - if ((draw_list->Flags & ImDrawListFlags_NoTextPixelSnap) == 0) + if ((draw_list->Flags & ImDrawListFlags_TextNoPixelSnap) == 0) { x = IM_TRUNC(x); y = IM_TRUNC(y); @@ -5808,7 +5808,7 @@ begin: float y = pos.y; if (y > clip_rect.w) return; - if ((draw_list->Flags & ImDrawListFlags_NoTextPixelSnap) == 0) + if ((draw_list->Flags & ImDrawListFlags_TextNoPixelSnap) == 0) { x = IM_TRUNC(x); y = IM_TRUNC(y); From 70f02b05581b1b38a981ac375f25c81276b5c97a Mon Sep 17 00:00:00 2001 From: Dex <60656530+dexmoh@users.noreply.github.com> Date: Sun, 31 May 2026 13:54:30 +0200 Subject: [PATCH 05/18] Docs: Fix small grammar mistake in README. (#9423) --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 283dd479b..cc73e28ec 100644 --- a/docs/README.md +++ b/docs/README.md @@ -43,7 +43,7 @@ Dear ImGui is particularly suited to integration in game engines (for tooling), **Backends for a variety of graphics API and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui. -C++20 users wishing to use a module may the use [stripe2933/imgui-module](https://github.com/stripe2933/imgui-module) third-party extension. +C++20 users wishing to use a module may use the [stripe2933/imgui-module](https://github.com/stripe2933/imgui-module) third-party extension. See the [Getting Started & Integration](#getting-started--integration) section of this document for more details. From 3b99fc48832ab8d3930cca0d38a6327239df30a7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 1 Jun 2026 14:23:17 +0200 Subject: [PATCH 06/18] ColorButton: small rendering tweak/optimization for the alpha checkerboard. Inverting the pattern means that for our typical 3x3 grid we don't need to draw 1+4 rounded rectangles, only 1. This also fix the slightly rounding mismatch when switching from a=255 to a<255 paths. --- docs/CHANGELOG.txt | 2 ++ imgui_draw.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 55803f333..76d855165 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -61,6 +61,8 @@ Other Changes: - Minor optimization to `AddLine()`, `AddLineH()`, `AddLineV()` functions. (#4091) - Added `ImDrawListFlags_TextNoPixelSnap` to disable snapping of AddText() coordinates for a given scope. (#3437, #9417, #2291) +- ColorButton: + - Small rendering tweak/optimization for the alpha checkerboard. - Demo: - Extract 'Widgets->Tree Nodes->Selectable Nodes' out of the 'Advanced' demo for clarity (manual reimplementation of basic selection). diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 090efb4d2..d8f9bf8e3 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -6198,8 +6198,8 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p flags = ImDrawFlags_RoundCornersDefault_; if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF) { - ImU32 col_bg1 = GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col)); - ImU32 col_bg2 = GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col)); + ImU32 col_bg1 = GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col)); + ImU32 col_bg2 = GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col)); draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, flags); int yi = 0; @@ -6208,12 +6208,12 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y); if (y2 <= y1) continue; - for (float x = p_min.x + grid_off.x + (yi & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f) + for (float x = p_min.x + grid_off.x + ((yi ^ 1) & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f) { float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x); if (x2 <= x1) continue; - ImDrawFlags cell_flags = ImDrawFlags_RoundCornersNone; + ImDrawFlags cell_flags = ImDrawFlags_RoundCornersNone; // FIXME: Could use CalcRoundingFlagsForRectInRect() if (y1 <= p_min.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersTopLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersTopRight; } if (y2 >= p_max.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersBottomLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersBottomRight; } From 3495e329f38b1e11df6607b26bdbadcdcee5b423 Mon Sep 17 00:00:00 2001 From: Flexan Date: Mon, 1 Jun 2026 15:34:00 +0200 Subject: [PATCH 07/18] Fixed small typo in demo code (#9425) --- imgui_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 673a0248a..e0bbd9af6 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -4121,7 +4121,7 @@ static void DemoWindowWidgetsTooltips() ImGui::BeginDisabled(); ImGui::Button("Disabled item", sz); if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip)) - ImGui::SetTooltip("I am a a tooltip for a disabled item."); + ImGui::SetTooltip("I am a tooltip for a disabled item."); ImGui::EndDisabled(); ImGui::TreePop(); From f241419b7856eda54908534dfea578d83bbbf0c2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 1 Jun 2026 16:48:48 +0200 Subject: [PATCH 08/18] Tabs: use AddRectFilled(). --- imgui_widgets.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a98cb6936..6a6605279 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -10873,13 +10873,9 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI IM_UNUSED(flags); IM_ASSERT(width > 0.0f); const float rounding = ImMax(0.0f, ImMin((flags & ImGuiTabItemFlags_Button) ? g.Style.FrameRounding : g.Style.TabRounding, width * 0.5f - 1.0f)); - const float y1 = bb.Min.y + 1.0f; + const float y1 = bb.Min.y + 1.0f; // Leave a bit of room in title bars. const float y2 = bb.Max.y - g.Style.TabBarBorderSize; - draw_list->PathLineTo(ImVec2(bb.Min.x, y2)); - draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding, y1 + rounding), rounding, 6, 9); - draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding, y1 + rounding), rounding, 9, 12); - draw_list->PathLineTo(ImVec2(bb.Max.x, y2)); - draw_list->PathFillConvex(col); + draw_list->AddRectFilled(bb.Min, ImVec2(bb.Max.x, y2), col, rounding, ImDrawFlags_RoundCornersTop); if (g.Style.TabBorderSize > 0.0f) { draw_list->PathLineTo(ImVec2(bb.Min.x + 0.5f, y2)); From 5aa0393a15f42f3d9274f6f9ea540b0b0e448ac5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 1 Jun 2026 17:23:11 +0200 Subject: [PATCH 09/18] DrawList: don't mark ImDrawListFlags_TextNoPixelSnap as internal in comments. (#3437, #9417, #2291) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 84c991727..d0c5ee8c6 100644 --- a/imgui.h +++ b/imgui.h @@ -3279,7 +3279,7 @@ enum ImDrawListFlags_ ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). ImDrawListFlags_AntiAliasedFill = 1 << 2, // Enable anti-aliased edge around filled shapes (rounded rectangles, circles). ImDrawListFlags_AllowVtxOffset = 1 << 3, // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled. - ImDrawListFlags_TextNoPixelSnap = 1 << 4, // [Internal] Disable automatically snapping AddText() calls to pixel boundaries. + ImDrawListFlags_TextNoPixelSnap = 1 << 4, // Disable automatically snapping AddText() calls to pixel boundaries. }; // Draw command list From 045a0907f4824ed3bfdb95bc8721f197f7d9734e Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 2 Jun 2026 18:05:23 +0200 Subject: [PATCH 10/18] Docs: Fonts.md: added notes about TexMinWidth,TexMinHeight. Probably misplaced: the document could have a section about memory usage considerations? --- docs/FONTS.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/FONTS.md b/docs/FONTS.md index 1e51cde48..f0fbd85f9 100644 --- a/docs/FONTS.md +++ b/docs/FONTS.md @@ -77,6 +77,17 @@ Some solutions: You can use the `ImFontGlyphRangesBuilder` for this purpose and rebuilding your atlas between frames when new characters are needed. This will be the biggest win! - Set `io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;` to disable rounding the texture height to the next power of two. +### (5) Reduce texture resizes/copy on startup + +🆕 Since 1.92, the ImFontAtlas is initially created using a 512x128 texture, then grows as glyphs and fonts are registered. Growth leads to a copy, and both the old and new sized textures are present in memory. If you use known fonts and want to reduce initial growth, you may set `TexMinWidth` and `TexMinHeight` during initializaton. + +```cpp +ImFontAtlas* atlas = io.Fonts; +atlas->TexMinWidth = 1024; +atlas->TexMinHeight = 1024; +atlas->AddFont(...); +``` + ##### [Return to Index](#index) --------------------------------------- From a054a016e28d8fb13a5f2d48b7c51647aa28bc36 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 2 Jun 2026 18:09:48 +0200 Subject: [PATCH 11/18] Docs: Fonts: amends. --- docs/FONTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/FONTS.md b/docs/FONTS.md index f0fbd85f9..ac93bca0c 100644 --- a/docs/FONTS.md +++ b/docs/FONTS.md @@ -79,7 +79,7 @@ Some solutions: ### (5) Reduce texture resizes/copy on startup -🆕 Since 1.92, the ImFontAtlas is initially created using a 512x128 texture, then grows as glyphs and fonts are registered. Growth leads to a copy, and both the old and new sized textures are present in memory. If you use known fonts and want to reduce initial growth, you may set `TexMinWidth` and `TexMinHeight` during initializaton. +🆕 Since 1.92, the ImFontAtlas is initially created using a 512x128 texture, then grows as glyphs and fonts are used. Atlas growth leads to alloc+copy, and both the old and new sized textures are present in memory for a short time (typically one frame). If you use known fonts and want to reduce initial growth, you may set `TexMinWidth` and `TexMinHeight` during initializaton. ```cpp ImFontAtlas* atlas = io.Fonts; From 995e4a65ff44892cc27cf28e5ee4e988337812e9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 2 Jun 2026 18:37:01 +0200 Subject: [PATCH 12/18] (Breaking) TreeNode: commented out legacy name ImGuiTreeNodeFlags_SpanTextWidth which was obsoleted in 1.90.7 (May 2024). Use ImGuiTreeNodeFlags_SpanLabelWidth instead. --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 1 + imgui.h | 6 +++--- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 76d855165..9c3c8e68b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,9 @@ HOW TO UPDATE? Breaking Changes: +- TreeNode: commented out legacy name `ImGuiTreeNodeFlags_SpanTextWidth` which + was obsoleted in 1.90.7 (May 2024). Use `ImGuiTreeNodeFlags_SpanLabelWidth`. + Other Changes: - Windows: diff --git a/imgui.cpp b/imgui.cpp index 28fc2aa3c..c56e9eff1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -395,6 +395,7 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures: When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2026/06/02 (1.92.9) - TreeNode: commented out legacy name ImGuiTreeNodeFlags_SpanTextWidth which was obsoleted in 1.90.7 (May 2024). Use ImGuiTreeNodeFlags_SpanLabelWidth instead. - 2026/05/07 (1.92.8) - DrawList: swapped the last two arguments of AddRect(), AddPolyline(), PathStroke(). - Before: void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f); - After: void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0); diff --git a/imgui.h b/imgui.h index d0c5ee8c6..9f7c3a162 100644 --- a/imgui.h +++ b/imgui.h @@ -1331,7 +1331,7 @@ enum ImGuiTreeNodeFlags_ #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGuiTreeNodeFlags_NavLeftJumpsBackHere = ImGuiTreeNodeFlags_NavLeftJumpsToParent, // Renamed in 1.92.0 - ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth, // Renamed in 1.90.7 + //ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth, // Renamed in 1.90.7 //ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7 #endif }; @@ -2614,7 +2614,7 @@ struct ImGuiIO //void* ImeWindowHandle; // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning. #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - float FontGlobalScale; // Moved io.FontGlobalScale to style.FontScaleMain in 1.92 (June 2025) + float FontGlobalScale; // Moved io.FontGlobalScale to style.FontScaleMain in 1.92.0 (June 2025) // Legacy: before 1.91.1, clipboard functions were stored in ImGuiIO instead of ImGuiPlatformIO. // As this is will affect all users of custom engines/backends, we are providing proper legacy redirection (will obsolete). @@ -3925,7 +3925,7 @@ struct ImFont IMGUI_API void RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c, const ImVec4* cpu_fine_clip = NULL); IMGUI_API void RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, ImDrawTextFlags flags = 0); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(LegacySize * scale, text, text_end, wrap_width); } + inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(LegacySize * scale, text, text_end, wrap_width); } // Obsoleted old name in 1.92.0. Note how `scale` was to `size`. #endif // [Internal] Don't use! From 5a42cddcd2408074ece1f9231ceeb0ca221e6efe Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 2 Jun 2026 18:40:14 +0200 Subject: [PATCH 13/18] Fixed a build issue when defined IMGUI_API + IMGUI_DISABLE_OBSOLETE_FUNCTIONS. (#9424) Amend 6df50a0 --- imgui.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index 9f7c3a162..c4828e591 100644 --- a/imgui.h +++ b/imgui.h @@ -3431,8 +3431,8 @@ struct ImDrawList inline void PushTextureID(ImTextureRef tex_ref) { PushTexture(tex_ref); } // RENAMED in 1.92.0 inline void PopTextureID() { PopTexture(); } // RENAMED in 1.92.0 #else - IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding /*= 0.0f*/, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete; - IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) = delete; + void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding /*= 0.0f*/, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete; + void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) = delete; inline void PathStroke(ImU32 col, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete; #endif //inline void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f) { AddEllipse(center, ImVec2(radius_x, radius_y), col, rot, num_segments, thickness); } // OBSOLETED in 1.90.5 (Mar 2024) From c4eaac6d4856d4136b31f7db6e3974c6d846db4d Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 2 Jun 2026 19:04:14 +0200 Subject: [PATCH 14/18] Fonts: fixed an issue where passing a manually created ImFontAtlas to CreateContext() would incorrectly destroy it in DestroyContext() when ref-count gets back to zero. (#9426) # Conflicts: # docs/CHANGELOG.txt --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9c3c8e68b..4f8cf7054 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -60,6 +60,8 @@ Other Changes: disable embedding either fonts separately. (#9407) - Tweak `CalcTextSize()` awkward width rounding/ceiling code to reduce floating-point imprecisions altering the result by 1 even at relatively small width. (#791) + - Fixed an issue where passing a manually created ImFontAtlas to CreateContext() would + incorrectly destroy it in DestroyContext() when ref-count gets back to zero. (#9426) - DrawList: - Minor optimization to `AddLine()`, `AddLineH()`, `AddLineV()` functions. (#4091) - Added `ImDrawListFlags_TextNoPixelSnap` to disable snapping of AddText() diff --git a/imgui.cpp b/imgui.cpp index c56e9eff1..516bd9dec 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4476,7 +4476,7 @@ void ImGui::Shutdown() for (ImFontAtlas* atlas : g.FontAtlases) { UnregisterFontAtlas(atlas); - if (atlas->RefCount == 0) + if (atlas->RefCount == 0 && atlas->OwnerContext == &g) { atlas->Locked = false; IM_DELETE(atlas); From 14278db0240aefee9af8beb960053aaaea55dce3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Jun 2026 15:27:02 +0200 Subject: [PATCH 15/18] Fonts: better document the fact that ImFontAtlas::Clear()/ClearFonts() functions are unlikely to be useful nowadays + fix tex->Updates[] ever-growing if ClearFonts() is called between frames. --- docs/CHANGELOG.txt | 3 +++ imgui.h | 16 +++++++++------- imgui_draw.cpp | 43 ++++++++++++++++++++++++------------------- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4f8cf7054..98bdb582d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -60,6 +60,9 @@ Other Changes: disable embedding either fonts separately. (#9407) - Tweak `CalcTextSize()` awkward width rounding/ceiling code to reduce floating-point imprecisions altering the result by 1 even at relatively small width. (#791) + - Better document the fact that ImFontAtlas::Clear()/ClearFonts() functions are + unlikely to be useful nowadays. Better recover to an edge case of mistakenly + calling ClearFonts() during rendering. - Fixed an issue where passing a manually created ImFontAtlas to CreateContext() would incorrectly destroy it in DestroyContext() when ref-count gets back to zero. (#9426) - DrawList: diff --git a/imgui.h b/imgui.h index c4828e591..378a8827a 100644 --- a/imgui.h +++ b/imgui.h @@ -3545,7 +3545,7 @@ struct ImTextureData bool WantDestroyNextFrame; // rw - // [Internal] Queued to set ImTextureStatus_WantDestroy next frame. May still be used in the current frame. // Functions - // - If GetPixels() functions asserts while being called by your render loop, it could be caused by calling ImFontAtlas::Clear() instead of ClearFonts()? + // - If GetPixels() functions asserts while being called by your render loop, it could be caused by calling ImFontAtlas::Clear()/ClearFonts()? ImTextureData() { memset((void*)this, 0, sizeof(*this)); Status = ImTextureStatus_Destroyed; TexID = ImTextureID_Invalid; } ~ImTextureData() { DestroyPixels(); } IMGUI_API void Create(ImTextureFormat format, int w, int h); @@ -3699,14 +3699,16 @@ struct ImFontAtlas IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_data_size, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed. IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_data_size, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter. - IMGUI_API void RemoveFont(ImFont* font); - - IMGUI_API void Clear(); // Clear everything (fonts + textures). Don't call mid-frame! - IMGUI_API void ClearFonts(); // Clear input+output font data/glyphs. You can call this mid-frame if you load new fonts afterwards! - IMGUI_API void CompactCache(); // Compact cached glyphs and texture. + IMGUI_API void RemoveFont(ImFont* font); // Remove a font + IMGUI_API void CompactCache(); // Compact cached glyphs and texture. IMGUI_API void SetFontLoader(const ImFontLoader* font_loader); // Change font loader at runtime. - // As we are transitioning toward a new font system, we expect to obsolete those soon: + // Clearing the atlas/fonts has little use nowadays, unless you want to batch remove all fonts. + // - Since 1.92, you can call ClearFonts() mid-frame, if you load new fonts afterwards. + // - As we are transitioning toward our new font system the semantic for those functions gets increasingly misleading and are often a source of issues. + // TL;DR; most likely, don't use any of those functions. We expect to obsolete/rework them. + IMGUI_API void Clear(); // Clear everything (fonts + textures). Don't call mid-frame! + IMGUI_API void ClearFonts(); // Clear input+output font data/glyphs. New fonts and textures will be recreated afterwards. 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 ClearTexData(); // [OBSOLETE] Clear CPU-side copy of the texture data. Saves RAM once the texture has been copied to graphics memory. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index d8f9bf8e3..03376e02d 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2691,6 +2691,7 @@ ImFontAtlas::~ImFontAtlas() // Calling this mid-frame will discard the CPU-side copy of the texture data which is generally unreliable as you may have textures queued for creation or updates. void ImFontAtlas::Clear() { + IMGUI_DEBUG_LOG_FONT("[font] ImFontAtlas::Clear()\n"); bool backup_renderer_has_textures = RendererHasTextures; RendererHasTextures = false; // Full Clear() is supported, but ClearTexData() only isn't. ClearFonts(); @@ -2701,6 +2702,7 @@ void ImFontAtlas::Clear() void ImFontAtlas::ClearFonts() { // FIXME-NEWATLAS: Illegal to remove currently bound font. + IMGUI_DEBUG_LOG_FONT("[font] ImFontAtlas::ClearFonts()\n"); IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!"); for (ImFont* font : Fonts) ImFontAtlasBuildNotifySetFont(this, font, NULL); @@ -2776,6 +2778,28 @@ void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count, bool rendere IM_ASSERT(atlas->Builder == NULL || atlas->Builder->FrameCount < frame_count); // Protection against being called twice. atlas->RendererHasTextures = renderer_has_textures; + // Update texture status and discard old textures. + // (we do this first thing to handle an edge case: if user mistakenly calls ClearFonts()+SetStatus(OK) during + // rendering, it would ImFontAtlasBuildMain() rebuilding before tex->Updates[] gets a chance to be cleared) + // (if somehow we need to move this back lower in the function, we could manually call the code to clear Updates[]). + for (int tex_n = 0; tex_n < atlas->TexList.Size; tex_n++) + { + // Update and remove if requested + ImTextureData* tex = atlas->TexList[tex_n]; + if (tex->Status == ImTextureStatus_WantCreate && atlas->RendererHasTextures) + IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture's TexID/BackendUserData but did not update Status to OK."); + + bool remove_from_list = ImTextureDataUpdateNewFrame(tex); + if (remove_from_list) + { + IM_ASSERT(atlas->TexData != tex); + tex->DestroyPixels(); + IM_DELETE(tex); + atlas->TexList.erase(atlas->TexList.begin() + tex_n); + tex_n--; + } + } + // Check that font atlas was built or backend support texture reload in which case we can build now if (atlas->RendererHasTextures) { @@ -2815,25 +2839,6 @@ void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count, bool rendere builder->BakedPool.Size -= builder->BakedDiscardedCount; builder->BakedDiscardedCount = 0; } - - // Update texture status - for (int tex_n = 0; tex_n < atlas->TexList.Size; tex_n++) - { - // Update and remove if requested - ImTextureData* tex = atlas->TexList[tex_n]; - if (tex->Status == ImTextureStatus_WantCreate && atlas->RendererHasTextures) - IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture's TexID/BackendUserData but did not update Status to OK."); - - bool remove_from_list = ImTextureDataUpdateNewFrame(tex); - if (remove_from_list) - { - IM_ASSERT(atlas->TexData != tex); - tex->DestroyPixels(); - IM_DELETE(tex); - atlas->TexList.erase(atlas->TexList.begin() + tex_n); - tex_n--; - } - } } bool ImTextureDataUpdateNewFrame(ImTextureData* tex) From 7950c96f0e86b761607a34601f19e90afa825bd6 Mon Sep 17 00:00:00 2001 From: Vladimir Perminov Date: Wed, 3 Jun 2026 04:08:21 +0300 Subject: [PATCH 16/18] Backends: OpenGL3: GLSL version detection assume GLSL 410 when GL context is 4.1. Fixes an issue running on macOS with Wine. (#9427, #6577) Amend fc737d23339 --- backends/imgui_impl_opengl3.cpp | 6 +++++- docs/CHANGELOG.txt | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 261ab00e0..a9e32b7ac 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -23,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2026-06-23: OpenGL: GLSL version detection assume GLSL 410 when GL context is 4.1. Fixes an issue running on macOS with Wine. (#9427, #6577) // 2026-04-23: OpenGL: Added support for standard draw callbacks (in platform_io): DrawCallback_ResetRenderState, DrawCallback_SetSamplerLinear, DrawCallback_SetSamplerNearest. (#9378) // 2026-03-12: OpenGL: Fixed invalid assert in ImGui_ImplOpenGL3_UpdateTexture() if ImTextureID_Invalid is defined to be != 0, which became the default since 2026-03-12. (#9295) // 2025-12-11: OpenGL: Fixed embedded loader multiple init/shutdown cycles broken on some platforms. (#8792, #9112) @@ -1048,7 +1049,10 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) #elif defined(__APPLE__) glsl_version = "#version 150"; #else - glsl_version = "#version 130"; + if (bd->GlVersion >= 410) + glsl_version = "#version 410"; + else + glsl_version = "#version 130"; #endif } IM_ASSERT((int)strlen(glsl_version) + 2 < IM_COUNTOF(bd->GlslVersionString)); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 98bdb582d..192a30523 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -75,6 +75,9 @@ Other Changes: - Extract 'Widgets->Tree Nodes->Selectable Nodes' out of the 'Advanced' demo for clarity (manual reimplementation of basic selection). - Backends: + - OpenGL3: + - GLSL version detection assume GLSL 410 when GL context is 4.1. + Fixes an issue running on macOS with Wine. [#9427, #6577) [@perminovVS] - Win32: - Uses `SetProcessDpiAwarenessContext()` instead of `SetThreadDpiAwarenessContext()` when available, fixing OpenGL DPI scaling issues as e.g. NVIDIA drivers tends From fc5e2f28fedf6bbe0d20885a5a144d1206a3474e Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Jun 2026 19:24:06 +0200 Subject: [PATCH 17/18] Examples: WGPU: fixed typo for wvgk cloning. (#9428, #9387) --- examples/example_glfw_wgpu/CMakeLists.txt | 2 +- examples/example_sdl2_wgpu/CMakeLists.txt | 2 +- examples/example_sdl3_wgpu/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/example_glfw_wgpu/CMakeLists.txt b/examples/example_glfw_wgpu/CMakeLists.txt index 95d9fe38a..287a89d62 100644 --- a/examples/example_glfw_wgpu/CMakeLists.txt +++ b/examples/example_glfw_wgpu/CMakeLists.txt @@ -14,7 +14,7 @@ # * build/example_glfw_wgpu[.exe] or build/Debug/example_glfw_wgpu[.exe] # Building for desktop with WGVK (MUCH EASIER) -# 1. git clone https://github.com/manuel5975p/WGVK dawn +# 1. git clone https://github.com/manuel5975p/WGVK wgvk # 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk # 3. cmake --build build # The resulting binary will be found at one of the following locations: diff --git a/examples/example_sdl2_wgpu/CMakeLists.txt b/examples/example_sdl2_wgpu/CMakeLists.txt index aa8a1e575..efe35ff61 100644 --- a/examples/example_sdl2_wgpu/CMakeLists.txt +++ b/examples/example_sdl2_wgpu/CMakeLists.txt @@ -14,7 +14,7 @@ # * build/example_sdl2_wgpu[.exe] or build/Debug/example_sdl2_wgpu[.exe] # Building for desktop with WGVK (MUCH EASIER) -# 1. git clone https://github.com/manuel5975p/WGVK dawn +# 1. git clone https://github.com/manuel5975p/WGVK wgvk # 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk # 3. cmake --build build # The resulting binary will be found at one of the following locations: diff --git a/examples/example_sdl3_wgpu/CMakeLists.txt b/examples/example_sdl3_wgpu/CMakeLists.txt index 7ecf0266d..dd7b1e40b 100644 --- a/examples/example_sdl3_wgpu/CMakeLists.txt +++ b/examples/example_sdl3_wgpu/CMakeLists.txt @@ -14,7 +14,7 @@ # * build/example_sdl3_wgpu[.exe] or build/Debug/example_sdl3_wgpu[.exe] # Building for desktop with WGVK (MUCH EASIER) -# 1. git clone https://github.com/manuel5975p/WGVK dawn +# 1. git clone https://github.com/manuel5975p/WGVK wgvk # 2. cmake -B build -DIMGUI_WGVK_DIR=wgvk # 3. cmake --build build # The resulting binary will be found at one of the following locations: From 6acba3b47d2ac4c7bb5ffb6ab04bcd896b3d3658 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Jun 2026 20:57:51 +0200 Subject: [PATCH 18/18] ImDrawListSharedData: rename CircleSegmentMaxError to CircleTessellationMaxError. Remove misleading ArcFastRadiusCutoff assignment. cc 051ce0765, f107693d9 (3808) --- imgui_draw.cpp | 11 +++++------ imgui_internal.h | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 03376e02d..4a68ff4a8 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -402,7 +402,6 @@ ImDrawListSharedData::ImDrawListSharedData() const float a = ((float)i * 2 * IM_PI) / (float)IM_COUNTOF(ArcFastVtx); ArcFastVtx[i] = ImVec2(ImCos(a), ImSin(a)); } - ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError); } ImDrawListSharedData::~ImDrawListSharedData() @@ -412,17 +411,17 @@ ImDrawListSharedData::~ImDrawListSharedData() void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error) { - if (CircleSegmentMaxError == max_error) + if (CircleTessellationMaxError == max_error) return; IM_ASSERT(max_error > 0.0f); - CircleSegmentMaxError = max_error; + CircleTessellationMaxError = max_error; for (int i = 0; i < IM_COUNTOF(CircleSegmentCounts); i++) { const float radius = (float)i; - CircleSegmentCounts[i] = (ImU8)((i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError) : IM_DRAWLIST_ARCFAST_SAMPLE_MAX); + CircleSegmentCounts[i] = (ImU8)((i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleTessellationMaxError) : IM_DRAWLIST_ARCFAST_SAMPLE_MAX); } - ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError); + ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleTessellationMaxError); } ImDrawList::ImDrawList(ImDrawListSharedData* shared_data) @@ -660,7 +659,7 @@ int ImDrawList::_CalcCircleAutoSegmentCount(float radius) const if (radius_idx >= 0 && radius_idx < IM_COUNTOF(_Data->CircleSegmentCounts)) return _Data->CircleSegmentCounts[radius_idx]; // Use cached value else - return IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError); + return IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleTessellationMaxError); } // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) diff --git a/imgui_internal.h b/imgui_internal.h index 4b9e18dd1..3444a20b5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -873,7 +873,7 @@ struct IMGUI_API ImDrawListSharedData float FontSize; // Current font size (used for for simplified AddText overload) float FontScale; // Current font scale (== FontSize / Font->FontSize) float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() - float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc + float CircleTessellationMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc float InitialFringeScale; // Initial scale to apply to AA fringe ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards) ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()