FullscreenUI: Don't clear state when switching renderers

Fixes things like the achievement summary not being displayed, or if the
pause menu is never accessed, the popups from showing at all.
This commit is contained in:
Connor McLaughlin 2022-12-03 00:38:08 +10:00 committed by refractionpcsx2
parent d52352966e
commit 1cb10eb889
13 changed files with 125 additions and 91 deletions

View File

@ -255,7 +255,7 @@ void Host::OnInputDeviceDisconnected(const std::string_view& identifier)
{
}
bool Host::AcquireHostDisplay(RenderAPI api)
bool Host::AcquireHostDisplay(RenderAPI api, bool clear_state_on_fail)
{
const std::optional<WindowInfo> wi(GSRunner::GetPlatformWindowInfo());
if (!wi.has_value())
@ -267,7 +267,7 @@ bool Host::AcquireHostDisplay(RenderAPI api)
if (!g_host_display->CreateDevice(wi.value()) || !g_host_display->MakeCurrent() || !g_host_display->SetupDevice() || !ImGuiManager::Initialize())
{
ReleaseHostDisplay();
ReleaseHostDisplay(clear_state_on_fail);
return false;
}
@ -277,12 +277,9 @@ bool Host::AcquireHostDisplay(RenderAPI api)
return g_host_display.get();
}
void Host::ReleaseHostDisplay()
void Host::ReleaseHostDisplay(bool clear_state)
{
if (!g_host_display)
return;
ImGuiManager::Shutdown();
ImGuiManager::Shutdown(clear_state);
g_host_display.reset();
}

View File

@ -866,7 +866,7 @@ void EmuThread::updateDisplay()
}
}
bool EmuThread::acquireHostDisplay(RenderAPI api)
bool EmuThread::acquireHostDisplay(RenderAPI api, bool clear_state_on_fail)
{
pxAssertRel(!g_host_display, "Host display does not exist on create");
m_is_rendering_to_main = shouldRenderToMain();
@ -888,24 +888,24 @@ bool EmuThread::acquireHostDisplay(RenderAPI api)
if (!g_host_display->MakeCurrent())
{
Console.Error("Failed to make render context current");
releaseHostDisplay();
releaseHostDisplay(clear_state_on_fail);
return false;
}
if (!g_host_display->SetupDevice() || !ImGuiManager::Initialize())
{
Console.Error("Failed to initialize device/imgui");
releaseHostDisplay();
releaseHostDisplay(clear_state_on_fail);
return false;
}
Console.WriteLn(Color_StrongGreen, "%s Graphics Driver Info:", HostDisplay::RenderAPIToString(g_host_display->GetRenderAPI()));
Console.Indent().WriteLn(g_host_display->GetDriverInfo());
if (m_run_fullscreen_ui && !FullscreenUI::Initialize())
if (m_run_fullscreen_ui && !ImGuiManager::InitializeFullscreenUI())
{
Console.Error("Failed to initialize fullscreen UI");
releaseHostDisplay();
releaseHostDisplay(clear_state_on_fail);
m_run_fullscreen_ui = false;
return false;
}
@ -913,22 +913,22 @@ bool EmuThread::acquireHostDisplay(RenderAPI api)
return true;
}
void EmuThread::releaseHostDisplay()
void EmuThread::releaseHostDisplay(bool clear_state)
{
ImGuiManager::Shutdown();
ImGuiManager::Shutdown(clear_state);
g_host_display.reset();
emit onDestroyDisplayRequested();
}
bool Host::AcquireHostDisplay(RenderAPI api)
bool Host::AcquireHostDisplay(RenderAPI api, bool clear_state_on_fail)
{
return g_emu_thread->acquireHostDisplay(api);
return g_emu_thread->acquireHostDisplay(api, clear_state_on_fail);
}
void Host::ReleaseHostDisplay()
void Host::ReleaseHostDisplay(bool clear_state)
{
g_emu_thread->releaseHostDisplay();
g_emu_thread->releaseHostDisplay(clear_state);
}
VsyncMode Host::GetEffectiveVSyncMode()

View File

@ -70,9 +70,9 @@ public:
bool shouldRenderToMain() const;
/// Called back from the GS thread when the display state changes (e.g. fullscreen, render to main).
bool acquireHostDisplay(RenderAPI api);
bool acquireHostDisplay(RenderAPI api, bool clear_state_on_fail);
void connectDisplaySignals(DisplayWidget* widget);
void releaseHostDisplay();
void releaseHostDisplay(bool clear_state);
void updateDisplay();
void startBackgroundControllerPollTimer();

View File

