From 584525cb11b33b32b78dd837f8cd1d99204654ec Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 26 Mar 2022 23:51:37 +1000 Subject: [PATCH] Cheevos: Move to core --- src/core/CMakeLists.txt | 9 +++ src/{frontend-common => core}/cheevos.cpp | 79 +++++++++---------- src/{frontend-common => core}/cheevos.h | 0 src/core/core.props | 5 +- src/core/core.vcxproj | 2 + src/core/core.vcxproj.filters | 2 + src/core/host_interface.h | 8 ++ src/core/imgui_fullscreen.cpp | 71 +++++++++++++++-- src/core/imgui_fullscreen.h | 22 +++++- src/duckstation-qt/achievementlogindialog.cpp | 2 +- .../achievementsettingswidget.cpp | 2 +- src/duckstation-qt/qthostinterface.cpp | 2 +- src/frontend-common/CMakeLists.txt | 9 --- src/frontend-common/common_host_interface.cpp | 14 +++- src/frontend-common/common_host_interface.h | 9 +-- src/frontend-common/frontend-common.props | 5 +- src/frontend-common/frontend-common.vcxproj | 2 - .../frontend-common.vcxproj.filters | 2 - src/frontend-common/fullscreen_ui.cpp | 49 ++++-------- src/frontend-common/fullscreen_ui.h | 1 - 20 files changed, 181 insertions(+), 114 deletions(-) rename src/{frontend-common => core}/cheevos.cpp (93%) rename src/{frontend-common => core}/cheevos.h (100%) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index fd61505e8..019e0ab6e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -157,3 +157,12 @@ elseif(${CPU_ARCH} STREQUAL "aarch64") else() message("Not building recompiler") endif() + +if(ENABLE_CHEEVOS) + target_sources(core PRIVATE + cheevos.cpp + cheevos.h + ) + target_compile_definitions(core PUBLIC -DWITH_CHEEVOS=1) + target_link_libraries(core PRIVATE rcheevos rapidjson) +endif() diff --git a/src/frontend-common/cheevos.cpp b/src/core/cheevos.cpp similarity index 93% rename from src/frontend-common/cheevos.cpp rename to src/core/cheevos.cpp index e53a007e4..7f9b93f5b 100644 --- a/src/frontend-common/cheevos.cpp +++ b/src/core/cheevos.cpp @@ -1,4 +1,5 @@ #include "cheevos.h" +#include "common/assert.h" #include "common/cd_image.h" #include "common/file_system.h" #include "common/http_downloader.h" @@ -7,14 +8,13 @@ #include "common/platform.h" #include "common/string_util.h" #include "common/timestamp.h" -#include "common_host_interface.h" #include "core/bios.h" #include "core/bus.h" #include "core/cpu_core.h" #include "core/host_display.h" -#include "core/imgui_fullscreen.h" #include "core/system.h" -#include "fullscreen_ui.h" +#include "host_interface.h" +#include "imgui_fullscreen.h" #include "rapidjson/document.h" #include "rc_url.h" #include "rcheevos.h" @@ -86,11 +86,6 @@ static u32 s_total_image_downloads; static u32 s_completed_image_downloads; static bool s_image_download_progress_active; -static ALWAYS_INLINE CommonHostInterface* GetHostInterface() -{ - return static_cast(g_host_interface); -} - static void FormattedError(const char* format, ...) printflike(1, 2); static void FormattedError(const char* format, ...) { @@ -103,7 +98,7 @@ static void FormattedError(const char* format, ...) va_end(ap); - GetHostInterface()->AddOSDMessage(str.GetCharArray(), 10.0f); + g_host_interface->AddOSDMessage(str.GetCharArray(), 10.0f); Log_ErrorPrint(str.GetCharArray()); } @@ -222,7 +217,7 @@ static void ClearGameInfo(bool clear_achievements = true, bool clear_leaderboard } if (had_game) - GetHostInterface()->OnAchievementsRefreshed(); + g_host_interface->OnAchievementsRefreshed(); } static void ClearGamePath() @@ -255,8 +250,8 @@ bool Initialize(bool test_mode, bool use_first_disc_from_playlist, bool enable_r rc_runtime_init(&s_rcheevos_runtime); s_last_ping_time.Reset(); - s_username = GetHostInterface()->GetStringSettingValue("Cheevos", "Username"); - s_login_token = GetHostInterface()->GetStringSettingValue("Cheevos", "Token"); + s_username = g_host_interface->GetStringSettingValue("Cheevos", "Username"); + s_login_token = g_host_interface->GetStringSettingValue("Cheevos", "Token"); s_logged_in = (!s_username.empty() && !s_login_token.empty()); if (IsLoggedIn() && System::IsValid()) @@ -288,7 +283,7 @@ void Shutdown() std::string().swap(s_username); std::string().swap(s_login_token); s_logged_in = false; - GetHostInterface()->OnAchievementsRefreshed(); + g_host_interface->OnAchievementsRefreshed(); g_active = false; rc_runtime_destroy(&s_rcheevos_runtime); @@ -367,12 +362,12 @@ static void LoginCallback(s32 status_code, const FrontendCommon::HTTPDownloader: // save to config { - std::lock_guard guard(GetHostInterface()->GetSettingsLock()); - GetHostInterface()->GetSettingsInterface()->SetStringValue("Cheevos", "Username", username.c_str()); - GetHostInterface()->GetSettingsInterface()->SetStringValue("Cheevos", "Token", login_token.c_str()); - GetHostInterface()->GetSettingsInterface()->SetStringValue( + std::lock_guard guard(g_host_interface->GetSettingsLock()); + g_host_interface->GetSettingsInterface()->SetStringValue("Cheevos", "Username", username.c_str()); + g_host_interface->GetSettingsInterface()->SetStringValue("Cheevos", "Token", login_token.c_str()); + g_host_interface->GetSettingsInterface()->SetStringValue( "Cheevos", "LoginTimestamp", TinyString::FromFormat("%" PRIu64, Timestamp::Now().AsUnixTimestamp())); - GetHostInterface()->GetSettingsInterface()->Save(); + g_host_interface->GetSettingsInterface()->Save(); } if (g_active) @@ -389,7 +384,7 @@ static void LoginCallback(s32 status_code, const FrontendCommon::HTTPDownloader: static void LoginASyncCallback(s32 status_code, const FrontendCommon::HTTPDownloader::Request::Data& data) { - if (GetHostInterface()->IsFullscreenUIEnabled()) + if (ImGuiFullscreen::IsInitialized()) ImGuiFullscreen::CloseBackgroundProgressDialog("cheevos_async_login"); LoginCallback(status_code, data); @@ -412,10 +407,10 @@ bool LoginAsync(const char* username, const char* password) if (s_logged_in || std::strlen(username) == 0 || std::strlen(password) == 0) return false; - if (GetHostInterface()->IsFullscreenUIEnabled()) + if (ImGuiFullscreen::IsInitialized()) { ImGuiFullscreen::OpenBackgroundProgressDialog( - "cheevos_async_login", GetHostInterface()->TranslateStdString("Cheevos", "Logging in to RetroAchivements..."), 0, + "cheevos_async_login", g_host_interface->TranslateStdString("Cheevos", "Logging in to RetroAchivements..."), 0, 1, 0); } @@ -448,7 +443,7 @@ bool Login(const char* username, const char* password) SendLogin(username, password, http_downloader.get(), LoginCallback); http_downloader->WaitForAllRequests(); - return !GetHostInterface()->GetStringSettingValue("Cheevos", "Token").empty(); + return !g_host_interface->GetStringSettingValue("Cheevos", "Token").empty(); } void Logout() @@ -462,17 +457,17 @@ void Logout() std::string().swap(s_username); std::string().swap(s_login_token); s_logged_in = false; - GetHostInterface()->OnAchievementsRefreshed(); + g_host_interface->OnAchievementsRefreshed(); } } // remove from config - std::lock_guard guard(GetHostInterface()->GetSettingsLock()); + std::lock_guard guard(g_host_interface->GetSettingsLock()); { - GetHostInterface()->GetSettingsInterface()->DeleteValue("Cheevos", "Username"); - GetHostInterface()->GetSettingsInterface()->DeleteValue("Cheevos", "Token"); - GetHostInterface()->GetSettingsInterface()->DeleteValue("Cheevos", "LoginTimestamp"); - GetHostInterface()->GetSettingsInterface()->Save(); + g_host_interface->GetSettingsInterface()->DeleteValue("Cheevos", "Username"); + g_host_interface->GetSettingsInterface()->DeleteValue("Cheevos", "Token"); + g_host_interface->GetSettingsInterface()->DeleteValue("Cheevos", "LoginTimestamp"); + g_host_interface->GetSettingsInterface()->Save(); } } @@ -494,7 +489,7 @@ static void UpdateImageDownloadProgress() return; } - if (!GetHostInterface()->IsFullscreenUIEnabled()) + if (!ImGuiFullscreen::IsInitialized()) return; std::string message(g_host_interface->TranslateStdString("Cheevos", "Downloading achievement resources...")); @@ -528,7 +523,7 @@ static void DownloadImage(std::string url, std::string cache_filename) return; } - FullscreenUI::InvalidateCachedTexture(cache_filename); + ImGuiFullscreen::InvalidateCachedTexture(cache_filename); UpdateImageDownloadProgress(); }; @@ -549,7 +544,7 @@ static std::string GetBadgeImageFilename(const char* badge_name, bool locked, bo // well, this comes from the internet.... :) SmallString clean_name(badge_name); FileSystem::SanitizeFileName(clean_name); - return GetHostInterface()->GetUserDirectoryRelativePath("cache" FS_OSPATH_SEPARATOR_STR + return g_host_interface->GetUserDirectoryRelativePath("cache" FS_OSPATH_SEPARATOR_STR "achievement_badge" FS_OSPATH_SEPARATOR_STR "%s%s.png", clean_name.GetCharArray(), locked ? "_lock" : ""); } @@ -575,30 +570,30 @@ static void DisplayAchievementSummary() { std::string title = s_game_title; if (g_challenge_mode) - title += GetHostInterface()->TranslateString("Cheevos", " (Hardcore Mode)"); + title += g_host_interface->TranslateString("Cheevos", " (Hardcore Mode)"); std::string summary; if (GetAchievementCount() > 0) { summary = StringUtil::StdStringFromFormat( - GetHostInterface()->TranslateString("Cheevos", "You have earned %u of %u achievements, and %u of %u points."), + g_host_interface->TranslateString("Cheevos", "You have earned %u of %u achievements, and %u of %u points."), GetUnlockedAchiementCount(), GetAchievementCount(), GetCurrentPointsForGame(), GetMaximumPointsForGame()); } else { - summary = GetHostInterface()->TranslateString("Cheevos", "This game has no achievements."); + summary = g_host_interface->TranslateString("Cheevos", "This game has no achievements."); } if (GetLeaderboardCount() > 0) { summary.push_back('\n'); if (g_challenge_mode) { - summary.append(GetHostInterface()->TranslateString("Cheevos", "Leaderboards are enabled.")); + summary.append(g_host_interface->TranslateString("Cheevos", "Leaderboards are enabled.")); } else { summary.append( - GetHostInterface()->TranslateString("Cheevos", "Leaderboards are DISABLED because Hardcore Mode is off.")); + g_host_interface->TranslateString("Cheevos", "Leaderboards are DISABLED because Hardcore Mode is off.")); } } @@ -649,7 +644,7 @@ static void GetUserUnlocksCallback(s32 status_code, const FrontendCommon::HTTPDo SendPlaying(); UpdateRichPresence(); SendPing(); - GetHostInterface()->OnAchievementsRefreshed(); + g_host_interface->OnAchievementsRefreshed(); } static void GetUserUnlocks() @@ -694,7 +689,7 @@ static void GetPatchesCallback(s32 status_code, const FrontendCommon::HTTPDownlo std::string icon_name(GetOptionalString(patch_data, "ImageIcon")); if (!icon_name.empty()) { - s_game_icon = GetHostInterface()->GetUserDirectoryRelativePath( + s_game_icon = g_host_interface->GetUserDirectoryRelativePath( "cache" FS_OSPATH_SEPARATOR_STR "achievement_gameicon" FS_OSPATH_SEPARATOR_STR "%u.png", g_game_id); if (!FileSystem::FileExists(s_game_icon.c_str())) { @@ -825,7 +820,7 @@ static void GetPatchesCallback(s32 status_code, const FrontendCommon::HTTPDownlo { ActivateLockedAchievements(); DisplayAchievementSummary(); - GetHostInterface()->OnAchievementsRefreshed(); + g_host_interface->OnAchievementsRefreshed(); } } else @@ -1024,7 +1019,7 @@ void GameChanged(const std::string& path, CDImage* image) if (s_game_hash.empty()) { - GetHostInterface()->AddOSDMessage(GetHostInterface()->TranslateStdString( + g_host_interface->AddOSDMessage(g_host_interface->TranslateStdString( "OSDMessage", "Failed to read executable from disc. Achievements disabled."), 10.0f); return; @@ -1070,7 +1065,7 @@ static void UpdateRichPresence() const bool had_rich_presence = !s_rich_presence_string.empty(); s_rich_presence_string.clear(); if (had_rich_presence) - GetHostInterface()->OnAchievementsRefreshed(); + g_host_interface->OnAchievementsRefreshed(); return; } @@ -1079,7 +1074,7 @@ static void UpdateRichPresence() return; s_rich_presence_string.assign(buffer); - GetHostInterface()->OnAchievementsRefreshed(); + g_host_interface->OnAchievementsRefreshed(); } static void SendPingCallback(s32 status_code, const FrontendCommon::HTTPDownloader::Request::Data& data) diff --git a/src/frontend-common/cheevos.h b/src/core/cheevos.h similarity index 100% rename from src/frontend-common/cheevos.h rename to src/core/cheevos.h diff --git a/src/core/core.props b/src/core/core.props index 8ea6c12a3..3b7962641 100644 --- a/src/core/core.props +++ b/src/core/core.props @@ -4,10 +4,11 @@ + WITH_CHEEVOS=1;%(PreprocessorDefinitions) WITH_RECOMPILER=1;%(PreprocessorDefinitions) WITH_MMAP_FASTMEM=1;%(PreprocessorDefinitions) - $(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) + $(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\rcheevos\include;$(SolutionDir)dep\rapidjson\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) $(SolutionDir)dep\xbyak\xbyak;%(AdditionalIncludeDirectories) $(SolutionDir)dep\vixl\include;%(AdditionalIncludeDirectories) @@ -16,7 +17,7 @@ - $(RootBuildDir)imgui\imgui.lib;$(RootBuildDir)stb\stb.lib;$(RootBuildDir)vulkan-loader\vulkan-loader.lib;$(RootBuildDir)xxhash\xxhash.lib;$(RootBuildDir)zlib\zlib.lib;$(RootBuildDir)common\common.lib;%(AdditionalDependencies) + $(RootBuildDir)rcheevos\rcheevos.lib;$(RootBuildDir)imgui\imgui.lib;$(RootBuildDir)stb\stb.lib;$(RootBuildDir)vulkan-loader\vulkan-loader.lib;$(RootBuildDir)xxhash\xxhash.lib;$(RootBuildDir)zlib\zlib.lib;$(RootBuildDir)common\common.lib;%(AdditionalDependencies) $(RootBuildDir)vixl\vixl.lib;%(AdditionalDependencies) diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index 8cc3cf525..33a6a4106 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -9,6 +9,7 @@ + @@ -82,6 +83,7 @@ + diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 08139a22c..d1a7fb20e 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -60,6 +60,7 @@ + @@ -124,5 +125,6 @@ + \ No newline at end of file diff --git a/src/core/host_interface.h b/src/core/host_interface.h index 361167319..fe40f7ffd 100644 --- a/src/core/host_interface.h +++ b/src/core/host_interface.h @@ -41,6 +41,7 @@ public: /// Access to host display. ALWAYS_INLINE HostDisplay* GetDisplay() const { return m_display.get(); } + ALWAYS_INLINE bool HasDisplay() const { return static_cast(m_display.get()); } /// Access to host audio stream. ALWAYS_INLINE AudioStream* GetAudioStream() const { return m_audio_stream.get(); } @@ -123,6 +124,10 @@ public: /// Returns a string list from the configuration. virtual std::vector GetSettingStringList(const char* section, const char* key) = 0; + /// Returns the settings interface. + virtual SettingsInterface* GetSettingsInterface() = 0; + virtual std::lock_guard GetSettingsLock() = 0; + /// Translates a string to the current language. virtual TinyString TranslateString(const char* context, const char* str, const char* disambiguation = nullptr, int n = -1) const; @@ -156,6 +161,9 @@ public: /// Called when the display is invalidated (e.g. a state is loaded). virtual void OnDisplayInvalidated() = 0; + /// Called when achievements data is loaded. + virtual void OnAchievementsRefreshed() = 0; + protected: virtual bool AcquireHostDisplay() = 0; virtual void ReleaseHostDisplay() = 0; diff --git a/src/core/imgui_fullscreen.cpp b/src/core/imgui_fullscreen.cpp index 26c7403ef..6f9f2a8d0 100644 --- a/src/core/imgui_fullscreen.cpp +++ b/src/core/imgui_fullscreen.cpp @@ -4,6 +4,7 @@ #include "IconsFontAwesome5.h" #include "common/assert.h" #include "common/easing.h" +#include "common/lru_cache.h" #include "common/file_system.h" #include "common/string.h" #include "common/string_util.h" @@ -21,6 +22,8 @@ static void DrawChoiceDialog(); static void DrawBackgroundProgressDialogs(ImVec2& position, float spacing); static void DrawNotifications(ImVec2& position, float spacing); +bool g_initialized = false; + ImFont* g_standard_font = nullptr; ImFont* g_medium_font = nullptr; ImFont* g_large_font = nullptr; @@ -37,10 +40,12 @@ static std::vector s_text_font_data; static std::vector s_icon_font_data; static float s_font_size = 15.0f; static const ImWchar* s_font_glyph_range = nullptr; -static ResolveTextureHandleCallback s_resolve_texture_handle = nullptr; +static LoadTextureFunction s_load_texture = nullptr; static u32 s_menu_button_index = 0; +static LRUCache> s_texture_cache; + void SetFontFilename(const char* filename) { if (filename) @@ -93,9 +98,26 @@ void SetMenuBarSize(float size) g_menu_bar_size = size; } -void SetResolveTextureFunction(ResolveTextureHandleCallback callback) +HostDisplayTexture* GetCachedTexture(const std::string& name) { - s_resolve_texture_handle = callback; + std::unique_ptr* tex_ptr = s_texture_cache.Lookup(name); + if (!tex_ptr) + { + std::unique_ptr tex = s_load_texture(name.c_str()); + tex_ptr = s_texture_cache.Insert(name, std::move(tex)); + } + + return tex_ptr->get(); +} + +bool InvalidateCachedTexture(const std::string& path) +{ + return s_texture_cache.Remove(path); +} + +void SetLoadTextureFunction(LoadTextureFunction callback) +{ + s_load_texture = callback; } static ImFont* AddTextFont(float size /*= 15.0f*/) @@ -977,6 +999,7 @@ static ImGuiID s_enum_choice_button_id = 0; static s32 s_enum_choice_button_value = 0; static bool s_enum_choice_button_set = false; + bool EnumChoiceButtonImpl(const char* title, const char* summary, s32* value_pointer, const char* (*to_display_name_function)(s32 value, void* opaque), void* opaque, u32 count, bool enabled, float height, ImFont* font, ImFont* summary_font) @@ -1747,11 +1770,11 @@ void DrawNotifications(ImVec2& position, float spacing) const ImVec2 badge_min(box_min.x + horizontal_padding, box_min.y + vertical_padding); const ImVec2 badge_max(badge_min.x + badge_size, badge_min.y + badge_size); - if (!notif.badge_path.empty() && s_resolve_texture_handle) + if (!notif.badge_path.empty()) { - ImTextureID tex = s_resolve_texture_handle(notif.badge_path); + HostDisplayTexture* tex = GetCachedTexture(notif.badge_path); if (tex) - dl->AddImage(tex, badge_min, badge_max); + dl->AddImage(static_cast(tex->GetHandle()), badge_min, badge_max); } const ImVec2 title_min(badge_max.x + horizontal_spacing, box_min.y + vertical_padding); @@ -1769,4 +1792,40 @@ void DrawNotifications(ImVec2& position, float spacing) } } +bool Initialize() +{ + s_texture_cache.SetMaxCapacity(128); + g_initialized = true; + return true; +} + +void Shutdown() +{ + g_standard_font = nullptr; + g_medium_font = nullptr; + g_large_font = nullptr; + + s_texture_cache.Clear(); + + s_notifications.clear(); + s_background_progress_dialogs.clear(); + 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(); + + g_initialized = false; +} + } // namespace ImGuiFullscreen \ No newline at end of file diff --git a/src/core/imgui_fullscreen.h b/src/core/imgui_fullscreen.h index c9c0ccbfb..d7b3b7e74 100644 --- a/src/core/imgui_fullscreen.h +++ b/src/core/imgui_fullscreen.h @@ -5,12 +5,14 @@ #include #include +class HostDisplayTexture; + namespace ImGuiFullscreen { #define HEX_TO_IMVEC4(hex, alpha) \ ImVec4(static_cast((hex >> 16) & 0xFFu) / 255.0f, static_cast((hex >> 8) & 0xFFu) / 255.0f, \ static_cast(hex & 0xFFu) / 255.0f, static_cast(alpha) / 255.0f) -using ResolveTextureHandleCallback = ImTextureID (*)(const std::string& path); +using LoadTextureFunction = std::unique_ptr(*)(const char* path); static constexpr float LAYOUT_SCREEN_WIDTH = 1280.0f; static constexpr float LAYOUT_SCREEN_HEIGHT = 720.0f; @@ -26,11 +28,17 @@ extern ImFont* g_standard_font; extern ImFont* g_medium_font; extern ImFont* g_large_font; +extern bool g_initialized; extern float g_layout_scale; extern float g_layout_padding_left; extern float g_layout_padding_top; extern float g_menu_bar_size; +static ALWAYS_INLINE bool IsInitialized() +{ + return g_initialized; +} + static ALWAYS_INLINE float DPIScale(float v) { return ImGui::GetIO().DisplayFramebufferScale.x * v; @@ -132,6 +140,12 @@ static ALWAYS_INLINE ImVec4 UISecondaryTextColor() return HEX_TO_IMVEC4(0xffffff, 0xff); } +/// Initializes, setting up any state. +bool Initialize(); + +/// Shuts down, clearing all state. +void Shutdown(); + void SetFontFilename(std::string filename); void SetFontData(std::vector data); void SetIconFontFilename(std::string icon_font_filename); @@ -142,8 +156,10 @@ void SetFontGlyphRanges(const ImWchar* glyph_ranges); /// Changes the menu bar size. Don't forget to call UpdateLayoutScale() and UpdateFonts(). void SetMenuBarSize(float size); -/// Resolves a texture name to a handle. -void SetResolveTextureFunction(ResolveTextureHandleCallback callback); +/// Texture cache. +HostDisplayTexture* GetCachedTexture(const std::string& name); +bool InvalidateCachedTexture(const std::string& path); +void SetLoadTextureFunction(LoadTextureFunction callback); /// Rebuilds fonts to a new scale if needed. Returns true if fonts have changed and the texture needs updating. bool UpdateFonts(); diff --git a/src/duckstation-qt/achievementlogindialog.cpp b/src/duckstation-qt/achievementlogindialog.cpp index 66b771447..612d7426d 100644 --- a/src/duckstation-qt/achievementlogindialog.cpp +++ b/src/duckstation-qt/achievementlogindialog.cpp @@ -1,5 +1,5 @@ #include "achievementlogindialog.h" -#include "frontend-common/cheevos.h" +#include "core/cheevos.h" #include "qthostinterface.h" #include diff --git a/src/duckstation-qt/achievementsettingswidget.cpp b/src/duckstation-qt/achievementsettingswidget.cpp index 9fa4dcf1f..a2eb80fba 100644 --- a/src/duckstation-qt/achievementsettingswidget.cpp +++ b/src/duckstation-qt/achievementsettingswidget.cpp @@ -1,8 +1,8 @@ #include "achievementsettingswidget.h" #include "achievementlogindialog.h" #include "common/string_util.h" +#include "core/cheevos.h" #include "core/system.h" -#include "frontend-common/cheevos.h" #include "mainwindow.h" #include "qtutils.h" #include "settingsdialog.h" diff --git a/src/duckstation-qt/qthostinterface.cpp b/src/duckstation-qt/qthostinterface.cpp index 6320899cb..7caa80249 100644 --- a/src/duckstation-qt/qthostinterface.cpp +++ b/src/duckstation-qt/qthostinterface.cpp @@ -48,7 +48,7 @@ Log_SetChannel(QtHostInterface); #endif #ifdef WITH_CHEEVOS -#include "frontend-common/cheevos.h" +#include "core/cheevos.h" #endif QtHostInterface::QtHostInterface(QObject* parent) : QObject(parent), CommonHostInterface() diff --git a/src/frontend-common/CMakeLists.txt b/src/frontend-common/CMakeLists.txt index 24d6ed657..97e67b0c0 100644 --- a/src/frontend-common/CMakeLists.txt +++ b/src/frontend-common/CMakeLists.txt @@ -108,15 +108,6 @@ if(ENABLE_DISCORD_PRESENCE) target_link_libraries(frontend-common PRIVATE discord-rpc) endif() -if(ENABLE_CHEEVOS) - target_sources(frontend-common PRIVATE - cheevos.cpp - cheevos.h - ) - target_compile_definitions(frontend-common PUBLIC -DWITH_CHEEVOS=1) - target_link_libraries(frontend-common PRIVATE rcheevos rapidjson) -endif() - # Copy the provided data directory to the output directory. add_custom_command(TARGET frontend-common POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/data" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" diff --git a/src/frontend-common/common_host_interface.cpp b/src/frontend-common/common_host_interface.cpp index dd63c29d7..c02da7852 100644 --- a/src/frontend-common/common_host_interface.cpp +++ b/src/frontend-common/common_host_interface.cpp @@ -52,7 +52,7 @@ #endif #ifdef WITH_CHEEVOS -#include "cheevos.h" +#include "core/cheevos.h" #endif #ifdef _WIN32 @@ -500,9 +500,7 @@ bool CommonHostInterface::ParseCommandLineParameters(int argc, char* argv[], void CommonHostInterface::OnAchievementsRefreshed() { -#ifdef WITH_CHEEVOS // noop -#endif } void CommonHostInterface::PollAndUpdate() @@ -3543,6 +3541,16 @@ std::vector CommonHostInterface::GetSettingStringList(const char* s return m_settings_interface->GetStringList(section, key); } +SettingsInterface* CommonHostInterface::GetSettingsInterface() +{ + return m_settings_interface.get(); +} + +std::lock_guard CommonHostInterface::GetSettingsLock() +{ + return std::lock_guard(m_settings_mutex); +} + void CommonHostInterface::SetTimerResolutionIncreased(bool enabled) { #if defined(_WIN32) && !defined(_UWP) diff --git a/src/frontend-common/common_host_interface.h b/src/frontend-common/common_host_interface.h index 23f42df62..574c48226 100644 --- a/src/frontend-common/common_host_interface.h +++ b/src/frontend-common/common_host_interface.h @@ -134,11 +134,8 @@ public: virtual void DestroySystem() override; /// Returns the settings interface. - ALWAYS_INLINE SettingsInterface* GetSettingsInterface() const { return m_settings_interface.get(); } - ALWAYS_INLINE std::lock_guard GetSettingsLock() - { - return std::lock_guard(m_settings_mutex); - } + SettingsInterface* GetSettingsInterface() override; + std::lock_guard GetSettingsLock() override; /// Returns the game list. ALWAYS_INLINE GameList* GetGameList() const { return m_game_list.get(); } @@ -312,7 +309,7 @@ public: virtual void* GetTopLevelWindowHandle() const; /// Called when achievements data is loaded. - virtual void OnAchievementsRefreshed(); + virtual void OnAchievementsRefreshed() override; /// Opens a file in the DuckStation "package". /// This is the APK for Android builds, or the program directory for standalone builds. diff --git a/src/frontend-common/frontend-common.props b/src/frontend-common/frontend-common.props index 6cddcadca..251cc5c98 100644 --- a/src/frontend-common/frontend-common.props +++ b/src/frontend-common/frontend-common.props @@ -4,11 +4,10 @@ - WITH_CHEEVOS=1;%(PreprocessorDefinitions) - $(SolutionDir)dep\imgui\include;$(SolutionDir)dep\simpleini\include;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\rcheevos\include;$(SolutionDir)dep\rapidjson\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) + $(SolutionDir)dep\simpleini\include;$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) - $(RootBuildDir)rcheevos\rcheevos.lib;$(RootBuildDir)simpleini\simpleini.lib;$(RootBuildDir)tinyxml2\tinyxml2.lib;$(RootBuildDir)core\core.lib;$(RootBuildDir)scmversion\scmversion.lib;%(AdditionalDependencies) + $(RootBuildDir)simpleini\simpleini.lib;$(RootBuildDir)tinyxml2\tinyxml2.lib;$(RootBuildDir)core\core.lib;$(RootBuildDir)scmversion\scmversion.lib;%(AdditionalDependencies) diff --git a/src/frontend-common/frontend-common.vcxproj b/src/frontend-common/frontend-common.vcxproj index 04ad3cd0d..bd043dfea 100644 --- a/src/frontend-common/frontend-common.vcxproj +++ b/src/frontend-common/frontend-common.vcxproj @@ -29,7 +29,6 @@ - true @@ -72,7 +71,6 @@ - true diff --git a/src/frontend-common/frontend-common.vcxproj.filters b/src/frontend-common/frontend-common.vcxproj.filters index b51d7ac4a..984952650 100644 --- a/src/frontend-common/frontend-common.vcxproj.filters +++ b/src/frontend-common/frontend-common.vcxproj.filters @@ -25,7 +25,6 @@ - @@ -58,7 +57,6 @@ - diff --git a/src/frontend-common/fullscreen_ui.cpp b/src/frontend-common/fullscreen_ui.cpp index b4bd7b034..0009bf312 100644 --- a/src/frontend-common/fullscreen_ui.cpp +++ b/src/frontend-common/fullscreen_ui.cpp @@ -2,11 +2,9 @@ #include "fullscreen_ui.h" #include "IconsFontAwesome5.h" -#include "cheevos.h" #include "common/byte_stream.h" #include "common/file_system.h" #include "common/log.h" -#include "common/lru_cache.h" #include "common/make_array.h" #include "common/string.h" #include "common/string_util.h" @@ -33,6 +31,10 @@ #include Log_SetChannel(FullscreenUI); +#ifdef WITH_CHEEVOS +#include "core/cheevos.h" +#endif + static constexpr float LAYOUT_MAIN_MENU_BAR_SIZE = 20.0f; // Should be DPI scaled, not layout scaled! using ImGuiFullscreen::g_large_font; @@ -64,6 +66,7 @@ using ImGuiFullscreen::EndMenuButtons; using ImGuiFullscreen::EndNavBar; using ImGuiFullscreen::EnumChoiceButton; using ImGuiFullscreen::FloatingButton; +using ImGuiFullscreen::GetCachedTexture; using ImGuiFullscreen::LayoutScale; using ImGuiFullscreen::MenuButton; using ImGuiFullscreen::MenuButtonFrame; @@ -123,8 +126,7 @@ static std::optional s_open_leaderboard_id; static bool LoadResources(); static void DestroyResources(); -static HostDisplayTexture* GetCachedTexture(const std::string& name); -static ImTextureID ResolveTextureHandle(const std::string& name); +static std::unique_ptr LoadTextureCallback(const char* path); static std::unique_ptr s_app_icon_texture; static std::unique_ptr s_placeholder_texture; @@ -135,7 +137,6 @@ static std::unique_ptr s_fallback_disc_texture; static std::unique_ptr s_fallback_exe_texture; static std::unique_ptr s_fallback_psf_texture; static std::unique_ptr s_fallback_playlist_texture; -static LRUCache> s_texture_cache; ////////////////////////////////////////////////////////////////////////// // Settings @@ -215,9 +216,11 @@ static std::thread s_game_list_load_thread; bool Initialize(CommonHostInterface* host_interface) { s_host_interface = host_interface; - s_texture_cache.SetMaxCapacity(128); - if (!LoadResources()) + if (!ImGuiFullscreen::Initialize() || !LoadResources()) + { + ImGuiFullscreen::Shutdown(); return false; + } s_settings_copy.Load(*s_host_interface->GetSettingsInterface()); LoadSettings(); @@ -225,7 +228,7 @@ bool Initialize(CommonHostInterface* host_interface) ImGuiFullscreen::UpdateLayoutScale(); ImGuiFullscreen::UpdateFonts(); - ImGuiFullscreen::SetResolveTextureFunction(ResolveTextureHandle); + ImGuiFullscreen::SetLoadTextureFunction(LoadTextureCallback); if (System::IsValid()) SystemCreated(); @@ -337,6 +340,7 @@ void Shutdown() s_cover_image_map.clear(); s_nav_input_values = {}; DestroyResources(); + ImGuiFullscreen::Shutdown(); s_host_interface = nullptr; } @@ -460,7 +464,6 @@ bool LoadResources() void DestroyResources() { - s_texture_cache.Clear(); s_app_icon_texture.reset(); s_placeholder_texture.reset(); s_fallback_playlist_texture.reset(); @@ -506,6 +509,11 @@ static std::unique_ptr LoadTexture(const char* path, bool fr return texture; } +std::unique_ptr LoadTextureCallback(const char* path) +{ + return LoadTexture(path, false); +} + std::unique_ptr LoadTextureResource(const char* name, bool allow_fallback /*= true*/) { const std::string path(StringUtil::StdStringFromFormat("resources" FS_OSPATH_SEPARATOR_STR "%s", name)); @@ -527,29 +535,6 @@ std::unique_ptr LoadTextureResource(const char* name, bool a return texture; } -HostDisplayTexture* GetCachedTexture(const std::string& name) -{ - std::unique_ptr* tex_ptr = s_texture_cache.Lookup(name); - if (!tex_ptr) - { - std::unique_ptr tex = LoadTexture(name.c_str(), false); - tex_ptr = s_texture_cache.Insert(name, std::move(tex)); - } - - return tex_ptr->get(); -} - -ImTextureID ResolveTextureHandle(const std::string& name) -{ - HostDisplayTexture* tex = GetCachedTexture(name); - return tex ? tex->GetHandle() : nullptr; -} - -bool InvalidateCachedTexture(const std::string& path) -{ - return s_texture_cache.Remove(path); -} - ////////////////////////////////////////////////////////////////////////// // Utility ////////////////////////////////////////////////////////////////////////// diff --git a/src/frontend-common/fullscreen_ui.h b/src/frontend-common/fullscreen_ui.h index f6bff698b..89ba592bd 100644 --- a/src/frontend-common/fullscreen_ui.h +++ b/src/frontend-common/fullscreen_ui.h @@ -63,7 +63,6 @@ bool IsBindingInput(); bool HandleKeyboardBinding(const char* keyName, bool pressed); std::unique_ptr LoadTextureResource(const char* name, bool allow_fallback = true); -bool InvalidateCachedTexture(const std::string& path); // Returns true if the message has been dismissed. bool DrawErrorWindow(const char* message);