summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorStenzek <stenzek@gmail.com>2018-10-10 01:26:31 +1100
committerStenzek <stenzek@gmail.com>2019-01-25 11:15:57 +1000
commit600d1fc0bc884644127057fa8cce5d31cbaef143 (patch)
tree33a66054011e565b3b3e09bbca8df6f312ad8230 /Source/Core
parentd1868d9475db2ec99314a2f7f192a63fc40bf962 (diff)
Renderer: Use imgui for drawing debug text and OSD
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/DolphinQt/HotkeyScheduler.cpp90
-rw-r--r--Source/Core/VideoBackends/D3D/Render.cpp4
-rw-r--r--Source/Core/VideoBackends/OGL/Render.cpp7
-rw-r--r--Source/Core/VideoBackends/Software/SWRenderer.cpp5
-rw-r--r--Source/Core/VideoBackends/Vulkan/Renderer.cpp3
-rw-r--r--Source/Core/VideoCommon/OnScreenDisplay.cpp100
-rw-r--r--Source/Core/VideoCommon/OnScreenDisplay.h22
-rw-r--r--Source/Core/VideoCommon/RenderBase.cpp171
-rw-r--r--Source/Core/VideoCommon/RenderBase.h16
-rw-r--r--Source/Core/VideoCommon/Statistics.cpp163
-rw-r--r--Source/Core/VideoCommon/Statistics.h5
-rw-r--r--Source/Core/VideoCommon/VideoBackendBase.cpp6
12 files changed, 269 insertions, 323 deletions
diff --git a/Source/Core/DolphinQt/HotkeyScheduler.cpp b/Source/Core/DolphinQt/HotkeyScheduler.cpp
index cd5c51822f..7cab2eb8a7 100644
--- a/Source/Core/DolphinQt/HotkeyScheduler.cpp
+++ b/Source/Core/DolphinQt/HotkeyScheduler.cpp
@@ -5,6 +5,7 @@
#include "DolphinQt/HotkeyScheduler.h"
#include <algorithm>
+#include <cmath>
#include <thread>
#include <QCoreApplication>
@@ -26,6 +27,7 @@
#include "InputCommon/ControllerInterface/ControllerInterface.h"
+#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/VertexShaderManager.h"
#include "VideoCommon/VideoConfig.h"
@@ -286,43 +288,62 @@ void HotkeyScheduler::Run()
else if (IsHotkey(HK_NEXT_GAME_WIIMOTE_PROFILE_4))
m_profile_cycler.NextWiimoteProfileForGame(3);
- const auto show_msg = [](OSDMessage message) {
- if (g_renderer)
- g_renderer->ShowOSDMessage(message);
+ auto ShowVolume = []() {
+ OSD::AddMessage(std::string("Volume: ") +
+ (SConfig::GetInstance().m_IsMuted ?
+ "Muted" :
+ std::to_string(SConfig::GetInstance().m_Volume)) +
+ "%");
};
// Volume
if (IsHotkey(HK_VOLUME_DOWN))
{
- show_msg(OSDMessage::VolumeChanged);
settings.DecreaseVolume(3);
+ ShowVolume();
}
if (IsHotkey(HK_VOLUME_UP))
{
- show_msg(OSDMessage::VolumeChanged);
settings.IncreaseVolume(3);
+ ShowVolume();
}
if (IsHotkey(HK_VOLUME_TOGGLE_MUTE))
{
- show_msg(OSDMessage::VolumeChanged);
AudioCommon::ToggleMuteVolume();
+ ShowVolume();
}
// Graphics
const auto efb_scale = Config::Get(Config::GFX_EFB_SCALE);
+ auto ShowEFBScale = []() {
+ switch (Config::Get(Config::GFX_EFB_SCALE))
+ {
+ case EFB_SCALE_AUTO_INTEGRAL:
+ OSD::AddMessage("Internal Resolution: Auto (integral)");
+ break;
+ case 1:
+ OSD::AddMessage("Internal Resolution: Native");
+ break;
+ default:
+ OSD::AddMessage("Internal Resolution: %dx", g_Config.iEFBScale);
+ break;
+ }
+ };
if (IsHotkey(HK_INCREASE_IR))
{
- show_msg(OSDMessage::IRChanged);
Config::SetCurrent(Config::GFX_EFB_SCALE, efb_scale + 1);
+ ShowEFBScale();
}
if (IsHotkey(HK_DECREASE_IR))
{
- show_msg(OSDMessage::IRChanged);
if (efb_scale > EFB_SCALE_AUTO_INTEGRAL)
+ {
Config::SetCurrent(Config::GFX_EFB_SCALE, efb_scale - 1);
+ ShowEFBScale();
+ }
}
if (IsHotkey(HK_TOGGLE_CROP))
@@ -330,34 +351,55 @@ void HotkeyScheduler::Run()
if (IsHotkey(HK_TOGGLE_AR))
{
- show_msg(OSDMessage::ARToggled);
const int aspect_ratio = (static_cast<int>(Config::Get(Config::GFX_ASPECT_RATIO)) + 1) & 3;
Config::SetCurrent(Config::GFX_ASPECT_RATIO, static_cast<AspectMode>(aspect_ratio));
+ switch (static_cast<AspectMode>(aspect_ratio))
+ {
+ case AspectMode::Stretch:
+ OSD::AddMessage("Stretch");
+ break;
+ case AspectMode::Analog:
+ OSD::AddMessage("Force 4:3");
+ break;
+ case AspectMode::AnalogWide:
+ OSD::AddMessage("Force 16:9");
+ break;
+ case AspectMode::Auto:
+ default:
+ OSD::AddMessage("Auto");
+ break;
+ }
}
if (IsHotkey(HK_TOGGLE_EFBCOPIES))
{
- show_msg(OSDMessage::EFBCopyToggled);
- Config::SetCurrent(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM,
- !Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM));
+ const bool new_value = !Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM);
+ Config::SetCurrent(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, new_value);
+ OSD::AddMessage(StringFromFormat("Copy EFB: %s", new_value ? "to Texture" : "to RAM"));
}
+ auto ShowXFBCopies = []() {
+ OSD::AddMessage(StringFromFormat(
+ "Copy XFB: %s%s", Config::Get(Config::GFX_HACK_IMMEDIATE_XFB) ? " (Immediate)" : "",
+ Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM) ? "to Texture" : "to RAM"));
+ };
+
if (IsHotkey(HK_TOGGLE_XFBCOPIES))
{
- show_msg(OSDMessage::XFBChanged);
Config::SetCurrent(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM,
!Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM));
+ ShowXFBCopies();
}
if (IsHotkey(HK_TOGGLE_IMMEDIATE_XFB))
{
- show_msg(OSDMessage::XFBChanged);
-
Config::SetCurrent(Config::GFX_HACK_IMMEDIATE_XFB,
!Config::Get(Config::GFX_HACK_IMMEDIATE_XFB));
+ ShowXFBCopies();
}
if (IsHotkey(HK_TOGGLE_FOG))
{
- show_msg(OSDMessage::FogToggled);
- Config::SetCurrent(Config::GFX_DISABLE_FOG, !Config::Get(Config::GFX_DISABLE_FOG));
+ const bool new_value = !Config::Get(Config::GFX_DISABLE_FOG);
+ Config::SetCurrent(Config::GFX_DISABLE_FOG, new_value);
+ OSD::AddMessage(StringFromFormat("Fog: %s", new_value ? "Enabled" : "Disabled"));
}
if (IsHotkey(HK_TOGGLE_DUMPTEXTURES))
@@ -368,22 +410,28 @@ void HotkeyScheduler::Run()
Core::SetIsThrottlerTempDisabled(IsHotkey(HK_TOGGLE_THROTTLE, true));
+ auto ShowEmulationSpeed = []() {
+ OSD::AddMessage(
+ SConfig::GetInstance().m_EmulationSpeed <= 0 ?
+ "Speed Limit: Unlimited" :
+ StringFromFormat("Speed Limit: %li%%",
+ std::lround(SConfig::GetInstance().m_EmulationSpeed * 100.f)));
+ };
+
if (IsHotkey(HK_DECREASE_EMULATION_SPEED))
{
- show_msg(OSDMessage::SpeedChanged);
-
auto speed = SConfig::GetInstance().m_EmulationSpeed - 0.1;
speed = (speed <= 0 || (speed >= 0.95 && speed <= 1.05)) ? 1.0 : speed;
SConfig::GetInstance().m_EmulationSpeed = speed;
+ ShowEmulationSpeed();
}
if (IsHotkey(HK_INCREASE_EMULATION_SPEED))
{
- show_msg(OSDMessage::SpeedChanged);
-
auto speed = SConfig::GetInstance().m_EmulationSpeed + 0.1;
speed = (speed >= 0.95 && speed <= 1.05) ? 1.0 : speed;
SConfig::GetInstance().m_EmulationSpeed = speed;
+ ShowEmulationSpeed();
}
// Slot Saving / Loading
diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp
index 43dd44f60f..87190a6d2b 100644
--- a/Source/Core/VideoBackends/D3D/Render.cpp
+++ b/Source/Core/VideoBackends/D3D/Render.cpp
@@ -595,10 +595,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.0f, 0.0f, static_cast<float>(m_backbuffer_width),
static_cast<float>(m_backbuffer_height));
D3D::context->RSSetViewports(1, &vp);
-
- Renderer::DrawDebugText();
-
- OSD::DrawMessages();
DrawImGui();
g_texture_cache->Cleanup(frameCount);
diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp
index e967ae6a75..c857cce083 100644
--- a/Source/Core/VideoBackends/OGL/Render.cpp
+++ b/Source/Core/VideoBackends/OGL/Render.cpp
@@ -1424,9 +1424,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
ResetAPIState();
- // Do our OSD callbacks
- OSD::DoCallbacks(OSD::CallbackType::OnFrame);
-
// Check if we need to render to a new surface.
CheckForSurfaceChange();
CheckForSurfaceResize();
@@ -1451,10 +1448,6 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region
// Render OSD messages.
glViewport(0, 0, m_backbuffer_width, m_backbuffer_height);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- DrawDebugText();
- OSD::DrawMessages();
DrawImGui();
// Swap the back and front buffers, presenting the image.
diff --git a/Source/Core/VideoBackends/Software/SWRenderer.cpp b/Source/Core/VideoBackends/Software/SWRenderer.cpp
index 0b64022725..f8032f7e5d 100644
--- a/Source/Core/VideoBackends/Software/SWRenderer.cpp
+++ b/Source/Core/VideoBackends/Software/SWRenderer.cpp
@@ -97,13 +97,8 @@ std::unique_ptr<AbstractPipeline> SWRenderer::CreatePipeline(const AbstractPipel
// Called on the GPU thread
void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region, u64 ticks)
{
- OSD::DoCallbacks(OSD::CallbackType::OnFrame);
-
if (!IsHeadless())
- {
- DrawDebugText();
m_window->ShowImage(texture, xfb_region);
- }
UpdateActiveConfig();
}
diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
index 509269368d..5ae6093f24 100644
--- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp
+++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp
@@ -704,9 +704,6 @@ void Renderer::DrawScreen(VKTexture* xfb_texture, const EFBRectangle& xfb_region
// Draw OSD
SetViewport(0.0f, 0.0f, static_cast<float>(backbuffer->GetWidth()),
static_cast<float>(backbuffer->GetHeight()), 0.0f, 1.0f);
- DrawDebugText();
- OSD::DoCallbacks(OSD::CallbackType::OnFrame);
- OSD::DrawMessages();
StateTracker::GetInstance()->SetPendingRebind();
DrawImGui();
diff --git a/Source/Core/VideoCommon/OnScreenDisplay.cpp b/Source/Core/VideoCommon/OnScreenDisplay.cpp
index 62997cd150..d6f9b38a3e 100644
--- a/Source/Core/VideoCommon/OnScreenDisplay.cpp
+++ b/Source/Core/VideoCommon/OnScreenDisplay.cpp
@@ -5,22 +5,79 @@
#include <algorithm>
#include <list>
#include <map>
+#include <mutex>
#include <string>
+#include "imgui.h"
+
#include "Common/CommonTypes.h"
#include "Common/Timer.h"
#include "Core/ConfigManager.h"
#include "VideoCommon/OnScreenDisplay.h"
-#include "VideoCommon/RenderBase.h"
namespace OSD
{
-static std::multimap<CallbackType, Callback> s_callbacks;
+constexpr float LEFT_MARGIN = 10.0f; // Pixels to the left of OSD messages.
+constexpr float TOP_MARGIN = 10.0f; // Pixels above the first OSD message.
+constexpr float WINDOW_PADDING = 4.0f; // Pixels between subsequent OSD messages.
+
+struct Message
+{
+ Message() {}
+ Message(const std::string& text_, u32 timestamp_, u32 color_)
+ : text(text_), timestamp(timestamp_), color(color_)
+ {
+ }
+ std::string text;
+ u32 timestamp;
+ u32 color;
+};
static std::multimap<MessageType, Message> s_messages;
static std::mutex s_messages_mutex;
+static ImVec4 RGBAToImVec4(const u32 rgba)
+{
+ return ImVec4(static_cast<float>((rgba >> 16) & 0xFF) / 255.0f,
+ static_cast<float>((rgba >> 8) & 0xFF) / 255.0f,
+ static_cast<float>((rgba >> 0) & 0xFF) / 255.0f,
+ static_cast<float>((rgba >> 24) & 0xFF) / 255.0f);
+}
+
+static float DrawMessage(int index, const Message& msg, const ImVec2& position, int time_left)
+{
+ // We have to provide a window name, and these shouldn't be duplicated.
+ // So instead, we generate a name based on the number of messages drawn.
+ const std::string window_name = StringFromFormat("osd_%d", index);
+
+ // The size must be reset, otherwise the length of old messages could influence new ones.
+ ImGui::SetNextWindowPos(position);
+ ImGui::SetNextWindowSize(ImVec2(0.0f, 0.0f));
+
+ // Gradually fade old messages away.
+ const float alpha = std::min(1.0f, std::max(0.0f, time_left / 1024.0f));
+ ImGui::PushStyleVar(ImGuiStyleVar_Alpha, alpha);
+
+ float window_height = 0.0f;
+ if (ImGui::Begin(window_name.c_str(), nullptr,
+ ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs |
+ ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings |
+ ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav |
+ ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing))
+ {
+ // Use %s in case message contains %.
+ ImGui::TextColored(RGBAToImVec4(msg.color), "%s", msg.text.c_str());
+ window_height =
+ ImGui::GetWindowSize().y + (WINDOW_PADDING * ImGui::GetIO().DisplayFramebufferScale.y);
+ }
+
+ ImGui::End();
+ ImGui::PopStyleVar();
+
+ return window_height;
+}
+
void AddTypedMessage(MessageType type, const std::string& message, u32 ms, u32 rgba)
{
std::lock_guard<std::mutex> lock(s_messages_mutex);
@@ -35,14 +92,6 @@ void AddMessage(const std::string& message, u32 ms, u32 rgba)
Message(message, Common::Timer::GetTimeMs() + ms, rgba));
}
-void DrawMessage(const Message& msg, int top, int left, int time_left)
-{
- float alpha = std::min(1.0f, std::max(0.0f, time_left / 1024.0f));
- u32 color = (msg.m_rgba & 0xFFFFFF) | ((u32)((msg.m_rgba >> 24) * alpha) << 24);
-
- g_renderer->RenderText(msg.m_str, left, top, color);
-}
-
void DrawMessages()
{
if (!SConfig::GetInstance().bOnScreenDisplayMessages)
@@ -51,21 +100,22 @@ void DrawMessages()
{
std::lock_guard<std::mutex> lock(s_messages_mutex);
- u32 now = Common::Timer::GetTimeMs();
- int left = 20, top = 35;
+ const u32 now = Common::Timer::GetTimeMs();
+ float current_x = LEFT_MARGIN * ImGui::GetIO().DisplayFramebufferScale.x;
+ float current_y = TOP_MARGIN * ImGui::GetIO().DisplayFramebufferScale.y;
+ int index = 0;
auto it = s_messages.begin();
while (it != s_messages.end())
{
const Message& msg = it->second;
- int time_left = (int)(msg.m_timestamp - now);
- DrawMessage(msg, top, left, time_left);
+ const int time_left = static_cast<int>(msg.timestamp - now);
+ current_y += DrawMessage(index++, msg, ImVec2(current_x, current_y), time_left);
if (time_left <= 0)
it = s_messages.erase(it);
else
++it;
- top += 15;
}
}
}
@@ -75,24 +125,4 @@ void ClearMessages()
std::lock_guard<std::mutex> lock(s_messages_mutex);
s_messages.clear();
}
-
-// On-Screen Display Callbacks
-void AddCallback(CallbackType type, Callback cb)
-{
- s_callbacks.emplace(type, cb);
-}
-
-void DoCallbacks(CallbackType type)
-{
- auto it_bounds = s_callbacks.equal_range(type);
- for (auto it = it_bounds.first; it != it_bounds.second; ++it)
- {
- it->second();
- }
-
- // Wipe all callbacks on shutdown
- if (type == CallbackType::Shutdown)
- s_callbacks.clear();
}
-
-} // namespace
diff --git a/Source/Core/VideoCommon/OnScreenDisplay.h b/Source/Core/VideoCommon/OnScreenDisplay.h
index a05f4058ef..51358aff19 100644
--- a/Source/Core/VideoCommon/OnScreenDisplay.h
+++ b/Source/Core/VideoCommon/OnScreenDisplay.h
@@ -11,15 +11,6 @@
namespace OSD
{
-struct Message
-{
- Message() {}
- Message(const std::string& s, u32 ts, u32 rgba) : m_str(s), m_timestamp(ts), m_rgba(rgba) {}
- std::string m_str;
- u32 m_timestamp;
- u32 m_rgba;
-};
-
enum class MessageType
{
NetPlayPing,
@@ -49,20 +40,7 @@ constexpr u32 VERY_LONG = 10000;
void AddMessage(const std::string& message, u32 ms = Duration::SHORT, u32 rgba = Color::YELLOW);
void AddTypedMessage(MessageType type, const std::string& message, u32 ms = Duration::SHORT,
u32 rgba = Color::YELLOW);
-void DrawMessage(const Message& msg, int top, int left, int time_left); // draw one message
void DrawMessages(); // draw the current messages on the screen. Only call once
// per frame.
void ClearMessages();
-
-// On-screen callbacks
-enum class CallbackType
-{
- Initialization,
- OnFrame,
- Shutdown
-};
-using Callback = std::function<void()>;
-
-void AddCallback(CallbackType type, Callback cb);
-void DoCallbacks(CallbackType type);
} // namespace OSD
diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp
index d30a7ccac3..76f3d29864 100644
--- a/Source/Core/VideoCommon/RenderBase.cpp
+++ b/Source/Core/VideoCommon/RenderBase.cpp
@@ -65,6 +65,7 @@
#include "VideoCommon/Statistics.h"
#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/TextureDecoder.h"
+#include "VideoCommon/VertexLoaderManager.h"
#include "VideoCommon/VertexManagerBase.h"
#include "VideoCommon/VertexShaderManager.h"
#include "VideoCommon/VideoConfig.h"
@@ -261,139 +262,64 @@ bool Renderer::CheckForHostConfigChanges()
// Create On-Screen-Messages
void Renderer::DrawDebugText()
{
- std::string final_yellow, final_cyan;
+ const auto& config = SConfig::GetInstance();
- if (g_ActiveConfig.bShowFPS || SConfig::GetInstance().m_ShowFrameCount)
+ if (g_ActiveConfig.bShowFPS)
{
- if (g_ActiveConfig.bShowFPS)
- final_cyan += StringFromFormat("FPS: %.2f", m_fps_counter.GetFPS());
-
- if (g_ActiveConfig.bShowFPS && SConfig::GetInstance().m_ShowFrameCount)
- final_cyan += " - ";
- if (SConfig::GetInstance().m_ShowFrameCount)
+ // Position in the top-right corner of the screen.
+ ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x - (10.0f * m_backbuffer_scale),
+ 10.0f * m_backbuffer_scale),
+ ImGuiCond_Always, ImVec2(1.0f, 0.0f));
+ ImGui::SetNextWindowSize(ImVec2(100.0f * m_backbuffer_scale, 30.0f * m_backbuffer_scale));
+
+ if (ImGui::Begin("FPS", nullptr,
+ ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs |
+ ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings |
+ ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav |
+ ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing))
{
- final_cyan += StringFromFormat("Frame: %" PRIu64, Movie::GetCurrentFrame());
- if (Movie::IsPlayingInput())
- final_cyan += StringFromFormat("\nInput: %" PRIu64 " / %" PRIu64,
- Movie::GetCurrentInputCount(), Movie::GetTotalInputCount());
+ ImGui::TextColored(ImVec4(0.0f, 1.0f, 1.0f, 1.0f), "FPS: %.2f", m_fps_counter.GetFPS());
}
-
- final_cyan += "\n";
- final_yellow += "\n";
- }
-
- if (SConfig::GetInstance().m_ShowLag)
- {
- final_cyan += StringFromFormat("Lag: %" PRIu64 "\n", Movie::GetCurrentLagCount());
- final_yellow += "\n";
- }
-
- if (SConfig::GetInstance().m_ShowInputDisplay)
- {
- final_cyan += Movie::GetInputDisplay();
- final_yellow += "\n";
- }
-
- if (SConfig::GetInstance().m_ShowRTC)
- {
- final_cyan += Movie::GetRTCDisplay();
- final_yellow += "\n";
+ ImGui::End();
}
- // OSD Menu messages
- if (m_osd_message > 0)
+ const bool show_movie_window =
+ config.m_ShowFrameCount | config.m_ShowLag | config.m_ShowInputDisplay | config.m_ShowRTC;
+ if (show_movie_window)
{
- m_osd_time = Common::Timer::GetTimeMs() + 3000;
- m_osd_message = -m_osd_message;
- }
-
- if (static_cast<u32>(m_osd_time) > Common::Timer::GetTimeMs())
- {
- std::string res_text;
- switch (g_ActiveConfig.iEFBScale)
- {
- case EFB_SCALE_AUTO_INTEGRAL:
- res_text = "Auto (integral)";
- break;
- case 1:
- res_text = "Native";
- break;
- default:
- res_text = StringFromFormat("%dx", g_ActiveConfig.iEFBScale);
- break;
- }
- const char* ar_text = "";
- switch (g_ActiveConfig.aspect_mode)
- {
- case AspectMode::Stretch:
- ar_text = "Stretch";
- break;
- case AspectMode::Analog:
- ar_text = "Force 4:3";
- break;
- case AspectMode::AnalogWide:
- ar_text = "Force 16:9";
- break;
- case AspectMode::Auto:
- default:
- ar_text = "Auto";
- break;
- }
- const std::string audio_text = SConfig::GetInstance().m_IsMuted ?
- "Muted" :
- std::to_string(SConfig::GetInstance().m_Volume) + "%";
-
- const char* const efbcopy_text = g_ActiveConfig.bSkipEFBCopyToRam ? "to Texture" : "to RAM";
- const char* const xfbcopy_text = g_ActiveConfig.bSkipXFBCopyToRam ? "to Texture" : "to RAM";
-
- // The rows
- const std::string lines[] = {
- std::string("Internal Resolution: ") + res_text,
- std::string("Aspect Ratio: ") + ar_text + (g_ActiveConfig.bCrop ? " (crop)" : ""),
- std::string("Copy EFB: ") + efbcopy_text,
- std::string("Fog: ") + (g_ActiveConfig.bDisableFog ? "Disabled" : "Enabled"),
- SConfig::GetInstance().m_EmulationSpeed <= 0 ?
- "Speed Limit: Unlimited" :
- StringFromFormat("Speed Limit: %li%%",
- std::lround(SConfig::GetInstance().m_EmulationSpeed * 100.f)),
- std::string("Copy XFB: ") + xfbcopy_text +
- (g_ActiveConfig.bImmediateXFB ? " (Immediate)" : ""),
- "Volume: " + audio_text,
- };
-
- enum
- {
- lines_count = sizeof(lines) / sizeof(*lines)
- };
-
- // The latest changed setting in yellow
- for (int i = 0; i != lines_count; ++i)
- {
- if (m_osd_message == -i - 1)
- final_yellow += lines[i];
- final_yellow += '\n';
- }
-
- // The other settings in cyan
- for (int i = 0; i != lines_count; ++i)
+ // Position under the FPS display.
+ ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x - (10.0f * m_backbuffer_scale),
+ 50.0f * m_backbuffer_scale),
+ ImGuiCond_FirstUseEver, ImVec2(1.0f, 0.0f));
+ ImGui::SetNextWindowSizeConstraints(
+ ImVec2(150.0f * m_backbuffer_scale, 20.0f * m_backbuffer_scale),
+ ImGui::GetIO().DisplaySize);
+ if (ImGui::Begin("Movie", nullptr, ImGuiWindowFlags_NoFocusOnAppearing))
{
- if (m_osd_message != -i - 1)
- final_cyan += lines[i];
- final_cyan += '\n';
+ if (config.m_ShowFrameCount)
+ {
+ ImGui::Text("Frame: %" PRIu64, Movie::GetCurrentFrame());
+ }
+ if (Movie::IsPlayingInput())
+ {
+ ImGui::Text("Input: %" PRIu64 " / %" PRIu64, Movie::GetCurrentInputCount(),
+ Movie::GetTotalInputCount());
+ }
+ if (SConfig::GetInstance().m_ShowLag)
+ ImGui::Text("Lag: %" PRIu64 "\n", Movie::GetCurrentLagCount());
+ if (SConfig::GetInstance().m_ShowInputDisplay)
+ ImGui::TextUnformatted(Movie::GetInputDisplay().c_str());
+ if (SConfig::GetInstance().m_ShowRTC)
+ ImGui::TextUnformatted(Movie::GetRTCDisplay().c_str());
}
+ ImGui::End();
}
- final_cyan += Common::Profiler::ToString();
-
if (g_ActiveConfig.bOverlayStats)
- final_cyan += Statistics::ToString();
+ Statistics::Display();
if (g_ActiveConfig.bOverlayProjStats)
- final_cyan += Statistics::ToStringProj();
-
- // and then the text
- RenderText(final_cyan, 20, 20, 0xFF00FFFF);
- RenderText(final_yellow, 20, 20, 0xFFFFFF00);
+ Statistics::DisplayProj();
}
float Renderer::CalculateDrawAspectRatio() const
@@ -955,6 +881,8 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const
// Draw any imgui overlays we have. Note that "draw" here means "create commands", the actual
// draw calls don't get issued until DrawImGui is called, which happens in SwapImpl.
+ DrawDebugText();
+ OSD::DrawMessages();
ImGui::Render();
// TODO: merge more generic parts into VideoCommon
@@ -1332,8 +1260,3 @@ std::unique_ptr<VideoCommon::AsyncShaderCompiler> Renderer::CreateAsyncShaderCom
{
return std::make_unique<VideoCommon::AsyncShaderCompiler>();
}
-
-void Renderer::ShowOSDMessage(OSDMessage message)
-{
- m_osd_message = static_cast<s32>(message);
-}
diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h
index b232d2c61f..b31384794c 100644
--- a/Source/Core/VideoCommon/RenderBase.h
+++ b/Source/Core/VideoCommon/RenderBase.h
@@ -57,17 +57,6 @@ struct EfbPokeData
extern int frameCount;
-enum class OSDMessage : s32
-{
- IRChanged = 1,
- ARToggled = 2,
- EFBCopyToggled = 3,
- FogToggled = 4,
- SpeedChanged = 5,
- XFBChanged = 6,
- VolumeChanged = 7,
-};
-
// Renderer really isn't a very good name for this class - it's more like "Misc".
// The long term goal is to get rid of this class and replace it with others that make
// more sense.
@@ -201,8 +190,6 @@ public:
virtual std::unique_ptr<VideoCommon::AsyncShaderCompiler> CreateAsyncShaderCompiler();
- void ShowOSDMessage(OSDMessage message);
-
protected:
std::tuple<int, int> CalculateTargetScale(int x, int y) const;
bool CalculateTargetSize();
@@ -303,9 +290,6 @@ private:
u32 m_last_xfb_width = MAX_XFB_WIDTH;
u32 m_last_xfb_height = MAX_XFB_HEIGHT;
- s32 m_osd_message = 0;
- s32 m_osd_time = 0;
-
// NOTE: The methods below are called on the framedumping thread.
bool StartFrameDumpToAVI(const FrameDumpConfig& config);
void DumpFrameToAVI(const FrameDumpConfig& config);
diff --git a/Source/Core/VideoCommon/Statistics.cpp b/Source/Core/VideoCommon/Statistics.cpp
index 0a4a9236b0..af122bfcdb 100644
--- a/Source/Core/VideoCommon/Statistics.cpp
+++ b/Source/Core/VideoCommon/Statistics.cpp
@@ -6,6 +6,8 @@
#include <string>
#include <utility>
+#include "imgui.h"
+
#include "Common/StringUtil.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/VertexLoaderManager.h"
@@ -26,91 +28,98 @@ void Statistics::SwapDL()
std::swap(stats.thisFrame.numBPLoadsInDL, stats.thisFrame.numBPLoads);
}
-std::string Statistics::ToString()
+void Statistics::Display()
{
- std::string str;
+ const float scale = ImGui::GetIO().DisplayFramebufferScale.x;
+ ImGui::SetNextWindowPos(ImVec2(10.0f * scale, 10.0f * scale), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSizeConstraints(ImVec2(275.0f * scale, 400.0f * scale),
+ ImGui::GetIO().DisplaySize);
+ if (!ImGui::Begin("Statistics", nullptr, ImGuiWindowFlags_NoNavInputs))
+ {
+ ImGui::End();
+ return;
+ }
+
+ ImGui::Columns(2, "Statistics", true);
+
+#define DRAW_STAT(name, format, ...) \
+ ImGui::Text(name); \
+ ImGui::NextColumn(); \
+ ImGui::Text(format, __VA_ARGS__); \
+ ImGui::NextColumn();
if (g_ActiveConfig.backend_info.api_type == APIType::Nothing)
{
- str += StringFromFormat("Objects: %i\n", stats.thisFrame.numDrawnObjects);
- str += StringFromFormat("Vertices Loaded: %i\n", stats.thisFrame.numVerticesLoaded);
- str += StringFromFormat("Triangles Input: %i\n", stats.thisFrame.numTrianglesIn);
- str += StringFromFormat("Triangles Rejected: %i\n", stats.thisFrame.numTrianglesRejected);
- str += StringFromFormat("Triangles Culled: %i\n", stats.thisFrame.numTrianglesCulled);
- str += StringFromFormat("Triangles Clipped: %i\n", stats.thisFrame.numTrianglesClipped);
- str += StringFromFormat("Triangles Drawn: %i\n", stats.thisFrame.numTrianglesDrawn);
- str += StringFromFormat("Rasterized Pix: %i\n", stats.thisFrame.rasterizedPixels);
- str += StringFromFormat("TEV Pix In: %i\n", stats.thisFrame.tevPixelsIn);
- str += StringFromFormat("TEV Pix Out: %i\n", stats.thisFrame.tevPixelsOut);
+ DRAW_STAT("Objects", "%d", stats.thisFrame.numDrawnObjects);
+ DRAW_STAT("Vertices Loaded", "%d", stats.thisFrame.numVerticesLoaded);
+ DRAW_STAT("Triangles Input", "%d", stats.thisFrame.numTrianglesIn);
+ DRAW_STAT("Triangles Rejected", "%d", stats.thisFrame.numTrianglesRejected);
+ DRAW_STAT("Triangles Culled", "%d", stats.thisFrame.numTrianglesCulled);
+ DRAW_STAT("Triangles Clipped", "%d", stats.thisFrame.numTrianglesClipped);
+ DRAW_STAT("Triangles Drawn", "%d", stats.thisFrame.numTrianglesDrawn);
+ DRAW_STAT("Rasterized Pix", "%d", stats.thisFrame.rasterizedPixels);
+ DRAW_STAT("TEV Pix In", "%d", stats.thisFrame.tevPixelsIn);
+ DRAW_STAT("TEV Pix Out", "%d", stats.thisFrame.tevPixelsOut);
}
- str += StringFromFormat("Textures created: %i\n", stats.numTexturesCreated);
- str += StringFromFormat("Textures uploaded: %i\n", stats.numTexturesUploaded);
- str += StringFromFormat("Textures alive: %i\n", stats.numTexturesAlive);
- str += StringFromFormat("pshaders created: %i\n", stats.numPixelShadersCreated);
- str += StringFromFormat("pshaders alive: %i\n", stats.numPixelShadersAlive);
- str += StringFromFormat("vshaders created: %i\n", stats.numVertexShadersCreated);
- str += StringFromFormat("vshaders alive: %i\n", stats.numVertexShadersAlive);
- str += StringFromFormat("shaders changes: %i\n", stats.thisFrame.numShaderChanges);
- str += StringFromFormat("dlists called: %i\n", stats.thisFrame.numDListsCalled);
- str += StringFromFormat("Primitive joins: %i\n", stats.thisFrame.numPrimitiveJoins);
- str += StringFromFormat("Draw calls: %i\n", stats.thisFrame.numDrawCalls);
- str += StringFromFormat("Primitives: %i\n", stats.thisFrame.numPrims);
- str += StringFromFormat("Primitives (DL): %i\n", stats.thisFrame.numDLPrims);
- str += StringFromFormat("XF loads: %i\n", stats.thisFrame.numXFLoads);
- str += StringFromFormat("XF loads (DL): %i\n", stats.thisFrame.numXFLoadsInDL);
- str += StringFromFormat("CP loads: %i\n", stats.thisFrame.numCPLoads);
- str += StringFromFormat("CP loads (DL): %i\n", stats.thisFrame.numCPLoadsInDL);
- str += StringFromFormat("BP loads: %i\n", stats.thisFrame.numBPLoads);
- str += StringFromFormat("BP loads (DL): %i\n", stats.thisFrame.numBPLoadsInDL);
- str += StringFromFormat("Vertex streamed: %i kB\n", stats.thisFrame.bytesVertexStreamed / 1024);
- str += StringFromFormat("Index streamed: %i kB\n", stats.thisFrame.bytesIndexStreamed / 1024);
- str += StringFromFormat("Uniform streamed: %i kB\n", stats.thisFrame.bytesUniformStreamed / 1024);
- str += StringFromFormat("Vertex Loaders: %i\n", stats.numVertexLoaders);
-
- std::string vertex_list = VertexLoaderManager::VertexLoadersToString();
-
- // TODO : at some point text1 just becomes too huge and overflows, we can't even read the added
- // stuff
- // since it gets added at the far bottom of the screen anyway (actually outside the rendering
- // window)
- // we should really reset the list instead of using substr
- if (vertex_list.size() + str.size() > 8170)
- vertex_list = vertex_list.substr(0, 8170 - str.size());
-
- str += vertex_list;
-
- return str;
+ DRAW_STAT("Textures created", "%d", stats.numTexturesCreated);
+ DRAW_STAT("Textures uploaded", "%d", stats.numTexturesUploaded);
+ DRAW_STAT("Textures alive", "%d", stats.numTexturesAlive);
+ DRAW_STAT("pshaders created", "%d", stats.numPixelShadersCreated);
+ DRAW_STAT("pshaders alive", "%d", stats.numPixelShadersAlive);
+ DRAW_STAT("vshaders created", "%d", stats.numVertexShadersCreated);
+ DRAW_STAT("vshaders alive", "%d", stats.numVertexShadersAlive);
+ DRAW_STAT("shaders changes", "%d", stats.thisFrame.numShaderChanges);
+ DRAW_STAT("dlists called", "%d", stats.thisFrame.numDListsCalled);
+ DRAW_STAT("Primitive joins", "%d", stats.thisFrame.numPrimitiveJoins);
+ DRAW_STAT("Draw calls", "%d", stats.thisFrame.numDrawCalls);
+ DRAW_STAT("Primitives", "%d", stats.thisFrame.numPrims);
+ DRAW_STAT("Primitives (DL)", "%d", stats.thisFrame.numDLPrims);
+ DRAW_STAT("XF loads", "%d", stats.thisFrame.numXFLoads);
+ DRAW_STAT("XF loads (DL)", "%d", stats.thisFrame.numXFLoadsInDL);
+ DRAW_STAT("CP loads", "%d", stats.thisFrame.numCPLoads);
+ DRAW_STAT("CP loads (DL)", "%d", stats.thisFrame.numCPLoadsInDL);
+ DRAW_STAT("BP loads", "%d", stats.thisFrame.numBPLoads);
+ DRAW_STAT("BP loads (DL)", "%d", stats.thisFrame.numBPLoadsInDL);
+ DRAW_STAT("Vertex streamed", "%i kB", stats.thisFrame.bytesVertexStreamed / 1024);
+ DRAW_STAT("Index streamed", "%i kB", stats.thisFrame.bytesIndexStreamed / 1024);
+ DRAW_STAT("Uniform streamed", "%i kB", stats.thisFrame.bytesUniformStreamed / 1024);
+ DRAW_STAT("Vertex Loaders", "%d", stats.numVertexLoaders);
+
+#undef DRAW_STAT
+
+ ImGui::Columns(1);
+
+ ImGui::End();
}
// Is this really needed?
-std::string Statistics::ToStringProj()
+void Statistics::DisplayProj()
{
- std::string projections;
-
- projections += "Projection #: X for Raw 6=0 (X for Raw 6!=0)\n\n";
- projections += StringFromFormat("Projection 0: %f (%f) Raw 0: %f\n", stats.gproj_0,
- stats.g2proj_0, stats.proj_0);
- projections += StringFromFormat("Projection 1: %f (%f)\n", stats.gproj_1, stats.g2proj_1);
- projections += StringFromFormat("Projection 2: %f (%f) Raw 1: %f\n", stats.gproj_2,
- stats.g2proj_2, stats.proj_1);
- projections += StringFromFormat("Projection 3: %f (%f)\n\n", stats.gproj_3, stats.g2proj_3);
- projections += StringFromFormat("Projection 4: %f (%f)\n", stats.gproj_4, stats.g2proj_4);
- projections += StringFromFormat("Projection 5: %f (%f) Raw 2: %f\n", stats.gproj_5,
- stats.g2proj_5, stats.proj_2);
- projections += StringFromFormat("Projection 6: %f (%f) Raw 3: %f\n", stats.gproj_6,
- stats.g2proj_6, stats.proj_3);
- projections += StringFromFormat("Projection 7: %f (%f)\n\n", stats.gproj_7, stats.g2proj_7);
- projections += StringFromFormat("Projection 8: %f (%f)\n", stats.gproj_8, stats.g2proj_8);
- projections += StringFromFormat("Projection 9: %f (%f)\n", stats.gproj_9, stats.g2proj_9);
- projections += StringFromFormat("Projection 10: %f (%f) Raw 4: %f\n\n", stats.gproj_10,
- stats.g2proj_10, stats.proj_4);
- projections += StringFromFormat("Projection 11: %f (%f) Raw 5: %f\n\n", stats.gproj_11,
- stats.g2proj_11, stats.proj_5);
- projections += StringFromFormat("Projection 12: %f (%f)\n", stats.gproj_12, stats.g2proj_12);
- projections += StringFromFormat("Projection 13: %f (%f)\n", stats.gproj_13, stats.g2proj_13);
- projections += StringFromFormat("Projection 14: %f (%f)\n", stats.gproj_14, stats.g2proj_14);
- projections += StringFromFormat("Projection 15: %f (%f)\n", stats.gproj_15, stats.g2proj_15);
-
- return projections;
+ if (!ImGui::Begin("Projection Statistics", nullptr, ImGuiWindowFlags_NoNavInputs))
+ {
+ ImGui::End();
+ return;
+ }
+
+ ImGui::Text("Projection #: X for Raw 6=0 (X for Raw 6!=0)");
+ ImGui::NewLine();
+ ImGui::Text("Projection 0: %f (%f) Raw 0: %f", stats.gproj_0, stats.g2proj_0, stats.proj_0);
+ ImGui::Text("Projection 1: %f (%f)", stats.gproj_1, stats.g2proj_1);
+ ImGui::Text("Projection 2: %f (%f) Raw 1: %f", stats.gproj_2, stats.g2proj_2, stats.proj_1);
+ ImGui::Text("Projection 3: %f (%f)", stats.gproj_3, stats.g2proj_3);
+ ImGui::Text("Projection 4: %f (%f)", stats.gproj_4, stats.g2proj_4);
+ ImGui::Text("Projection 5: %f (%f) Raw 2: %f", stats.gproj_5, stats.g2proj_5, stats.proj_2);
+ ImGui::Text("Projection 6: %f (%f) Raw 3: %f", stats.gproj_6, stats.g2proj_6, stats.proj_3);
+ ImGui::Text("Projection 7: %f (%f)", stats.gproj_7, stats.g2proj_7);
+ ImGui::Text("Projection 8: %f (%f)", stats.gproj_8, stats.g2proj_8);
+ ImGui::Text("Projection 9: %f (%f)", stats.gproj_9, stats.g2proj_9);
+ ImGui::Text("Projection 10: %f (%f) Raw 4: %f", stats.gproj_10, stats.g2proj_10, stats.proj_4);
+ ImGui::Text("Projection 11: %f (%f) Raw 5: %f", stats.gproj_11, stats.g2proj_11, stats.proj_5);
+ ImGui::Text("Projection 12: %f (%f)", stats.gproj_12, stats.g2proj_12);
+ ImGui::Text("Projection 13: %f (%f)", stats.gproj_13, stats.g2proj_13);
+ ImGui::Text("Projection 14: %f (%f)", stats.gproj_14, stats.g2proj_14);
+ ImGui::Text("Projection 15: %f (%f)", stats.gproj_15, stats.g2proj_15);
+
+ ImGui::End();
}
diff --git a/Source/Core/VideoCommon/Statistics.h b/Source/Core/VideoCommon/Statistics.h
index 74ee317b82..c743bf7f08 100644
--- a/Source/Core/VideoCommon/Statistics.h
+++ b/Source/Core/VideoCommon/Statistics.h
@@ -65,9 +65,8 @@ struct Statistics
ThisFrame thisFrame;
void ResetFrame();
static void SwapDL();
-
- static std::string ToString();
- static std::string ToStringProj();
+ static void Display();
+ static void DisplayProj();
};
extern Statistics stats;
diff --git a/Source/Core/VideoCommon/VideoBackendBase.cpp b/Source/Core/VideoCommon/VideoBackendBase.cpp
index fd6bbdfa2b..aa8b3d110f 100644
--- a/Source/Core/VideoCommon/VideoBackendBase.cpp
+++ b/Source/Core/VideoCommon/VideoBackendBase.cpp
@@ -278,9 +278,6 @@ void VideoBackendBase::InitializeShared()
memset(&g_preprocess_cp_state, 0, sizeof(g_preprocess_cp_state));
memset(texMem, 0, TMEM_SIZE);
- // Do our OSD callbacks
- OSD::DoCallbacks(OSD::CallbackType::Initialization);
-
// do not initialize again for the config window
m_initialized = true;
@@ -303,9 +300,6 @@ void VideoBackendBase::InitializeShared()
void VideoBackendBase::ShutdownShared()
{
- // Do our OSD callbacks
- OSD::DoCallbacks(OSD::CallbackType::Shutdown);
-
m_initialized = false;
VertexLoaderManager::Clear();