FullscreenUI: Deadlock fix and add reset confirm for HC enable

This commit is contained in:
Connor McLaughlin 2022-10-10 23:59:48 +10:00 committed by refractionpcsx2
parent e845c59229
commit da7f068d5d
1 changed files with 57 additions and 38 deletions

View File

@ -294,7 +294,7 @@ namespace FullscreenUI
static void DrawCreateMemoryCardWindow(); static void DrawCreateMemoryCardWindow();
static void DrawControllerSettingsPage(); static void DrawControllerSettingsPage();
static void DrawHotkeySettingsPage(); static void DrawHotkeySettingsPage();
static void DrawAchievementsSettingsPage(); static void DrawAchievementsSettingsPage(std::unique_lock<std::mutex>& settings_lock);
static void DrawFoldersSettingsPage(); static void DrawFoldersSettingsPage();
static void DrawAchievementsLoginWindow(); static void DrawAchievementsLoginWindow();
static void DrawAdvancedSettingsPage(); static void DrawAdvancedSettingsPage();
@ -2115,7 +2115,7 @@ void FullscreenUI::DrawSettingsWindow()
break; break;
case SettingsPage::Achievements: case SettingsPage::Achievements:
DrawAchievementsSettingsPage(); DrawAchievementsSettingsPage(lock);
break; break;
case SettingsPage::Folders: case SettingsPage::Folders:
@ -3486,7 +3486,7 @@ void FullscreenUI::DrawFoldersSettingsPage()
#ifndef ENABLE_ACHIEVEMENTS #ifndef ENABLE_ACHIEVEMENTS
void FullscreenUI::DrawAchievementsSettingsPage() void FullscreenUI::DrawAchievementsSettingsPage(std::unique_lock<std::mutex>& settings_lock)
{ {
BeginMenuButtons(); BeginMenuButtons();
ActiveButton(ICON_FA_BAN " This build was not compiled with Achievements support.", false, false, ActiveButton(ICON_FA_BAN " This build was not compiled with Achievements support.", false, false,
@ -5762,7 +5762,7 @@ void FullscreenUI::DrawLeaderboardsWindow()
s_open_leaderboard_id.reset(); s_open_leaderboard_id.reset();
} }
void FullscreenUI::DrawAchievementsSettingsPage() void FullscreenUI::DrawAchievementsSettingsPage(std::unique_lock<std::mutex>& settings_lock)
{ {
#ifdef ENABLE_RAINTEGRATION #ifdef ENABLE_RAINTEGRATION
if (Achievements::IsUsingRAIntegration()) if (Achievements::IsUsingRAIntegration())
@ -5775,16 +5775,14 @@ void FullscreenUI::DrawAchievementsSettingsPage()
} }
#endif #endif
const auto lock = Achievements::GetLock();
if (Achievements::IsActive())
Achievements::ProcessPendingHTTPRequestsFromGSThread();
SettingsInterface* bsi = GetEditingSettingsInterface(); SettingsInterface* bsi = GetEditingSettingsInterface();
bool check_challenge_state = false;
bool challenge_state_just_enabled = false;
BeginMenuButtons(); BeginMenuButtons();
MenuHeading("Settings"); MenuHeading("Settings");
DrawToggleSetting(bsi, ICON_FA_TROPHY " Enable Achievements", check_challenge_state = DrawToggleSetting(bsi, ICON_FA_TROPHY " Enable Achievements",
"When enabled and logged in, PCSX2 will scan for achievements on startup.", "Achievements", "Enabled", false); "When enabled and logged in, PCSX2 will scan for achievements on startup.", "Achievements", "Enabled", false);
const bool enabled = bsi->GetBoolValue("Achievements", "Enabled", false); const bool enabled = bsi->GetBoolValue("Achievements", "Enabled", false);
@ -5793,13 +5791,9 @@ void FullscreenUI::DrawAchievementsSettingsPage()
DrawToggleSetting(bsi, ICON_FA_USER_FRIENDS " Rich Presence", DrawToggleSetting(bsi, ICON_FA_USER_FRIENDS " Rich Presence",
"When enabled, rich presence information will be collected and sent to the server where supported.", "Achievements", "RichPresence", "When enabled, rich presence information will be collected and sent to the server where supported.", "Achievements", "RichPresence",
true, enabled); true, enabled);
if (DrawToggleSetting(bsi, ICON_FA_HARD_HAT " Hardcore Mode", check_challenge_state |= DrawToggleSetting(bsi, ICON_FA_HARD_HAT " Hardcore Mode",
"\"Challenge\" mode for achievements, including leaderboard tracking. Disables save state, cheats, and slowdown functions.", "\"Challenge\" mode for achievements, including leaderboard tracking. Disables save state, cheats, and slowdown functions.",
"Achievements", "ChallengeMode", false, enabled)) "Achievements", "ChallengeMode", false, enabled);
{
if (VMManager::HasValidVM() && bsi->GetBoolValue("Achievements", "ChallengeMode", false))
ShowToast(std::string(), "Hardcore mode will be enabled on next game restart.");
}
DrawToggleSetting(bsi, ICON_FA_LIST_OL " Leaderboards", "Enables tracking and submission of leaderboards in supported games.", DrawToggleSetting(bsi, ICON_FA_LIST_OL " Leaderboards", "Enables tracking and submission of leaderboards in supported games.",
"Achievements", "Leaderboards", true, enabled && challenge); "Achievements", "Leaderboards", true, enabled && challenge);
DrawToggleSetting(bsi, ICON_FA_HEADPHONES " Sound Effects", DrawToggleSetting(bsi, ICON_FA_HEADPHONES " Sound Effects",
@ -5815,35 +5809,58 @@ void FullscreenUI::DrawAchievementsSettingsPage()
"When enabled, PCSX2 will assume all achievements are locked and not send any unlock notifications to the server.", "Achievements", "When enabled, PCSX2 will assume all achievements are locked and not send any unlock notifications to the server.", "Achievements",
"TestMode", false, enabled); "TestMode", false, enabled);
MenuHeading("Account"); // Check for challenge mode just being enabled.
if (Achievements::IsLoggedIn()) if (check_challenge_state && enabled && bsi->GetBoolValue("Achievements", "ChallengeMode", false) && VMManager::HasValidVM())
{ {
ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_Text]); ImGuiFullscreen::OpenConfirmMessageDialog("Reset System",
ActiveButton(fmt::format(ICON_FA_USER " Username: {}", Achievements::GetUsername()).c_str(), false, false, "Hardcore mode will not be enabled until the system is reset. Do you want to reset the system now?", [](bool reset) {
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); if (!VMManager::HasValidVM())
return;
const u64 ts = StringUtil::FromChars<u64>(bsi->GetStringValue("Achievements", "LoginTimestamp", "0")).value_or(0); if (reset)
ActiveButton(fmt::format(ICON_FA_CLOCK " Login token generated on {}", TimeToPrintableString(static_cast<time_t>(ts))).c_str(), DoReset();
false, false, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); });
ImGui::PopStyleColor(); }
if (MenuButton(ICON_FA_KEY " Logout", "Logs out of RetroAchievements.")) // Potential deadlock here: when we enable achievements, CPU thread reads settings, releases lock, then there's a brief
// time when we can progress here and get the setting lock, by the time it goes to read the username out of settings,
// we've got it here, but can't get the achievements lock. So only hold one at once.
const u64 ts = StringUtil::FromChars<u64>(bsi->GetStringValue("Achievements", "LoginTimestamp", "0")).value_or(0);
settings_lock.unlock();
{
const auto achievements_lock = Achievements::GetLock();
if (Achievements::IsActive())
Achievements::ProcessPendingHTTPRequestsFromGSThread();
MenuHeading("Account");
if (Achievements::IsLoggedIn())
{ {
Host::RunOnCPUThread([]() { Achievements::Logout(); }); ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_Text]);
ActiveButton(fmt::format(ICON_FA_USER " Username: {}", Achievements::GetUsername()).c_str(), false, false,
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
ActiveButton(fmt::format(ICON_FA_CLOCK " Login token generated on {}", TimeToPrintableString(static_cast<time_t>(ts))).c_str(),
false, false, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
ImGui::PopStyleColor();
if (MenuButton(ICON_FA_KEY " Logout", "Logs out of RetroAchievements."))
{
Host::RunOnCPUThread([]() { Achievements::Logout(); });
}
} }
} else if (Achievements::IsActive())
else if (Achievements::IsActive()) {
{ ActiveButton(ICON_FA_USER " Not Logged In", false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
ActiveButton(ICON_FA_USER " Not Logged In", false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
if (MenuButton(ICON_FA_KEY " Login", "Logs in to RetroAchievements.")) if (MenuButton(ICON_FA_KEY " Login", "Logs in to RetroAchievements."))
ImGui::OpenPopup("Achievements Login"); ImGui::OpenPopup("Achievements Login");
DrawAchievementsLoginWindow(); DrawAchievementsLoginWindow();
} }
else else
{ {
ActiveButton(ICON_FA_USER " Achievements are disabled.", false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); ActiveButton(ICON_FA_USER " Achievements are disabled.", false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
}
} }
MenuHeading("Current Game"); MenuHeading("Current Game");
@ -5878,6 +5895,8 @@ void FullscreenUI::DrawAchievementsSettingsPage()
} }
EndMenuButtons(); EndMenuButtons();
settings_lock.lock();
} }
void FullscreenUI::DrawAchievementsLoginWindow() void FullscreenUI::DrawAchievementsLoginWindow()