FullscreenUI: Always initialize widgets

That way notifications etc can be used independently of FSUI.
pull/3589/head
Stenzek 1 week ago
parent 9cbcf78090
commit 8c25144abb
No known key found for this signature in database

@ -1317,11 +1317,6 @@ void Achievements::ClientLoadGameCallback(int result, const char* error_message,
s_state.has_achievements = has_achievements; s_state.has_achievements = has_achievements;
s_state.has_leaderboards = has_leaderboards; s_state.has_leaderboards = has_leaderboards;
s_state.has_rich_presence = rc_client_has_rich_presence(client); s_state.has_rich_presence = rc_client_has_rich_presence(client);
// ensure fullscreen UI is ready for notifications
if (display_summary)
GPUThread::RunOnThread(&FullscreenUI::Initialize);
s_state.game_icon_url = s_state.game_icon_url =
info->badge_url ? std::string(info->badge_url) : GetImageURL(info->badge_name, RC_IMAGE_TYPE_GAME); info->badge_url ? std::string(info->badge_url) : GetImageURL(info->badge_name, RC_IMAGE_TYPE_GAME);
s_state.game_icon = GetLocalImagePath(info->badge_name, RC_IMAGE_TYPE_GAME); s_state.game_icon = GetLocalImagePath(info->badge_name, RC_IMAGE_TYPE_GAME);
@ -1410,18 +1405,12 @@ void Achievements::DisplayAchievementSummary()
GPUThread::RunOnThread([title = s_state.game_title, summary = std::string(summary.view()), icon = s_state.game_icon, GPUThread::RunOnThread([title = s_state.game_title, summary = std::string(summary.view()), icon = s_state.game_icon,
time = IsHardcoreModeActive() ? ACHIEVEMENT_SUMMARY_NOTIFICATION_TIME_HC : time = IsHardcoreModeActive() ? ACHIEVEMENT_SUMMARY_NOTIFICATION_TIME_HC :
ACHIEVEMENT_SUMMARY_NOTIFICATION_TIME]() mutable { ACHIEVEMENT_SUMMARY_NOTIFICATION_TIME]() mutable {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::AddNotification("AchievementsSummary", time, std::move(title), std::move(summary), std::move(icon)); FullscreenUI::AddNotification("AchievementsSummary", time, std::move(title), std::move(summary), std::move(icon));
}); });
if (s_state.game_summary.num_unsupported_achievements > 0) if (s_state.game_summary.num_unsupported_achievements > 0)
{ {
GPUThread::RunOnThread([num_unsupported = s_state.game_summary.num_unsupported_achievements]() mutable { GPUThread::RunOnThread([num_unsupported = s_state.game_summary.num_unsupported_achievements]() mutable {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::AddNotification("UnsupportedAchievements", ACHIEVEMENT_SUMMARY_UNSUPPORTED_TIME, FullscreenUI::AddNotification("UnsupportedAchievements", ACHIEVEMENT_SUMMARY_UNSUPPORTED_TIME,
TRANSLATE_STR("Achievements", "Unsupported Achievements"), TRANSLATE_STR("Achievements", "Unsupported Achievements"),
TRANSLATE_PLURAL_STR("Achievements", TRANSLATE_PLURAL_STR("Achievements",
@ -1442,9 +1431,6 @@ void Achievements::DisplayHardcoreDeferredMessage()
if (g_settings.achievements_hardcore_mode && System::IsValid()) if (g_settings.achievements_hardcore_mode && System::IsValid())
{ {
GPUThread::RunOnThread([]() { GPUThread::RunOnThread([]() {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::ShowToast(std::string(), FullscreenUI::ShowToast(std::string(),
TRANSLATE_STR("Achievements", "Hardcore mode will be enabled on system reset."), TRANSLATE_STR("Achievements", "Hardcore mode will be enabled on system reset."),
Host::OSD_WARNING_DURATION); Host::OSD_WARNING_DURATION);
@ -1478,9 +1464,6 @@ void Achievements::HandleUnlockEvent(const rc_client_event_t* event)
GPUThread::RunOnThread([id = cheevo->id, duration = g_settings.achievements_notification_duration, GPUThread::RunOnThread([id = cheevo->id, duration = g_settings.achievements_notification_duration,
title = std::move(title), description = std::string(cheevo->description), title = std::move(title), description = std::string(cheevo->description),
badge_path = std::move(badge_path)]() mutable { badge_path = std::move(badge_path)]() mutable {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::AddNotification(fmt::format("achievement_unlock_{}", id), static_cast<float>(duration), FullscreenUI::AddNotification(fmt::format("achievement_unlock_{}", id), static_cast<float>(duration),
std::move(title), std::move(description), std::move(badge_path)); std::move(title), std::move(description), std::move(badge_path));
}); });
@ -1505,9 +1488,6 @@ void Achievements::HandleGameCompleteEvent(const rc_client_event_t* event)
GPUThread::RunOnThread( GPUThread::RunOnThread(
[title = s_state.game_title, message = std::move(message), icon = s_state.game_icon]() mutable { [title = s_state.game_title, message = std::move(message), icon = s_state.game_icon]() mutable {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::AddNotification("achievement_mastery", GAME_COMPLETE_NOTIFICATION_TIME, std::move(title), FullscreenUI::AddNotification("achievement_mastery", GAME_COMPLETE_NOTIFICATION_TIME, std::move(title),
std::move(message), std::move(icon)); std::move(message), std::move(icon));
}); });
@ -1542,9 +1522,6 @@ void Achievements::HandleSubsetCompleteEvent(const rc_client_event_t* event)
GPUThread::RunOnThread( GPUThread::RunOnThread(
[title = std::move(title), message = std::move(message), badge_path = std::move(badge_path)]() mutable { [title = std::move(title), message = std::move(message), badge_path = std::move(badge_path)]() mutable {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::AddNotification("achievement_mastery", GAME_COMPLETE_NOTIFICATION_TIME, std::move(title), FullscreenUI::AddNotification("achievement_mastery", GAME_COMPLETE_NOTIFICATION_TIME, std::move(title),
std::move(message), std::move(badge_path)); std::move(message), std::move(badge_path));
}); });
@ -1562,9 +1539,6 @@ void Achievements::HandleLeaderboardStartedEvent(const rc_client_event_t* event)
GPUThread::RunOnThread([id = event->leaderboard->id, title = std::move(title), message = std::move(message), GPUThread::RunOnThread([id = event->leaderboard->id, title = std::move(title), message = std::move(message),
icon = s_state.game_icon]() mutable { icon = s_state.game_icon]() mutable {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::AddNotification(fmt::format("leaderboard_{}", id), LEADERBOARD_STARTED_NOTIFICATION_TIME, FullscreenUI::AddNotification(fmt::format("leaderboard_{}", id), LEADERBOARD_STARTED_NOTIFICATION_TIME,
std::move(title), std::move(message), std::move(icon)); std::move(title), std::move(message), std::move(icon));
}); });
@ -1582,9 +1556,6 @@ void Achievements::HandleLeaderboardFailedEvent(const rc_client_event_t* event)
GPUThread::RunOnThread([id = event->leaderboard->id, title = std::move(title), message = std::move(message), GPUThread::RunOnThread([id = event->leaderboard->id, title = std::move(title), message = std::move(message),
icon = s_state.game_icon]() mutable { icon = s_state.game_icon]() mutable {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::AddNotification(fmt::format("leaderboard_{}", id), LEADERBOARD_FAILED_NOTIFICATION_TIME, FullscreenUI::AddNotification(fmt::format("leaderboard_{}", id), LEADERBOARD_FAILED_NOTIFICATION_TIME,
std::move(title), std::move(message), std::move(icon)); std::move(title), std::move(message), std::move(icon));
}); });
@ -1613,8 +1584,6 @@ void Achievements::HandleLeaderboardSubmittedEvent(const rc_client_event_t* even
GPUThread::RunOnThread([id = event->leaderboard->id, title = std::move(title), message = std::move(message), GPUThread::RunOnThread([id = event->leaderboard->id, title = std::move(title), message = std::move(message),
icon = s_state.game_icon]() mutable { icon = s_state.game_icon]() mutable {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::AddNotification(fmt::format("leaderboard_{}", id), FullscreenUI::AddNotification(fmt::format("leaderboard_{}", id),
static_cast<float>(g_settings.achievements_leaderboard_duration), std::move(title), static_cast<float>(g_settings.achievements_leaderboard_duration), std::move(title),
std::move(message), std::move(icon)); std::move(message), std::move(icon));
@ -1649,9 +1618,6 @@ void Achievements::HandleLeaderboardScoreboardEvent(const rc_client_event_t* eve
GPUThread::RunOnThread([id = event->leaderboard->id, title = std::move(title), message = std::move(message), GPUThread::RunOnThread([id = event->leaderboard->id, title = std::move(title), message = std::move(message),
icon = s_state.game_icon]() mutable { icon = s_state.game_icon]() mutable {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::AddNotification(fmt::format("leaderboard_{}", id), FullscreenUI::AddNotification(fmt::format("leaderboard_{}", id),
static_cast<float>(g_settings.achievements_leaderboard_duration), std::move(title), static_cast<float>(g_settings.achievements_leaderboard_duration), std::move(title),
std::move(message), std::move(icon)); std::move(message), std::move(icon));
@ -1734,9 +1700,6 @@ void Achievements::HandleAchievementChallengeIndicatorShowEvent(const rc_client_
[title = std::move(title), [title = std::move(title),
description = std::string(event->achievement->description ? event->achievement->description : ""), badge_path, description = std::string(event->achievement->description ? event->achievement->description : ""), badge_path,
id = event->achievement->id]() mutable { id = event->achievement->id]() mutable {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::AddNotification(fmt::format("AchievementChallenge{}", id), CHALLENGE_STARTED_NOTIFICATION_TIME, FullscreenUI::AddNotification(fmt::format("AchievementChallenge{}", id), CHALLENGE_STARTED_NOTIFICATION_TIME,
std::move(title), std::move(description), std::move(badge_path)); std::move(title), std::move(description), std::move(badge_path));
}); });
@ -1772,9 +1735,6 @@ void Achievements::HandleAchievementChallengeIndicatorHideEvent(const rc_client_
[title = std::move(title), [title = std::move(title),
description = std::string(event->achievement->description ? event->achievement->description : ""), description = std::string(event->achievement->description ? event->achievement->description : ""),
badge_path = std::move(badge_path), id = event->achievement->id]() mutable { badge_path = std::move(badge_path), id = event->achievement->id]() mutable {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::AddNotification(fmt::format("AchievementChallenge{}", id), CHALLENGE_FAILED_NOTIFICATION_TIME, FullscreenUI::AddNotification(fmt::format("AchievementChallenge{}", id), CHALLENGE_FAILED_NOTIFICATION_TIME,
std::move(title), std::move(description), std::move(badge_path)); std::move(title), std::move(description), std::move(badge_path));
}); });
@ -1851,9 +1811,6 @@ void Achievements::HandleServerDisconnectedEvent(const rc_client_event_t* event)
WARNING_LOG("Server disconnected."); WARNING_LOG("Server disconnected.");
GPUThread::RunOnThread([]() { GPUThread::RunOnThread([]() {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::ShowToast( FullscreenUI::ShowToast(
TRANSLATE_STR("Achievements", "Achievements Disconnected"), TRANSLATE_STR("Achievements", "Achievements Disconnected"),
TRANSLATE_STR("Achievements", TRANSLATE_STR("Achievements",
@ -1867,9 +1824,6 @@ void Achievements::HandleServerReconnectedEvent(const rc_client_event_t* event)
WARNING_LOG("Server reconnected."); WARNING_LOG("Server reconnected.");
GPUThread::RunOnThread([]() { GPUThread::RunOnThread([]() {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::ShowToast(TRANSLATE_STR("Achievements", "Achievements Reconnected"), FullscreenUI::ShowToast(TRANSLATE_STR("Achievements", "Achievements Reconnected"),
TRANSLATE_STR("Achievements", "All pending unlock requests have completed."), TRANSLATE_STR("Achievements", "All pending unlock requests have completed."),
Host::OSD_INFO_DURATION); Host::OSD_INFO_DURATION);
@ -1906,9 +1860,6 @@ void Achievements::OnHardcoreModeChanged(bool enabled, bool display_message, boo
if (System::IsValid() && display_message) if (System::IsValid() && display_message)
{ {
GPUThread::RunOnThread([enabled]() { GPUThread::RunOnThread([enabled]() {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::ShowToast(std::string(), FullscreenUI::ShowToast(std::string(),
enabled ? TRANSLATE_STR("Achievements", "Hardcore mode is now enabled.") : enabled ? TRANSLATE_STR("Achievements", "Hardcore mode is now enabled.") :
TRANSLATE_STR("Achievements", "Hardcore mode is now disabled."), TRANSLATE_STR("Achievements", "Hardcore mode is now disabled."),
@ -2202,7 +2153,8 @@ void Achievements::ClientLoginWithTokenCallback(int result, const char* error_me
TRANSLATE_FS("Achievements", "Achievement unlocks will not be submitted for this session.\nError: {}"), TRANSLATE_FS("Achievements", "Achievement unlocks will not be submitted for this session.\nError: {}"),
error_message); error_message);
GPUThread::RunOnThread([message = std::move(message)]() mutable { GPUThread::RunOnThread([message = std::move(message)]() mutable {
if (!GPUThread::HasGPUBackend() || !FullscreenUI::Initialize()) // Only display this notification if we're booting a game.
if (!GPUThread::HasGPUBackend())
return; return;
FullscreenUI::AddNotification("AchievementsLoginFailed", Host::OSD_ERROR_DURATION, FullscreenUI::AddNotification("AchievementsLoginFailed", Host::OSD_ERROR_DURATION,
@ -2252,9 +2204,6 @@ void Achievements::ShowLoginNotification()
GPUThread::RunOnThread( GPUThread::RunOnThread(
[title = std::move(title), summary = std::move(summary), badge_path = std::move(badge_path)]() mutable { [title = std::move(title), summary = std::move(summary), badge_path = std::move(badge_path)]() mutable {
if (!FullscreenUI::Initialize())
return;
FullscreenUI::AddNotification("achievements_login", LOGIN_NOTIFICATION_TIME, std::move(title), FullscreenUI::AddNotification("achievements_login", LOGIN_NOTIFICATION_TIME, std::move(title),
std::move(summary), std::move(badge_path)); std::move(summary), std::move(badge_path));
}); });

@ -393,7 +393,6 @@ struct ALIGN_TO_CACHE_LINE WidgetsState
PauseSubMenu current_pause_submenu = PauseSubMenu::None; PauseSubMenu current_pause_submenu = PauseSubMenu::None;
MainWindowType previous_main_window = MainWindowType::None; MainWindowType previous_main_window = MainWindowType::None;
bool initialized = false; bool initialized = false;
bool tried_to_initialize = false;
bool pause_menu_was_open = false; bool pause_menu_was_open = false;
bool was_paused_on_quick_menu_open = false; bool was_paused_on_quick_menu_open = false;
std::string achievements_user_badge_path; std::string achievements_user_badge_path;
@ -464,20 +463,11 @@ static WidgetsState s_state;
// Main // Main
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
bool FullscreenUI::Initialize() void FullscreenUI::Initialize()
{ {
if (s_state.initialized)
return true;
// some achievement callbacks fire early while e.g. there is a load state popup blocking system init // some achievement callbacks fire early while e.g. there is a load state popup blocking system init
if (s_state.tried_to_initialize || !ImGuiManager::IsInitialized()) if (s_state.initialized || !ImGuiManager::IsInitialized())
return false; return;
if (!InitializeWidgets())
{
s_state.tried_to_initialize = true;
return false;
}
s_state.initialized = true; s_state.initialized = true;
s_state.show_localized_titles = Host::GetBaseBoolSettingValue("Main", "FullscreenUIShowLocalizedTitles", true); s_state.show_localized_titles = Host::GetBaseBoolSettingValue("Main", "FullscreenUIShowLocalizedTitles", true);
@ -496,8 +486,6 @@ bool FullscreenUI::Initialize()
{ {
UpdateRunIdleState(); UpdateRunIdleState();
} }
return true;
} }
bool FullscreenUI::IsInitialized() bool FullscreenUI::IsInitialized()
@ -611,7 +599,8 @@ void FullscreenUI::OpenPauseMenu()
return; return;
GPUThread::RunOnThread([]() { GPUThread::RunOnThread([]() {
if (!Initialize() || s_state.current_main_window != MainWindowType::None) Initialize();
if (s_state.current_main_window != MainWindowType::None)
return; return;
PauseForMenuOpen(true); PauseForMenuOpen(true);
@ -631,7 +620,8 @@ void FullscreenUI::OpenCheatsMenu()
return; return;
GPUThread::RunOnThread([]() { GPUThread::RunOnThread([]() {
if (!Initialize() || s_state.current_main_window != MainWindowType::None) Initialize();
if (s_state.current_main_window != MainWindowType::None)
return; return;
PauseForMenuOpen(false); PauseForMenuOpen(false);
@ -798,10 +788,8 @@ void FullscreenUI::Shutdown(bool clear_state)
} }
DestroyResources(); DestroyResources();
ShutdownWidgets(clear_state);
s_state.initialized = false; s_state.initialized = false;
s_state.tried_to_initialize = false;
UpdateRunIdleState(); UpdateRunIdleState();
} }
@ -1252,8 +1240,7 @@ void FullscreenUI::BeginChangeDiscOnCPUThread(bool needs_pause)
options.emplace_back(System::GetMediaSubImageTitle(i), i == current_index); options.emplace_back(System::GetMediaSubImageTitle(i), i == current_index);
GPUThread::RunOnThread([options = std::move(options), pause_if_needed = std::move(pause_if_needed)]() mutable { GPUThread::RunOnThread([options = std::move(options), pause_if_needed = std::move(pause_if_needed)]() mutable {
if (!Initialize()) Initialize();
return;
auto callback = [](s32 index, const std::string& title, bool checked) { auto callback = [](s32 index, const std::string& title, bool checked) {
if (index == 0) if (index == 0)
@ -1304,8 +1291,7 @@ void FullscreenUI::BeginChangeDiscOnCPUThread(bool needs_pause)
GPUThread::RunOnThread([options = std::move(options), paths = std::move(paths), GPUThread::RunOnThread([options = std::move(options), paths = std::move(paths),
pause_if_needed = std::move(pause_if_needed)]() mutable { pause_if_needed = std::move(pause_if_needed)]() mutable {
if (!Initialize()) Initialize();
return;
auto callback = [paths = std::move(paths)](s32 index, const std::string& title, bool checked) mutable { auto callback = [paths = std::move(paths)](s32 index, const std::string& title, bool checked) mutable {
if (index == 0) if (index == 0)
@ -1337,9 +1323,7 @@ void FullscreenUI::BeginChangeDiscOnCPUThread(bool needs_pause)
} }
GPUThread::RunOnThread([pause_if_needed = std::move(pause_if_needed)]() { GPUThread::RunOnThread([pause_if_needed = std::move(pause_if_needed)]() {
if (!Initialize()) Initialize();
return;
StartChangeDiscFromFile(); StartChangeDiscFromFile();
pause_if_needed(); pause_if_needed();
}); });
@ -8721,9 +8705,6 @@ void FullscreenUI::OpenAchievementsWindow()
if (!Achievements::IsActive() || !Achievements::HasAchievements()) if (!Achievements::IsActive() || !Achievements::HasAchievements())
{ {
GPUThread::RunOnThread([]() { GPUThread::RunOnThread([]() {
if (!Initialize())
return;
ShowToast(std::string(), Achievements::IsActive() ? FSUI_STR("This game has no achievements.") : ShowToast(std::string(), Achievements::IsActive() ? FSUI_STR("This game has no achievements.") :
FSUI_STR("Achievements are not enabled.")); FSUI_STR("Achievements are not enabled."));
}); });
@ -8731,8 +8712,7 @@ void FullscreenUI::OpenAchievementsWindow()
} }
GPUThread::RunOnThread([]() { GPUThread::RunOnThread([]() {
if (!Initialize()) Initialize();
return;
PauseForMenuOpen(false); PauseForMenuOpen(false);
ForceKeyNavEnabled(); ForceKeyNavEnabled();
@ -8761,9 +8741,6 @@ void FullscreenUI::OpenLeaderboardsWindow()
if (!Achievements::IsActive() || !Achievements::HasLeaderboards()) if (!Achievements::IsActive() || !Achievements::HasLeaderboards())
{ {
GPUThread::RunOnThread([]() { GPUThread::RunOnThread([]() {
if (!Initialize())
return;
ShowToast(std::string(), Achievements::IsActive() ? FSUI_STR("This game has no leaderboards.") : ShowToast(std::string(), Achievements::IsActive() ? FSUI_STR("This game has no leaderboards.") :
FSUI_STR("Achievements are not enabled.")); FSUI_STR("Achievements are not enabled."));
}); });
@ -8771,8 +8748,7 @@ void FullscreenUI::OpenLeaderboardsWindow()
} }
GPUThread::RunOnThread([]() { GPUThread::RunOnThread([]() {
if (!Initialize()) Initialize();
return;
PauseForMenuOpen(false); PauseForMenuOpen(false);
ForceKeyNavEnabled(); ForceKeyNavEnabled();

@ -19,7 +19,7 @@ class SmallStringBase;
struct GPUSettings; struct GPUSettings;
namespace FullscreenUI { namespace FullscreenUI {
bool Initialize(); void Initialize();
bool IsInitialized(); bool IsInitialized();
bool HasActiveWindow(); bool HasActiveWindow();
void CheckForConfigChanges(const GPUSettings& old_settings); void CheckForConfigChanges(const GPUSettings& old_settings);

@ -57,7 +57,7 @@ static constexpr u32 LOADING_PROGRESS_SAMPLE_COUNT = 30;
static std::optional<Image> LoadTextureImage(std::string_view path, u32 svg_width, u32 svg_height); static std::optional<Image> LoadTextureImage(std::string_view path, u32 svg_width, u32 svg_height);
static std::shared_ptr<GPUTexture> UploadTexture(std::string_view path, const Image& image); static std::shared_ptr<GPUTexture> UploadTexture(std::string_view path, const Image& image);
static bool CompileTransitionPipelines(); static bool CompileTransitionPipelines(Error* error);
static void CreateFooterTextString(SmallStringBase& dest, static void CreateFooterTextString(SmallStringBase& dest,
std::span<const std::pair<const char*, std::string_view>> items); std::span<const std::pair<const char*, std::string_view>> items);
@ -374,15 +374,16 @@ void FullscreenUI::SetFont(ImFont* ui_font)
UIStyle.Font = ui_font; UIStyle.Font = ui_font;
} }
bool FullscreenUI::InitializeWidgets() bool FullscreenUI::InitializeWidgets(Error* error)
{ {
std::unique_lock lock(s_state.shared_state_mutex); std::unique_lock lock(s_state.shared_state_mutex);
s_state.focus_reset_queued = FocusResetType::ViewChanged; s_state.focus_reset_queued = FocusResetType::ViewChanged;
s_state.close_button_state = CloseButtonState::None; s_state.close_button_state = CloseButtonState::None;
s_state.placeholder_texture = LoadTexture("images/placeholder.png"); if (!(s_state.placeholder_texture = LoadTexture("images/placeholder.png")))
if (!s_state.placeholder_texture || !CompileTransitionPipelines()) Error::SetStringView(error, "Failed to load placeholder.png");
if (!s_state.placeholder_texture || !CompileTransitionPipelines(error))
{ {
ShutdownWidgets(true); ShutdownWidgets(true);
return false; return false;
@ -741,20 +742,19 @@ GPUTexture* FullscreenUI::GetTransitionRenderTexture(GPUSwapChain* swap_chain)
return s_state.transition_current_texture.get(); return s_state.transition_current_texture.get();
} }
bool FullscreenUI::CompileTransitionPipelines() bool FullscreenUI::CompileTransitionPipelines(Error* error)
{ {
const RenderAPI render_api = g_gpu_device->GetRenderAPI(); const RenderAPI render_api = g_gpu_device->GetRenderAPI();
const ShaderGen shadergen(render_api, ShaderGen::GetShaderLanguageForAPI(render_api), false, false); const ShaderGen shadergen(render_api, ShaderGen::GetShaderLanguageForAPI(render_api), false, false);
GPUSwapChain* const swap_chain = g_gpu_device->GetMainSwapChain(); GPUSwapChain* const swap_chain = g_gpu_device->GetMainSwapChain();
Error error;
std::unique_ptr<GPUShader> vs = g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GetLanguage(), std::unique_ptr<GPUShader> vs = g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GetLanguage(),
shadergen.GeneratePassthroughVertexShader(), &error); shadergen.GeneratePassthroughVertexShader(), error);
std::unique_ptr<GPUShader> fs = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(), std::unique_ptr<GPUShader> fs = g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GetLanguage(),
shadergen.GenerateFadeFragmentShader(), &error); shadergen.GenerateFadeFragmentShader(), error);
if (!vs || !fs) if (!vs || !fs)
{ {
ERROR_LOG("Failed to compile transition shaders: {}", error.GetDescription()); Error::AddPrefix(error, "Failed to compile transition shaders: ");
return false; return false;
} }
GL_OBJECT_NAME(vs, "Transition Vertex Shader"); GL_OBJECT_NAME(vs, "Transition Vertex Shader");
@ -774,10 +774,10 @@ bool FullscreenUI::CompileTransitionPipelines()
plconfig.geometry_shader = nullptr; plconfig.geometry_shader = nullptr;
plconfig.fragment_shader = fs.get(); plconfig.fragment_shader = fs.get();
s_state.transition_blend_pipeline = g_gpu_device->CreatePipeline(plconfig, &error); s_state.transition_blend_pipeline = g_gpu_device->CreatePipeline(plconfig, error);
if (!s_state.transition_blend_pipeline) if (!s_state.transition_blend_pipeline)
{ {
ERROR_LOG("Failed to create transition blend pipeline: {}", error.GetDescription()); Error::AddPrefix(error, "Failed to create transition blend pipeline: ");
return false; return false;
} }
@ -4627,7 +4627,7 @@ void FullscreenUI::AddNotification(std::string key, float duration, std::string
notif.target_y = -1.0f; notif.target_y = -1.0f;
notif.last_y = -1.0f; notif.last_y = -1.0f;
s_state.notifications.push_back(std::move(notif)); s_state.notifications.push_back(std::move(notif));
FullscreenUI::UpdateRunIdleState(); UpdateRunIdleState();
} }
bool FullscreenUI::HasAnyNotifications() bool FullscreenUI::HasAnyNotifications()

@ -23,6 +23,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
class Error;
class Image; class Image;
class GPUTexture; class GPUTexture;
class GPUSwapChain; class GPUSwapChain;
@ -208,7 +209,7 @@ ImRect CenterImage(const ImRect& fit_rect, const GPUTexture* texture);
ImRect FitImage(const ImVec2& fit_size, const ImVec2& image_size); ImRect FitImage(const ImVec2& fit_size, const ImVec2& image_size);
/// Initializes, setting up any state. /// Initializes, setting up any state.
bool InitializeWidgets(); bool InitializeWidgets(Error* error);
/// Shuts down, clearing all state. /// Shuts down, clearing all state.
void ShutdownWidgets(bool clear_state); void ShutdownWidgets(bool clear_state);

@ -1087,8 +1087,7 @@ bool GPUPresenter::PresentFrame(GPUPresenter* presenter, GPUBackend* backend, bo
ImGuiManager::RenderOSDMessages(); ImGuiManager::RenderOSDMessages();
if (FullscreenUI::IsInitialized()) FullscreenUI::RenderOverlays();
FullscreenUI::RenderOverlays();
if (backend && !GPUThread::IsSystemPaused()) if (backend && !GPUThread::IsSystemPaused())
ImGuiManager::RenderSoftwareCursors(); ImGuiManager::RenderSoftwareCursors();

@ -696,13 +696,11 @@ bool GPUThread::CreateDeviceOnThread(RenderAPI api, bool fullscreen, bool clear_
} }
if (!ImGuiManager::Initialize(g_gpu_settings.display_osd_scale / 100.0f, g_gpu_settings.display_osd_margin, if (!ImGuiManager::Initialize(g_gpu_settings.display_osd_scale / 100.0f, g_gpu_settings.display_osd_margin,
&create_error) || &create_error))
(s_state.requested_fullscreen_ui && !FullscreenUI::Initialize()))
{ {
ERROR_LOG("Failed to initialize ImGuiManager: {}", create_error.GetDescription()); ERROR_LOG("Failed to initialize ImGuiManager: {}", create_error.GetDescription());
Error::SetStringFmt(error, "Failed to initialize ImGuiManager: {}", create_error.GetDescription()); Error::SetStringFmt(error, "Failed to initialize ImGuiManager: {}", create_error.GetDescription());
FullscreenUI::Shutdown(clear_fsui_state_on_failure); ImGuiManager::Shutdown(clear_fsui_state_on_failure);
ImGuiManager::Shutdown();
g_gpu_device->Destroy(); g_gpu_device->Destroy();
g_gpu_device.reset(); g_gpu_device.reset();
if (wi.has_value()) if (wi.has_value())
@ -710,6 +708,9 @@ bool GPUThread::CreateDeviceOnThread(RenderAPI api, bool fullscreen, bool clear_
return false; return false;
} }
if (s_state.requested_fullscreen_ui)
FullscreenUI::Initialize();
InputManager::SetDisplayWindowSize(ImGuiManager::GetWindowWidth(), ImGuiManager::GetWindowHeight()); InputManager::SetDisplayWindowSize(ImGuiManager::GetWindowWidth(), ImGuiManager::GetWindowHeight());
if (const GPUSwapChain* swap_chain = g_gpu_device->GetMainSwapChain()) if (const GPUSwapChain* swap_chain = g_gpu_device->GetMainSwapChain())
@ -736,7 +737,7 @@ void GPUThread::DestroyDeviceOnThread(bool clear_fsui_state)
Assert(!s_state.gpu_presenter); Assert(!s_state.gpu_presenter);
FullscreenUI::Shutdown(clear_fsui_state); FullscreenUI::Shutdown(clear_fsui_state);
ImGuiManager::Shutdown(); ImGuiManager::Shutdown(clear_fsui_state);
INFO_LOG("Destroying {} GPU device...", GPUDevice::RenderAPIToString(g_gpu_device->GetRenderAPI())); INFO_LOG("Destroying {} GPU device...", GPUDevice::RenderAPIToString(g_gpu_device->GetRenderAPI()));
g_gpu_device->Destroy(); g_gpu_device->Destroy();
@ -910,10 +911,9 @@ void GPUThread::ReconfigureOnThread(GPUThreadReconfigureCommand* cmd)
} }
else if (s_state.requested_fullscreen_ui) else if (s_state.requested_fullscreen_ui)
{ {
const bool had_gpu_device = static_cast<bool>(g_gpu_device); if (!(*cmd->out_result =
if (!g_gpu_device && !CreateDeviceOnThread(expected_api, cmd->fullscreen.value_or(false), true, cmd->error_ptr)) g_gpu_device || CreateDeviceOnThread(expected_api, cmd->fullscreen.value_or(false), true, cmd->error_ptr)))
{ {
*cmd->out_result = false;
return; return;
} }
@ -924,12 +924,8 @@ void GPUThread::ReconfigureOnThread(GPUThreadReconfigureCommand* cmd)
// Don't need timing to run FSUI. // Don't need timing to run FSUI.
g_gpu_device->SetGPUTimingEnabled(false); g_gpu_device->SetGPUTimingEnabled(false);
if (!(*cmd->out_result = FullscreenUI::IsInitialized() || FullscreenUI::Initialize())) // Ensure FSUI is initialized.
{ FullscreenUI::Initialize();
Error::SetStringView(cmd->error_ptr, "Failed to initialize FullscreenUI.");
if (!had_gpu_device)
DestroyDeviceOnThread(true);
}
} }
} }

@ -2151,12 +2151,6 @@ void Host::ConfirmMessageAsync(std::string_view title, std::string_view message,
callback(result); callback(result);
}; };
if (!FullscreenUI::Initialize())
{
final_callback(false);
return;
}
FullscreenUI::OpenConfirmMessageDialog(std::move(title), std::move(message), std::move(final_callback), FullscreenUI::OpenConfirmMessageDialog(std::move(title), std::move(message), std::move(final_callback),
fmt::format(ICON_FA_CHECK " {}", yes_text), fmt::format(ICON_FA_CHECK " {}", yes_text),
fmt::format(ICON_FA_XMARK " {}", no_text)); fmt::format(ICON_FA_XMARK " {}", no_text));

@ -225,7 +225,7 @@ bool ImGuiManager::Initialize(float global_scale, float screen_margin, Error* er
FullscreenUI::UpdateTheme(); FullscreenUI::UpdateTheme();
FullscreenUI::UpdateLayoutScale(); FullscreenUI::UpdateLayoutScale();
if (!CreateFontAtlas(error) || !CompilePipelines(error)) if (!CreateFontAtlas(error) || !CompilePipelines(error) || !FullscreenUI::InitializeWidgets(error))
return false; return false;
NewFrame(); NewFrame();
@ -234,10 +234,12 @@ bool ImGuiManager::Initialize(float global_scale, float screen_margin, Error* er
return true; return true;
} }
void ImGuiManager::Shutdown() void ImGuiManager::Shutdown(bool clear_fsui_state)
{ {
DestroySoftwareCursorTextures(); DestroySoftwareCursorTextures();
FullscreenUI::ShutdownWidgets(clear_fsui_state);
s_state.text_font = nullptr; s_state.text_font = nullptr;
s_state.fixed_font = nullptr; s_state.fixed_font = nullptr;
FullscreenUI::SetFont(nullptr); FullscreenUI::SetFont(nullptr);

@ -87,7 +87,7 @@ void SetGlobalScale(float global_scale);
bool Initialize(float global_scale, float screen_margin, Error* error); bool Initialize(float global_scale, float screen_margin, Error* error);
/// Frees all ImGui resources. /// Frees all ImGui resources.
void Shutdown(); void Shutdown(bool clear_fsui_state);
/// Returns main ImGui context. /// Returns main ImGui context.
ImGuiContext* GetMainContext(); ImGuiContext* GetMainContext();

Loading…
Cancel
Save