diff options
Diffstat (limited to 'Source/Core/VideoCommon/OnScreenDisplay.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/OnScreenDisplay.cpp | 62 |
1 files changed, 55 insertions, 7 deletions
diff --git a/Source/Core/VideoCommon/OnScreenDisplay.cpp b/Source/Core/VideoCommon/OnScreenDisplay.cpp index e860c53ec0..0e07dbc397 100644 --- a/Source/Core/VideoCommon/OnScreenDisplay.cpp +++ b/Source/Core/VideoCommon/OnScreenDisplay.cpp @@ -18,6 +18,10 @@ #include "Core/Config/MainSettings.h" +#include "VideoCommon/AbstractGfx.h" +#include "VideoCommon/AbstractTexture.h" +#include "VideoCommon/TextureConfig.h" + namespace OSD { constexpr float LEFT_MARGIN = 10.0f; // Pixels to the left of OSD messages. @@ -32,8 +36,8 @@ static std::atomic<int> s_obscured_pixels_top = 0; struct Message { Message() = default; - Message(std::string text_, u32 duration_, u32 color_) - : text(std::move(text_)), duration(duration_), color(color_) + Message(std::string text_, u32 duration_, u32 color_, std::unique_ptr<Icon> icon_ = nullptr) + : text(std::move(text_)), duration(duration_), color(color_), icon(std::move(icon_)) { timer.Start(); } @@ -42,7 +46,10 @@ struct Message Common::Timer timer; u32 duration = 0; bool ever_drawn = false; + bool should_discard = false; u32 color = 0; + std::unique_ptr<Icon> icon; + std::unique_ptr<AbstractTexture> texture; }; static std::multimap<MessageType, Message> s_messages; static std::mutex s_messages_mutex; @@ -77,6 +84,33 @@ static float DrawMessage(int index, Message& msg, const ImVec2& position, int ti ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing)) { + if (msg.icon) + { + if (!msg.texture) + { + const u32 width = msg.icon->width; + const u32 height = msg.icon->height; + TextureConfig tex_config(width, height, 1, 1, 1, AbstractTextureFormat::RGBA8, 0); + msg.texture = g_gfx->CreateTexture(tex_config); + if (msg.texture) + { + msg.texture->Load(0, width, height, width, msg.icon->rgba_data.data(), + sizeof(u32) * width * height); + } + else + { + // don't try again next time + msg.icon.reset(); + } + } + + if (msg.texture) + { + ImGui::Image(msg.texture.get(), ImVec2(static_cast<float>(msg.icon->width), + static_cast<float>(msg.icon->height))); + } + } + // Use %s in case message contains %. ImGui::TextColored(ARGBToImVec4(msg.color), "%s", msg.text.c_str()); window_height = @@ -91,17 +125,25 @@ static float DrawMessage(int index, Message& msg, const ImVec2& position, int ti return window_height; } -void AddTypedMessage(MessageType type, std::string message, u32 ms, u32 argb) +void AddTypedMessage(MessageType type, std::string message, u32 ms, u32 argb, + std::unique_ptr<Icon> icon) { std::lock_guard lock{s_messages_mutex}; - s_messages.erase(type); - s_messages.emplace(type, Message(std::move(message), ms, argb)); + + // A message may hold a reference to a texture that can only be destroyed on the video thread, so + // only mark the old typed message (if any) for removal. It will be discarded on the next call to + // DrawMessages(). + auto range = s_messages.equal_range(type); + for (auto it = range.first; it != range.second; ++it) + it->second.should_discard = true; + + s_messages.emplace(type, Message(std::move(message), ms, argb, std::move(icon))); } -void AddMessage(std::string message, u32 ms, u32 argb) +void AddMessage(std::string message, u32 ms, u32 argb, std::unique_ptr<Icon> icon) { std::lock_guard lock{s_messages_mutex}; - s_messages.emplace(MessageType::Typeless, Message(std::move(message), ms, argb)); + s_messages.emplace(MessageType::Typeless, Message(std::move(message), ms, argb, std::move(icon))); } void DrawMessages() @@ -117,6 +159,12 @@ void DrawMessages() for (auto it = s_messages.begin(); it != s_messages.end();) { Message& msg = it->second; + if (msg.should_discard) + { + it = s_messages.erase(it); + continue; + } + const s64 time_left = msg.TimeRemaining(); // Make sure we draw them at least once if they were printed with 0ms, |
