From d360c800945d05ff2dd200e30cd8711378f3f010 Mon Sep 17 00:00:00 2001 From: IceTDrinker Date: Sat, 27 Apr 2019 13:08:19 +0200 Subject: [PATCH] FPS Counter at the end of the display chain 1) Gives actual refresh rate of the window 2) FPS display based on profiler data, toggleable by pressing the the h key on the keyboard, use Shift + h to modify FPS text scale (x1, x2 or x4) 3) Fix linux build by updating the gtk window 4) Fix linux build again, include microprofiler header directly and correct parameters sent to ImGui::Text 5) Fix linux build by using a define to hide undefined functions on linux --- src/xenia/app/emulator_window.cc | 7 ++++++ src/xenia/ui/window.cc | 43 ++++++++++++++++++++++++++++++++ src/xenia/ui/window.h | 24 +++++++++++++++++- src/xenia/ui/window_gtk.cc | 4 +-- src/xenia/ui/window_gtk.h | 3 ++- src/xenia/ui/window_win.cc | 4 +-- src/xenia/ui/window_win.h | 3 ++- 7 files changed, 81 insertions(+), 7 deletions(-) diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index 62ff25948..b40202370 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -100,6 +100,13 @@ bool EmulatorWindow::Initialize() { window_->on_key_down.AddListener([this](KeyEvent* e) { bool handled = true; switch (e->key_code()) { + case 0x48: { // h + if (e->is_shift_pressed()) { + window_->FPSTextScale(); + } else { + window_->ToggleFPS(); + } + } break; case 0x4F: { // o if (e->is_ctrl_pressed()) { FileOpen(); diff --git a/src/xenia/ui/window.cc b/src/xenia/ui/window.cc index 8be8900c8..e43dd117f 100644 --- a/src/xenia/ui/window.cc +++ b/src/xenia/ui/window.cc @@ -17,6 +17,8 @@ #include "xenia/base/logging.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/base/profiling.h" + namespace xe { namespace ui { @@ -183,6 +185,33 @@ void Window::OnPaint(UIEvent* e) { tick_frequency)); fps_update_time_ticks_ = now_ticks; fps_frame_count_ = 0; + +#if XE_OPTION_PROFILING + // This means FPS counter will not work with profiling disabled (e.g. on + // Linux) + float fToMs = + MicroProfileTickToMsMultiplier(MicroProfileTicksPerSecondCpu()); + uint64_t nFlipTicks = 0; + { + std::lock_guard lock(MicroProfileGetMutex()); + MicroProfile& S = *MicroProfileGet(); + nFlipTicks = S.nFlipTicks; + } + float fMs = fToMs * nFlipTicks; + + if (fMs != 0.0f) { + game_fps_ = static_cast(1000.0f / fMs); + } +#endif + + title_fps_text_ = base_title_; + title_fps_text_ += " | "; + title_fps_text_ += std::to_string(game_fps_); + title_fps_text_ += " FPS"; + set_title(title_fps_text_, false); + + osd_fps_text_ = std::to_string(game_fps_); + osd_fps_text_ += " FPS"; } GraphicsContextLock context_lock(context_.get()); @@ -213,6 +242,20 @@ void Window::OnPaint(UIEvent* e) { ForEachListener([e](auto listener) { listener->OnPaint(e); }); on_paint(e); + if (display_fps_) { + ImGui::Begin("FPS", (bool*)0, + ImGuiWindowFlags_::ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_::ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_::ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_::ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_::ImGuiWindowFlags_NoSavedSettings | + ImGuiWindowFlags_::ImGuiWindowFlags_NoInputs); + ImGui::SetWindowFontScale(fps_font_scale_); + ImGui::Text("%s", osd_fps_text_.c_str()); + ImGui::SetWindowSize({0.0f, 0.0f}); // Resize to fit content + ImGui::End(); + } + // Flush ImGui buffers before we swap. ImGui::Render(); imgui_drawer_->RenderDrawLists(); diff --git a/src/xenia/ui/window.h b/src/xenia/ui/window.h index e1e48e2a0..551d235ab 100644 --- a/src/xenia/ui/window.h +++ b/src/xenia/ui/window.h @@ -47,15 +47,27 @@ class Window { virtual void EnableMainMenu() = 0; virtual void DisableMainMenu() = 0; + const std::string& title() const { return title_; } - virtual bool set_title(const std::string& title) { + virtual bool set_title(const std::string& title, + bool set_base_title = true) { if (title == title_) { return false; } title_ = title; + if (set_base_title) { + base_title_ = title; + } return true; } + void ToggleFPS() { display_fps_ = !display_fps_; } + + void FPSTextScale() { + fps_font_scale_ = fps_font_scale_ * 2.0f; + fps_font_scale_ = (fps_font_scale_ > 4.0f) ? 1.0f : fps_font_scale_; + } + virtual bool SetIcon(const void* buffer, size_t size) = 0; void ResetIcon() { SetIcon(nullptr, 0); } @@ -171,7 +183,10 @@ class Window { Loop* loop_ = nullptr; std::unique_ptr main_menu_; + std::string title_; + std::string base_title_; + int32_t width_ = 0; int32_t height_ = 0; bool has_focus_ = true; @@ -187,6 +202,13 @@ class Window { uint64_t fps_frame_count_ = 0; uint64_t last_paint_time_ticks_ = 0; + bool display_fps_ = false; + uint32_t game_fps_ = 0; + float fps_font_scale_ = 1.0f; + + std::string title_fps_text_; + std::string osd_fps_text_; + bool modifier_shift_pressed_ = false; bool modifier_cntrl_pressed_ = false; bool modifier_alt_pressed_ = false; diff --git a/src/xenia/ui/window_gtk.cc b/src/xenia/ui/window_gtk.cc index a6ca2087b..30e49f491 100644 --- a/src/xenia/ui/window_gtk.cc +++ b/src/xenia/ui/window_gtk.cc @@ -99,8 +99,8 @@ void GTKWindow::OnClose() { super::OnClose(); } -bool GTKWindow::set_title(const std::string& title) { - if (!super::set_title(title)) { +bool GTKWindow::set_title(const std::string& title, bool set_base_title) { + if (!super::set_title(title, set_base_title)) { return false; } gtk_window_set_title(GTK_WINDOW(window_), (gchar*)title.c_str()); diff --git a/src/xenia/ui/window_gtk.h b/src/xenia/ui/window_gtk.h index b0b56f70d..1a49e58ce 100644 --- a/src/xenia/ui/window_gtk.h +++ b/src/xenia/ui/window_gtk.h @@ -38,7 +38,8 @@ class GTKWindow : public Window { void EnableMainMenu() override {} void DisableMainMenu() override {} - bool set_title(const std::string& title) override; + bool set_title(const std::string& title, + bool set_base_title = true) override; bool SetIcon(const void* buffer, size_t size) override; diff --git a/src/xenia/ui/window_win.cc b/src/xenia/ui/window_win.cc index 2e60d2e42..b47729526 100644 --- a/src/xenia/ui/window_win.cc +++ b/src/xenia/ui/window_win.cc @@ -198,8 +198,8 @@ void Win32Window::DisableMainMenu() { } } -bool Win32Window::set_title(const std::string& title) { - if (!super::set_title(title)) { +bool Win32Window::set_title(const std::string& title, bool set_base_title) { + if (!super::set_title(title, set_base_title)) { return false; } SetWindowTextW(hwnd_, reinterpret_cast(xe::to_utf16(title).c_str())); diff --git a/src/xenia/ui/window_win.h b/src/xenia/ui/window_win.h index da638afdc..4c5d1301e 100644 --- a/src/xenia/ui/window_win.h +++ b/src/xenia/ui/window_win.h @@ -34,7 +34,8 @@ class Win32Window : public Window { void EnableMainMenu() override; void DisableMainMenu() override; - bool set_title(const std::string& title) override; + bool set_title(const std::string& title, + bool set_base_title = true) override; bool SetIcon(const void* buffer, size_t size) override;