@ -19,6 +19,7 @@
#include "Frontend/CommonHost.h"
#include "Frontend/FullscreenUI.h"
#include "Frontend/ImGuiFullscreen.h"
#include "Frontend/ImGuiManager.h"
#include "common/Assertions.h"
#include "common/FileSystem.h"
@ -427,7 +428,7 @@ std::string Achievements::GetUserAgent()
void Achievements::BeginLoadingScreen(const char* text, bool* was_running_idle)
{
GetMTGS().RunOnGSThread(&FullscreenUI::Initialize);
GetMTGS().RunOnGSThread(&ImGuiManager::InitializeFullscreenUI);
ImGuiFullscreen::OpenBackgroundProgressDialog("achievements_loading", text, 0, 0, 0);
}
@ -1131,7 +1132,7 @@ void Achievements::GetPatchesCallback(s32 status_code, const std::string& conten
return;
// ensure fullscreen UI is ready
GetMTGS().RunOnGSThread([]() { FullscreenUI::Initialize(); });
GetMTGS().RunOnGSThread(&ImGuiManager::InitializeFullscreenUI);
s_game_id = response.id;
s_game_title = response.title;

View File

@ -553,17 +553,12 @@ bool FullscreenUI::Initialize()
if (!ImGuiManager::AddFullscreenFontsIfMissing() || !ImGuiFullscreen::Initialize("fullscreenui/placeholder.png") || !LoadResources())
{
DestroyResources();
ImGuiFullscreen::Shutdown();
ImGuiFullscreen::Shutdown(true);
s_tried_to_initialize = true;
return false;
}
s_initialized = true;
s_current_main_window = MainWindowType::None;
s_current_pause_submenu = PauseSubMenu::None;
s_pause_menu_was_open = false;
s_was_paused_on_quick_menu_open = false;
s_about_window_open = false;
s_hotkey_list_cache = InputManager::GetHotkeyList();
GetMTGS().SetRunIdle(true);
@ -573,7 +568,9 @@ bool FullscreenUI::Initialize()
}
else
{
SwitchToLanding();
// only switch to landing if we weren't e.g. in settings
if (s_current_main_window == MainWindowType::None)
SwitchToLanding();
}
return true;
@ -708,7 +705,7 @@ void FullscreenUI::OpenPauseMenu()
return;
GetMTGS().RunOnGSThread([]() {
if (!Initialize() || s_current_main_window != MainWindowType::None)
if (!ImGuiManager::InitializeFullscreenUI() || s_current_main_window != MainWindowType::None)
return;
PauseForMenuOpen();
@ -739,23 +736,32 @@ void FullscreenUI::OpenPauseSubMenu(PauseSubMenu submenu)
QueueResetFocus();
}
void FullscreenUI::Shutdown()
void FullscreenUI::Shutdown(bool clear_state)
{
CancelAsyncOps();
CloseSaveStateSelector();
s_cover_image_map.clear();
s_game_list_sorted_entries = {};
s_game_list_directories_cache = {};
s_fullscreen_mode_list_cache = {};
s_graphics_adapter_list_cache = {};
if (clear_state)
{
CancelAsyncOps();
CloseSaveStateSelector();
s_cover_image_map.clear();
s_game_list_sorted_entries = {};
s_game_list_directories_cache = {};
s_fullscreen_mode_list_cache = {};
s_graphics_adapter_list_cache = {};
s_current_game_title = {};
s_current_game_subtitle = {};
s_current_game_serial = {};
s_current_game_path = {};
s_current_game_crc = 0;
s_current_main_window = MainWindowType::None;
s_current_pause_submenu = PauseSubMenu::None;
s_pause_menu_was_open = false;
s_was_paused_on_quick_menu_open = false;
s_about_window_open = false;
}
s_hotkey_list_cache = {};
s_current_game_title = {};
s_current_game_subtitle = {};
s_current_game_serial = {};
s_current_game_path = {};
s_current_game_crc = 0;
DestroyResources();
ImGuiFullscreen::Shutdown();
ImGuiFullscreen::Shutdown(clear_state);
s_initialized = false;
s_tried_to_initialize = false;
}
@ -5690,7 +5696,7 @@ void FullscreenUI::OpenAchievementsWindow()
return;
GetMTGS().RunOnGSThread([]() {
if (!Initialize())
if (!ImGuiManager::InitializeFullscreenUI())
return;
SwitchToAchievementsWindow();
@ -6080,7 +6086,7 @@ void FullscreenUI::OpenLeaderboardsWindow()
return;
GetMTGS().RunOnGSThread([]() {
if (!Initialize())
if (!ImGuiManager::InitializeFullscreenUI())
return;
SwitchToLeaderboardsWindow();

View File

@ -38,7 +38,7 @@ namespace FullscreenUI
void OpenAchievementsWindow();
void OpenLeaderboardsWindow();
void Shutdown();
void Shutdown(bool clear_state);
void Render();
void InvalidateCoverCache();

View File

@ -203,7 +203,7 @@ bool ImGuiFullscreen::Initialize(const char* placeholder_image_path)
return true;
}
void ImGuiFullscreen::Shutdown()
void ImGuiFullscreen::Shutdown(bool clear_state)
{
if (s_texture_load_thread.Joinable())
{
@ -223,25 +223,28 @@ void ImGuiFullscreen::Shutdown()
s_texture_cache.Clear();
s_notifications.clear();
s_background_progress_dialogs.clear();
CloseInputDialog();
CloseMessageDialog();
s_choice_dialog_open = false;
s_choice_dialog_checkable = false;
s_choice_dialog_title = {};
s_choice_dialog_options.clear();
s_choice_dialog_callback = {};
s_enum_choice_button_id = 0;
s_enum_choice_button_value = 0;
s_enum_choice_button_set = false;
s_file_selector_open = false;
s_file_selector_directory = false;
s_file_selector_title = {};
s_file_selector_callback = {};
s_file_selector_current_directory = {};
s_file_selector_filters.clear();
s_file_selector_items.clear();
if (clear_state)
{
s_notifications.clear();
s_background_progress_dialogs.clear();
CloseInputDialog();
CloseMessageDialog();
s_choice_dialog_open = false;
s_choice_dialog_checkable = false;
s_choice_dialog_title = {};
s_choice_dialog_options.clear();
s_choice_dialog_callback = {};
s_enum_choice_button_id = 0;
s_enum_choice_button_value = 0;
s_enum_choice_button_set = false;
s_file_selector_open = false;
s_file_selector_directory = false;
s_file_selector_title = {};
s_file_selector_callback = {};
s_file_selector_current_directory = {};
s_file_selector_filters.clear();
s_file_selector_items.clear();
}
}
const std::shared_ptr<HostDisplayTexture>& ImGuiFullscreen::GetPlaceholderTexture()

View File

@ -112,8 +112,8 @@ namespace ImGuiFullscreen
void SetFonts(ImFont* standard_font, ImFont* medium_font, ImFont* large_font);
bool UpdateLayoutScale();
/// Shuts down, clearing all state.
void Shutdown();
/// Shuts down, optionally clearing all state (including notifications).
void Shutdown(bool clear_state);
/// Texture cache.
const std::shared_ptr<HostDisplayTexture>& GetPlaceholderTexture();

View File

@ -85,6 +85,9 @@ static std::atomic_bool s_imgui_wants_text{false};
// mapping of host key -> imgui key
static std::unordered_map<u32, ImGuiKey> s_imgui_key_map;
// need to keep track of this, so we can reinitialize on renderer switch
static bool s_fullscreen_ui_was_initialized = false;
#endif
bool ImGuiManager::Initialize()
@ -116,7 +119,10 @@ bool ImGuiManager::Initialize()
SetStyle();
#ifdef PCSX2_CORE
const bool add_fullscreen_fonts = s_fullscreen_ui_was_initialized;
pxAssertRel(!FullscreenUI::IsInitialized(), "Fullscreen UI is not initialized on ImGui init");
#else
const bool add_fullscreen_fonts = false;
#endif
if (!g_host_display->CreateImGuiContext())
@ -128,7 +134,7 @@ bool ImGuiManager::Initialize()
return false;
}
if (!AddImGuiFonts(false) || !g_host_display->UpdateImGuiFontTexture())
if (!AddImGuiFonts(add_fullscreen_fonts) || !g_host_display->UpdateImGuiFontTexture())
{
pxFailRel("Failed to create ImGui font text");
g_host_display->DestroyImGuiContext();
@ -141,13 +147,33 @@ bool ImGuiManager::Initialize()
ImGui::GetIO().Fonts->ClearTexData();
NewFrame();
// reinitialize fsui if it was previously enabled
#ifdef PCSX2_CORE
if (add_fullscreen_fonts)
InitializeFullscreenUI();
#endif
return true;
}
void ImGuiManager::Shutdown()
bool ImGuiManager::InitializeFullscreenUI()
{
#ifdef PCSX2_CORE
FullscreenUI::Shutdown();
s_fullscreen_ui_was_initialized = FullscreenUI::Initialize();
return s_fullscreen_ui_was_initialized;
#else
return false;
#endif
}
void ImGuiManager::Shutdown(bool clear_state)
{
#ifdef PCSX2_CORE
FullscreenUI::Shutdown(clear_state);
ImGuiFullscreen::SetFonts(nullptr, nullptr, nullptr);
if (clear_state)
s_fullscreen_ui_was_initialized = false;
#endif
if (g_host_display)
@ -159,11 +185,9 @@ void ImGuiManager::Shutdown()
s_fixed_font = nullptr;
s_medium_font = nullptr;
s_large_font = nullptr;
#ifdef PCSX2_CORE
ImGuiFullscreen::SetFonts(nullptr, nullptr, nullptr);
#endif
UnloadFontData();
if (clear_state)
UnloadFontData();
}
void ImGuiManager::WindowResized()

View File

@ -25,8 +25,11 @@ namespace ImGuiManager
/// Initializes ImGui, creates fonts, etc.
bool Initialize();
/// Initializes fullscreen UI.
bool InitializeFullscreenUI();
/// Frees all ImGui resources.
void Shutdown();
void Shutdown(bool clear_state);
/// Updates internal state when the window is size.
void WindowResized();

View File

@ -127,7 +127,7 @@ void GSshutdown()
g_gs_device.reset();
}
Host::ReleaseHostDisplay();
Host::ReleaseHostDisplay(true);
#endif
#ifdef _WIN32
@ -156,7 +156,7 @@ void GSclose()
if (g_host_display)
g_host_display->SetGPUTimingEnabled(false);
Host::ReleaseHostDisplay();
Host::ReleaseHostDisplay(true);
}
static RenderAPI GetAPIForRenderer(GSRendererType renderer)
@ -319,13 +319,13 @@ bool GSreopen(bool recreate_display, const Pcsx2Config::GSOptions& old_config)
if (recreate_display)
{
Host::ReleaseHostDisplay();
if (!Host::AcquireHostDisplay(GetAPIForRenderer(GSConfig.Renderer)))
Host::ReleaseHostDisplay(false);
if (!Host::AcquireHostDisplay(GetAPIForRenderer(GSConfig.Renderer), false))
{
Console.Error("(GSreopen) Failed to reacquire host display");
// try to get the old one back
if (!Host::AcquireHostDisplay(GetAPIForRenderer(old_config.Renderer)))
if (!Host::AcquireHostDisplay(GetAPIForRenderer(old_config.Renderer), false))
{
pxFailRel("Failed to recreate old config host display");
return false;
@ -345,8 +345,8 @@ bool GSreopen(bool recreate_display, const Pcsx2Config::GSOptions& old_config)
// try the old config
if (recreate_display && GSConfig.Renderer != old_config.Renderer)
{
Host::ReleaseHostDisplay();
if (!Host::AcquireHostDisplay(GetAPIForRenderer(old_config.Renderer)))
Host::ReleaseHostDisplay(false);
if (!Host::AcquireHostDisplay(GetAPIForRenderer(old_config.Renderer), false))
{
pxFailRel("Failed to recreate old config host display (part 2)");
return false;
@ -380,7 +380,7 @@ bool GSopen(const Pcsx2Config::GSOptions& config, GSRendererType renderer, u8* b
GSConfig = config;
GSConfig.Renderer = renderer;
if (!Host::AcquireHostDisplay(GetAPIForRenderer(renderer)))
if (!Host::AcquireHostDisplay(GetAPIForRenderer(renderer), true))
{
Console.Error("Failed to acquire host display");
return false;
@ -388,7 +388,7 @@ bool GSopen(const Pcsx2Config::GSOptions& config, GSRendererType renderer, u8* b
if (!DoGSOpen(renderer, basemem))
{
Host::ReleaseHostDisplay();
Host::ReleaseHostDisplay(true);
return false;
}

View File

@ -173,10 +173,10 @@ extern std::unique_ptr<HostDisplay> g_host_display;
namespace Host
{
/// Creates the host display. This may create a new window. The API used depends on the current configuration.
bool AcquireHostDisplay(RenderAPI api);
bool AcquireHostDisplay(RenderAPI api, bool clear_state_on_fail);
/// Destroys the host display. This may close the display window.
void ReleaseHostDisplay();
void ReleaseHostDisplay(bool clear_state);
/// Returns the desired vsync mode, depending on the runtime environment.
VsyncMode GetEffectiveVSyncMode();

View File

@ -117,7 +117,7 @@ bool Host::ConfirmMessage(const std::string_view& title, const std::string_view&
return true;
}
bool Host::AcquireHostDisplay(RenderAPI api)
bool Host::AcquireHostDisplay(RenderAPI api, bool clear_state_on_fail)
{
sApp.OpenGsPanel();
@ -141,9 +141,9 @@ bool Host::AcquireHostDisplay(RenderAPI api)
return true;
}
void Host::ReleaseHostDisplay()
void Host::ReleaseHostDisplay(bool clear_state_on_fail)
{
ImGuiManager::Shutdown();
ImGuiManager::Shutdown(clear_state_on_fail);
if (g_host_display)
g_host_display.reset();