summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTryTwo <taolas@gmail.com>2025-08-12 02:00:44 -0700
committerTryTwo <taolas@gmail.com>2025-08-18 05:38:14 -0700
commitaffc22f17d329a4d17d595dd468ce82ac3a015dd (patch)
tree605230fcdc34211ac94fcd8f391efb7941b8e3cf
parent7315acb9816de9f32165e5bd2eeb0b7f1e8519f4 (diff)
Update code to work with new version of ImGui.
UpdateImGuiTexture now handles creating font textures and modifying them.
-rw-r--r--Source/Core/VideoCommon/AbstractTexture.cpp5
-rw-r--r--Source/Core/VideoCommon/AbstractTexture.h5
-rw-r--r--Source/Core/VideoCommon/OnScreenUI.cpp134
-rw-r--r--Source/Core/VideoCommon/OnScreenUI.h2
4 files changed, 117 insertions, 29 deletions
diff --git a/Source/Core/VideoCommon/AbstractTexture.cpp b/Source/Core/VideoCommon/AbstractTexture.cpp
index d60925ab25..a557f46020 100644
--- a/Source/Core/VideoCommon/AbstractTexture.cpp
+++ b/Source/Core/VideoCommon/AbstractTexture.cpp
@@ -20,6 +20,11 @@ AbstractTexture::AbstractTexture(const TextureConfig& c) : m_config(c)
{
}
+AbstractTexture::operator ImTextureRef() const
+{
+ return ImTextureRef(reinterpret_cast<AbstractTexture::imgui_texture_id>(this));
+}
+
void AbstractTexture::FinishedRendering()
{
}
diff --git a/Source/Core/VideoCommon/AbstractTexture.h b/Source/Core/VideoCommon/AbstractTexture.h
index da5c2d69b2..3abd535b13 100644
--- a/Source/Core/VideoCommon/AbstractTexture.h
+++ b/Source/Core/VideoCommon/AbstractTexture.h
@@ -10,15 +10,18 @@
#include "Common/MathUtil.h"
#include "VideoCommon/TextureConfig.h"
+struct ImTextureRef;
+
class AbstractTexture
{
public:
explicit AbstractTexture(const TextureConfig& c);
virtual ~AbstractTexture() = default;
- // Support implicit conversion between AbstractTexture and ImTextureId
+ // Support implicit conversion between AbstractTexture and ImTextureId and ImTextureRef.
using imgui_texture_id = unsigned long long;
operator imgui_texture_id() const { return reinterpret_cast<imgui_texture_id>(this); }
+ operator ImTextureRef() const;
virtual void CopyRectangleFromTexture(const AbstractTexture* src,
const MathUtil::Rectangle<int>& src_rect, u32 src_layer,
diff --git a/Source/Core/VideoCommon/OnScreenUI.cpp b/Source/Core/VideoCommon/OnScreenUI.cpp
index d1c15f7f80..e9f72587f5 100644
--- a/Source/Core/VideoCommon/OnScreenUI.cpp
+++ b/Source/Core/VideoCommon/OnScreenUI.cpp
@@ -17,6 +17,7 @@
#include "VideoCommon/AbstractGfx.h"
#include "VideoCommon/AbstractPipeline.h"
#include "VideoCommon/AbstractShader.h"
+#include "VideoCommon/AbstractStagingTexture.h"
#include "VideoCommon/FramebufferShaderGen.h"
#include "VideoCommon/NetPlayChatUI.h"
#include "VideoCommon/NetPlayGolfUI.h"
@@ -71,30 +72,12 @@ bool OnScreenUI::Initialize(u32 width, u32 height, float scale)
return false;
}
- // Font texture(s).
- {
- ImGuiIO& io = ImGui::GetIO();
- u8* font_tex_pixels;
- int font_tex_width, font_tex_height;
- io.Fonts->GetTexDataAsRGBA32(&font_tex_pixels, &font_tex_width, &font_tex_height);
-
- TextureConfig font_tex_config(font_tex_width, font_tex_height, 1, 1, 1,
- AbstractTextureFormat::RGBA8, 0,
- AbstractTextureType::Texture_2DArray);
- std::unique_ptr<AbstractTexture> font_tex =
- g_gfx->CreateTexture(font_tex_config, "ImGui font texture");
- if (!font_tex)
- {
- PanicAlertFmt("Failed to create ImGui texture");
- return false;
- }
- font_tex->Load(0, font_tex_width, font_tex_height, font_tex_width, font_tex_pixels,
- sizeof(u32) * font_tex_width * font_tex_height);
+ // Font defaults
+ m_imgui_textures.clear();
- io.Fonts->TexID = *font_tex.get();
-
- m_imgui_textures.push_back(std::move(font_tex));
- }
+ // Setup new font management behavior.
+ ImGui::GetIO().BackendFlags |=
+ ImGuiBackendFlags_RendererHasTextures | ImGuiBackendFlags_RendererHasVtxOffset;
if (!RecompileImGuiPipeline())
return false;
@@ -113,6 +96,7 @@ OnScreenUI::~OnScreenUI()
ImGui::EndFrame();
ImPlot::DestroyContext();
ImGui::DestroyContext();
+ m_imgui_textures.clear();
}
bool OnScreenUI::RecompileImGuiPipeline()
@@ -252,7 +236,7 @@ void OnScreenUI::DrawImGui()
static_cast<int>(cmd.ClipRect.x), static_cast<int>(cmd.ClipRect.y),
static_cast<int>(cmd.ClipRect.z), static_cast<int>(cmd.ClipRect.w)),
g_gfx->GetCurrentFramebuffer()));
- g_gfx->SetTexture(0, reinterpret_cast<const AbstractTexture*>(cmd.TextureId));
+ g_gfx->SetTexture(0, reinterpret_cast<const AbstractTexture*>(cmd.GetTexID()));
g_gfx->DrawIndexed(base_index, cmd.ElemCount, base_vertex);
base_index += cmd.ElemCount;
}
@@ -410,6 +394,98 @@ void OnScreenUI::Finalize()
OSD::DrawMessages();
DrawChallengesAndLeaderboards();
ImGui::Render();
+
+ // Create or update fonts.
+ ImDrawData* draw_data = ImGui::GetDrawData();
+ if (draw_data->Textures != nullptr)
+ for (ImTextureData* tex : *draw_data->Textures)
+ if (tex->Status != ImTextureStatus_OK)
+ UpdateImguiTexture(tex);
+}
+
+void OnScreenUI::UpdateImguiTexture(ImTextureData* tex)
+{
+ if (tex->Status == ImTextureStatus_WantCreate)
+ {
+ // Create new font texture.
+ IM_ASSERT(tex->TexID == ImTextureID_Invalid);
+ IM_ASSERT(tex->Format == ImTextureFormat_RGBA32);
+
+ TextureConfig font_tex_config(tex->Width, tex->Height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0,
+ AbstractTextureType::Texture_2DArray);
+ std::unique_ptr<AbstractTexture> font_tex =
+ g_gfx->CreateTexture(font_tex_config, "ImGui font texture");
+
+ if (!font_tex)
+ {
+ PanicAlertFmt("Failed to create ImGui texture");
+ return;
+ }
+
+ font_tex->Load(0, tex->Width, tex->Height, tex->Width, tex->Pixels,
+ sizeof(u32) * tex->Width * tex->Height);
+
+ tex->SetTexID(static_cast<ImTextureID>(*font_tex.get()));
+ // Keeps the texture alive.
+ m_imgui_textures.push_back(std::move(font_tex));
+
+ tex->SetStatus(ImTextureStatus_OK);
+ }
+ else if (tex->Status == ImTextureStatus_WantUpdates)
+ {
+ AbstractTexture* font_tex = reinterpret_cast<AbstractTexture*>(tex->GetTexID());
+
+ if (!font_tex || tex->TexID == ImTextureID_Invalid)
+ {
+ PanicAlertFmt("ImGui texture not created before update");
+ return;
+ }
+
+ for (const ImTextureRect& r : tex->Updates)
+ {
+ // Rect of texture that will be updated.
+ const int x_offset = static_cast<int>(r.x);
+ const int y_offset = static_cast<int>(r.y);
+ const int width = static_cast<int>(r.w);
+ const int height = static_cast<int>(r.h);
+
+ // Create a staging texture to update the font texture with.
+ TextureConfig font_tex_config(width, height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0,
+ AbstractTextureType::Texture_2DArray);
+ std::unique_ptr<AbstractStagingTexture> stage =
+ g_gfx->CreateStagingTexture(StagingTextureType::Upload, font_tex_config);
+
+ const int src_pitch = width * tex->BytesPerPixel;
+
+ // Write to staging texture.
+ for (int y = 0; y < height; y++)
+ {
+ const MathUtil::Rectangle<int> rect_line = {0, y, width, y + 1};
+ stage->WriteTexels(rect_line, tex->GetPixelsAt(x_offset, y_offset + y), src_pitch);
+ }
+
+ // Copy to font texture.
+ const MathUtil::Rectangle<int> rect_staging = {0, 0, width, height};
+ const MathUtil::Rectangle<int> rect_target = {x_offset, y_offset, width + x_offset,
+ height + y_offset};
+
+ stage->CopyToTexture(rect_staging, font_tex, rect_target, 0, 0);
+ }
+
+ tex->SetStatus(ImTextureStatus_OK);
+ }
+ else if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames > 0)
+ {
+ AbstractTexture* font_tex = reinterpret_cast<AbstractTexture*>(tex->GetTexID());
+
+ tex->SetTexID(ImTextureID_Invalid);
+
+ m_imgui_textures.erase(
+ std::find_if(m_imgui_textures.begin(), m_imgui_textures.end(),
+ [font_tex](auto& element) { return element.get() == font_tex; }));
+
+ tex->Status = ImTextureStatus_Destroyed;
+ }
}
std::unique_lock<std::mutex> OnScreenUI::GetImGuiLock()
@@ -421,12 +497,14 @@ void OnScreenUI::SetScale(float backbuffer_scale)
{
ImGui::GetIO().DisplayFramebufferScale.x = backbuffer_scale;
ImGui::GetIO().DisplayFramebufferScale.y = backbuffer_scale;
- ImGui::GetIO().FontGlobalScale = backbuffer_scale;
+
// ScaleAllSizes scales in-place, so calling it twice will double-apply the scale
// Reset the style first so that the scale is applied to the base style, not an already-scaled one
- ImGui::GetStyle() = {};
- ImGui::GetStyle().WindowRounding = 7.0f;
- ImGui::GetStyle().ScaleAllSizes(backbuffer_scale);
+ ImGuiStyle& style = ImGui::GetStyle();
+ style = {};
+ style.FontScaleMain = backbuffer_scale;
+ style.WindowRounding = 7.0f;
+ style.ScaleAllSizes(backbuffer_scale);
m_backbuffer_scale = backbuffer_scale;
}
diff --git a/Source/Core/VideoCommon/OnScreenUI.h b/Source/Core/VideoCommon/OnScreenUI.h
index 28749807be..7f9c7aa3c2 100644
--- a/Source/Core/VideoCommon/OnScreenUI.h
+++ b/Source/Core/VideoCommon/OnScreenUI.h
@@ -15,6 +15,7 @@
class NativeVertexFormat;
class AbstractTexture;
class AbstractPipeline;
+class ImTextureData;
namespace VideoCommon
{
@@ -62,6 +63,7 @@ public:
private:
void DrawDebugText();
void DrawChallengesAndLeaderboards();
+ void UpdateImguiTexture(ImTextureData* tex);
// ImGui resources.
std::unique_ptr<NativeVertexFormat> m_imgui_vertex_format;