From 5d973a87d45ac8d982e31dd1feddf32efdcbbeaa Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 14 May 2024 19:10:31 +0200 Subject: [PATCH] Backends: SDL_Renderer2/SDL_Renderer3: and ImGui_ImplSDLRenderer2_RenderDrawData() and ImGui_ImplSDLRenderer3_RenderDrawData() now takes a SDL_Renderer* parameter. --- backends/imgui_impl_sdlrenderer2.cpp | 41 +++++++++----------- backends/imgui_impl_sdlrenderer2.h | 2 +- backends/imgui_impl_sdlrenderer3.cpp | 43 ++++++++++----------- backends/imgui_impl_sdlrenderer3.h | 2 +- docs/CHANGELOG.txt | 4 ++ examples/example_sdl2_sdlrenderer2/main.cpp | 2 +- examples/example_sdl3_sdlrenderer3/main.cpp | 2 +- imgui.cpp | 1 + 8 files changed, 48 insertions(+), 49 deletions(-) diff --git a/backends/imgui_impl_sdlrenderer2.cpp b/backends/imgui_impl_sdlrenderer2.cpp index bee874687..3d538dfe7 100644 --- a/backends/imgui_impl_sdlrenderer2.cpp +++ b/backends/imgui_impl_sdlrenderer2.cpp @@ -20,6 +20,7 @@ // - Introduction, links and more at the top of imgui.cpp // CHANGELOG +// 2024-05-14: *BREAKING CHANGE* ImGui_ImplSDLRenderer3_RenderDrawData() requires SDL_Renderer* passed as parameter. // 2023-05-30: Renamed imgui_impl_sdlrenderer.h/.cpp to imgui_impl_sdlrenderer2.h/.cpp to accommodate for upcoming SDL3. // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. // 2021-12-21: Update SDL_RenderGeometryRaw() format to work with SDL 2.0.19. @@ -47,9 +48,9 @@ // SDL_Renderer data struct ImGui_ImplSDLRenderer2_Data { - SDL_Renderer* SDLRenderer; + SDL_Renderer* Renderer; // Main viewport's renderer SDL_Texture* FontTexture; - ImGui_ImplSDLRenderer2_Data() { memset((void*)this, 0, sizeof(*this)); } + ImGui_ImplSDLRenderer2_Data() { memset((void*)this, 0, sizeof(*this)); } }; // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts @@ -73,7 +74,7 @@ bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer) io.BackendRendererName = "imgui_impl_sdlrenderer2"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. - bd->SDLRenderer = renderer; + bd->Renderer = renderer; return true; } @@ -92,14 +93,12 @@ void ImGui_ImplSDLRenderer2_Shutdown() IM_DELETE(bd); } -static void ImGui_ImplSDLRenderer2_SetupRenderState() +static void ImGui_ImplSDLRenderer2_SetupRenderState(SDL_Renderer* renderer) { - ImGui_ImplSDLRenderer2_Data* bd = ImGui_ImplSDLRenderer2_GetBackendData(); - // Clear out any viewports and cliprect set by the user // FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process. - SDL_RenderSetViewport(bd->SDLRenderer, nullptr); - SDL_RenderSetClipRect(bd->SDLRenderer, nullptr); + SDL_RenderSetViewport(renderer, nullptr); + SDL_RenderSetClipRect(renderer, nullptr); } void ImGui_ImplSDLRenderer2_NewFrame() @@ -111,16 +110,14 @@ void ImGui_ImplSDLRenderer2_NewFrame() ImGui_ImplSDLRenderer2_CreateDeviceObjects(); } -void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data) +void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer) { - ImGui_ImplSDLRenderer2_Data* bd = ImGui_ImplSDLRenderer2_GetBackendData(); - // If there's a scale factor set by the user, use that instead // If the user has specified a scale factor to SDL_Renderer already via SDL_RenderSetScale(), SDL will scale whatever we pass // to SDL_RenderGeometryRaw() by that scale factor. In that case we don't want to be also scaling it ourselves here. float rsx = 1.0f; float rsy = 1.0f; - SDL_RenderGetScale(bd->SDLRenderer, &rsx, &rsy); + SDL_RenderGetScale(renderer, &rsx, &rsy); ImVec2 render_scale; render_scale.x = (rsx == 1.0f) ? draw_data->FramebufferScale.x : 1.0f; render_scale.y = (rsy == 1.0f) ? draw_data->FramebufferScale.y : 1.0f; @@ -139,16 +136,16 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data) SDL_Rect ClipRect; }; BackupSDLRendererState old = {}; - old.ClipEnabled = SDL_RenderIsClipEnabled(bd->SDLRenderer) == SDL_TRUE; - SDL_RenderGetViewport(bd->SDLRenderer, &old.Viewport); - SDL_RenderGetClipRect(bd->SDLRenderer, &old.ClipRect); + old.ClipEnabled = SDL_RenderIsClipEnabled(renderer) == SDL_TRUE; + SDL_RenderGetViewport(renderer, &old.Viewport); + SDL_RenderGetClipRect(renderer, &old.ClipRect); // Will project scissor/clipping rectangles into framebuffer space ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports ImVec2 clip_scale = render_scale; // Render command lists - ImGui_ImplSDLRenderer2_SetupRenderState(); + ImGui_ImplSDLRenderer2_SetupRenderState(renderer); for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -163,7 +160,7 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data) // User callback, registered via ImDrawList::AddCallback() // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) - ImGui_ImplSDLRenderer2_SetupRenderState(); + ImGui_ImplSDLRenderer2_SetupRenderState(renderer); else pcmd->UserCallback(cmd_list, pcmd); } @@ -180,7 +177,7 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data) continue; SDL_Rect r = { (int)(clip_min.x), (int)(clip_min.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y) }; - SDL_RenderSetClipRect(bd->SDLRenderer, &r); + SDL_RenderSetClipRect(renderer, &r); const float* xy = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, pos)); const float* uv = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, uv)); @@ -192,7 +189,7 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data) // Bind texture, Draw SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID(); - SDL_RenderGeometryRaw(bd->SDLRenderer, tex, + SDL_RenderGeometryRaw(renderer, tex, xy, (int)sizeof(ImDrawVert), color, (int)sizeof(ImDrawVert), uv, (int)sizeof(ImDrawVert), @@ -203,8 +200,8 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data) } // Restore modified SDL_Renderer state - SDL_RenderSetViewport(bd->SDLRenderer, &old.Viewport); - SDL_RenderSetClipRect(bd->SDLRenderer, old.ClipEnabled ? &old.ClipRect : nullptr); + SDL_RenderSetViewport(renderer, &old.Viewport); + SDL_RenderSetClipRect(renderer, old.ClipEnabled ? &old.ClipRect : nullptr); } // Called by Init/NewFrame/Shutdown @@ -220,7 +217,7 @@ bool ImGui_ImplSDLRenderer2_CreateFontsTexture() // Upload texture to graphics system // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling) - bd->FontTexture = SDL_CreateTexture(bd->SDLRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, width, height); + bd->FontTexture = SDL_CreateTexture(bd->Renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, width, height); if (bd->FontTexture == nullptr) { SDL_Log("error creating texture"); diff --git a/backends/imgui_impl_sdlrenderer2.h b/backends/imgui_impl_sdlrenderer2.h index 843850ff4..aee40524d 100644 --- a/backends/imgui_impl_sdlrenderer2.h +++ b/backends/imgui_impl_sdlrenderer2.h @@ -28,7 +28,7 @@ struct SDL_Renderer; IMGUI_IMPL_API bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer); IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_Shutdown(); IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_NewFrame(); -IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data); +IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer); // Called by Init/NewFrame/Shutdown IMGUI_IMPL_API bool ImGui_ImplSDLRenderer2_CreateFontsTexture(); diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp index 2a86f859a..ae75b7c8b 100644 --- a/backends/imgui_impl_sdlrenderer3.cpp +++ b/backends/imgui_impl_sdlrenderer3.cpp @@ -20,6 +20,7 @@ // - Introduction, links and more at the top of imgui.cpp // CHANGELOG +// 2024-05-14: *BREAKING CHANGE* ImGui_ImplSDLRenderer3_RenderDrawData() requires SDL_Renderer* passed as parameter. // 2024-02-12: Amend to query SDL_RenderViewportSet() and restore viewport accordingly. // 2023-05-30: Initial version. @@ -43,9 +44,9 @@ // SDL_Renderer data struct ImGui_ImplSDLRenderer3_Data { - SDL_Renderer* SDLRenderer; + SDL_Renderer* Renderer; // Main viewport's renderer SDL_Texture* FontTexture; - ImGui_ImplSDLRenderer3_Data() { memset((void*)this, 0, sizeof(*this)); } + ImGui_ImplSDLRenderer3_Data() { memset((void*)this, 0, sizeof(*this)); } }; // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts @@ -69,7 +70,7 @@ bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer) io.BackendRendererName = "imgui_impl_sdlrenderer3"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. - bd->SDLRenderer = renderer; + bd->Renderer = renderer; return true; } @@ -88,14 +89,12 @@ void ImGui_ImplSDLRenderer3_Shutdown() IM_DELETE(bd); } -static void ImGui_ImplSDLRenderer3_SetupRenderState() +static void ImGui_ImplSDLRenderer3_SetupRenderState(SDL_Renderer* renderer) { - ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); - // Clear out any viewports and cliprect set by the user // FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process. - SDL_SetRenderViewport(bd->SDLRenderer, nullptr); - SDL_SetRenderClipRect(bd->SDLRenderer, nullptr); + SDL_SetRenderViewport(renderer, nullptr); + SDL_SetRenderClipRect(renderer, nullptr); } void ImGui_ImplSDLRenderer3_NewFrame() @@ -107,16 +106,14 @@ void ImGui_ImplSDLRenderer3_NewFrame() ImGui_ImplSDLRenderer3_CreateDeviceObjects(); } -void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data) +void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer) { - ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); - // If there's a scale factor set by the user, use that instead // If the user has specified a scale factor to SDL_Renderer already via SDL_RenderSetScale(), SDL will scale whatever we pass // to SDL_RenderGeometryRaw() by that scale factor. In that case we don't want to be also scaling it ourselves here. float rsx = 1.0f; float rsy = 1.0f; - SDL_GetRenderScale(bd->SDLRenderer, &rsx, &rsy); + SDL_GetRenderScale(renderer, &rsx, &rsy); ImVec2 render_scale; render_scale.x = (rsx == 1.0f) ? draw_data->FramebufferScale.x : 1.0f; render_scale.y = (rsy == 1.0f) ? draw_data->FramebufferScale.y : 1.0f; @@ -136,17 +133,17 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data) SDL_Rect ClipRect; }; BackupSDLRendererState old = {}; - old.ViewportEnabled = SDL_RenderViewportSet(bd->SDLRenderer) == SDL_TRUE; - old.ClipEnabled = SDL_RenderClipEnabled(bd->SDLRenderer) == SDL_TRUE; - SDL_GetRenderViewport(bd->SDLRenderer, &old.Viewport); - SDL_GetRenderClipRect(bd->SDLRenderer, &old.ClipRect); + old.ViewportEnabled = SDL_RenderViewportSet(renderer) == SDL_TRUE; + old.ClipEnabled = SDL_RenderClipEnabled(renderer) == SDL_TRUE; + SDL_GetRenderViewport(renderer, &old.Viewport); + SDL_GetRenderClipRect(renderer, &old.ClipRect); // Will project scissor/clipping rectangles into framebuffer space ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports ImVec2 clip_scale = render_scale; // Render command lists - ImGui_ImplSDLRenderer3_SetupRenderState(); + ImGui_ImplSDLRenderer3_SetupRenderState(renderer); for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -161,7 +158,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data) // User callback, registered via ImDrawList::AddCallback() // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) - ImGui_ImplSDLRenderer3_SetupRenderState(); + ImGui_ImplSDLRenderer3_SetupRenderState(renderer); else pcmd->UserCallback(cmd_list, pcmd); } @@ -178,7 +175,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data) continue; SDL_Rect r = { (int)(clip_min.x), (int)(clip_min.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y) }; - SDL_SetRenderClipRect(bd->SDLRenderer, &r); + SDL_SetRenderClipRect(renderer, &r); const float* xy = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, pos)); const float* uv = (const float*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, uv)); @@ -186,7 +183,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data) // Bind texture, Draw SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID(); - SDL_RenderGeometryRaw(bd->SDLRenderer, tex, + SDL_RenderGeometryRaw(renderer, tex, xy, (int)sizeof(ImDrawVert), color, (int)sizeof(ImDrawVert), uv, (int)sizeof(ImDrawVert), @@ -197,8 +194,8 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data) } // Restore modified SDL_Renderer state - SDL_SetRenderViewport(bd->SDLRenderer, old.ViewportEnabled ? &old.Viewport : nullptr); - SDL_SetRenderClipRect(bd->SDLRenderer, old.ClipEnabled ? &old.ClipRect : nullptr); + SDL_SetRenderViewport(renderer, old.ViewportEnabled ? &old.Viewport : nullptr); + SDL_SetRenderClipRect(renderer, old.ClipEnabled ? &old.ClipRect : nullptr); } // Called by Init/NewFrame/Shutdown @@ -214,7 +211,7 @@ bool ImGui_ImplSDLRenderer3_CreateFontsTexture() // Upload texture to graphics system // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling) - bd->FontTexture = SDL_CreateTexture(bd->SDLRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, width, height); + bd->FontTexture = SDL_CreateTexture(bd->Renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, width, height); if (bd->FontTexture == nullptr) { SDL_Log("error creating texture"); diff --git a/backends/imgui_impl_sdlrenderer3.h b/backends/imgui_impl_sdlrenderer3.h index dd05adfd4..968ec0825 100644 --- a/backends/imgui_impl_sdlrenderer3.h +++ b/backends/imgui_impl_sdlrenderer3.h @@ -28,7 +28,7 @@ struct SDL_Renderer; IMGUI_IMPL_API bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer); IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_Shutdown(); IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_NewFrame(); -IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data); +IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer); // Called by Init/NewFrame/Shutdown IMGUI_IMPL_API bool ImGui_ImplSDLRenderer3_CreateFontsTexture(); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4293ad78a..df64929a3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,10 @@ HOW TO UPDATE? Breaking changes: +- Backends: SDL_Renderer2/SDL_Renderer3: and ImGui_ImplSDLRenderer2_RenderDrawData() and + ImGui_ImplSDLRenderer3_RenderDrawData() now takes a SDL_Renderer* parameter. This was previously + overlooked from the API but it will facilitate eventual support for multi-viewports. + Other changes: - Nav: fixed holding Ctrl or gamepad L1 from not slowing down keyboard/gamepad tweak speed. diff --git a/examples/example_sdl2_sdlrenderer2/main.cpp b/examples/example_sdl2_sdlrenderer2/main.cpp index bfba8fa6a..8bb309920 100644 --- a/examples/example_sdl2_sdlrenderer2/main.cpp +++ b/examples/example_sdl2_sdlrenderer2/main.cpp @@ -155,7 +155,7 @@ int main(int, char**) SDL_RenderSetScale(renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y); SDL_SetRenderDrawColor(renderer, (Uint8)(clear_color.x * 255), (Uint8)(clear_color.y * 255), (Uint8)(clear_color.z * 255), (Uint8)(clear_color.w * 255)); SDL_RenderClear(renderer); - ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData()); + ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), renderer); SDL_RenderPresent(renderer); } diff --git a/examples/example_sdl3_sdlrenderer3/main.cpp b/examples/example_sdl3_sdlrenderer3/main.cpp index 0f2200a25..802d68cd5 100644 --- a/examples/example_sdl3_sdlrenderer3/main.cpp +++ b/examples/example_sdl3_sdlrenderer3/main.cpp @@ -161,7 +161,7 @@ int main(int, char**) //SDL_RenderSetScale(renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y); SDL_SetRenderDrawColor(renderer, (Uint8)(clear_color.x * 255), (Uint8)(clear_color.y * 255), (Uint8)(clear_color.z * 255), (Uint8)(clear_color.w * 255)); SDL_RenderClear(renderer); - ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData()); + ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), renderer); SDL_RenderPresent(renderer); } diff --git a/imgui.cpp b/imgui.cpp index 7951fed4d..13a14bede 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -430,6 +430,7 @@ CODE 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. + - 2024/05/14 (1.90.7) - backends: SDL_Renderer2 and SDL_Renderer3 backend now take a SDL_Renderer* in their RenderDrawData() functions. - 2024/04/18 (1.90.6) - TreeNode: Fixed a layout inconsistency when using an empty/hidden label followed by a SameLine() call. (#7505, #282) - old: TreeNode("##Hidden"); SameLine(); Text("Hello"); // <-- This was actually incorrect! BUT appeared to look ok with the default style where ItemSpacing.x == FramePadding.x * 2 (it didn't look aligned otherwise). - new: TreeNode("##Hidden"); SameLine(0, 0); Text("Hello"); // <-- This is correct for all styles values.