From 616ee81f84d753669e3c182c4f04a5757e421939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 6 Apr 2024 12:04:45 +0200 Subject: [PATCH 1/4] Add another parameter to the internal "request" framework. --- Common/System/Request.cpp | 5 ++--- Common/System/Request.h | 3 ++- Common/System/System.h | 2 +- Common/VR/VRRenderer.cpp | 4 ++-- Core/RetroAchievements.cpp | 2 +- Qt/QtMain.cpp | 4 ++-- SDL/CocoaBarItems.mm | 2 +- SDL/SDLMain.cpp | 2 +- UWP/PPSSPP_UWPMain.cpp | 4 ++-- Windows/main.cpp | 3 ++- android/jni/app-android.cpp | 2 +- headless/Headless.cpp | 2 +- ios/main.mm | 2 +- libretro/libretro.cpp | 2 +- unittest/JitHarness.cpp | 2 +- 15 files changed, 21 insertions(+), 20 deletions(-) diff --git a/Common/System/Request.cpp b/Common/System/Request.cpp index ccaf5622f1..d6368c1042 100644 --- a/Common/System/Request.cpp +++ b/Common/System/Request.cpp @@ -31,7 +31,7 @@ const char *RequestTypeAsString(SystemRequestType type) { } } -bool RequestManager::MakeSystemRequest(SystemRequestType type, RequesterToken token, RequestCallback callback, RequestFailedCallback failedCallback, std::string_view param1, std::string_view param2, int param3) { +bool RequestManager::MakeSystemRequest(SystemRequestType type, RequesterToken token, RequestCallback callback, RequestFailedCallback failedCallback, std::string_view param1, std::string_view param2, int64_t param3, int64_t param4) { if (token == NO_REQUESTER_TOKEN) { _dbg_assert_(!callback); _dbg_assert_(!failedCallback); @@ -52,14 +52,13 @@ bool RequestManager::MakeSystemRequest(SystemRequestType type, RequesterToken to std::string p1(param1); std::string p2(param2); // TODO: Convert to string_view - if (!System_MakeRequest(type, requestId, p1, p2, param3)) { + if (!System_MakeRequest(type, requestId, p1, p2, param3, param4)) { if (callback || failedCallback) { std::lock_guard guard(callbackMutex_); callbackMap_.erase(requestId); } return false; } - return true; } diff --git a/Common/System/Request.h b/Common/System/Request.h index ec82214884..6e6e922b2a 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -27,7 +27,8 @@ public: // The callback you pass in will be called on the main thread later. // Params are at the end since it's the part most likely to recieve additions in the future, // now that we have both callbacks. - bool MakeSystemRequest(SystemRequestType type, RequesterToken token, RequestCallback callback, RequestFailedCallback failedCallback, std::string_view param1, std::string_view param2, int param3); + // Pointers can be passed through param3 and param4 if needed, by casting. + bool MakeSystemRequest(SystemRequestType type, RequesterToken token, RequestCallback callback, RequestFailedCallback failedCallback, std::string_view param1, std::string_view param2, int64_t param3, int64_t param4 = 0); // Called by the platform implementation, when it's finished with a request. void PostSystemSuccess(int requestId, const char *responseString, int responseValue = 0); diff --git a/Common/System/System.h b/Common/System/System.h index f0d1575de4..6763f79dc4 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -93,7 +93,7 @@ enum class SystemRequestType { // This can return false if it's known that the platform doesn't support the request, the app is supposed to handle // or ignore that cleanly. // Some requests don't use responses. -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3); +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int64_t param3, int64_t param4); PermissionStatus System_GetPermissionStatus(SystemPermission permission); void System_AskForPermission(SystemPermission permission); diff --git a/Common/VR/VRRenderer.cpp b/Common/VR/VRRenderer.cpp index 76184844d1..352d20f9c9 100644 --- a/Common/VR/VRRenderer.cpp +++ b/Common/VR/VRRenderer.cpp @@ -295,13 +295,13 @@ bool VR_InitFrame( engine_t* engine ) { } // Update passthrough - if (passthroughRunning != VR_GetConfig(VR_CONFIG_PASSTHROUGH)) { + if (passthroughRunning != (VR_GetConfig(VR_CONFIG_PASSTHROUGH) != 0)) { if (VR_GetConfig(VR_CONFIG_PASSTHROUGH)) { OXR(xrPassthroughLayerResumeFB(passthroughLayer)); } else { OXR(xrPassthroughLayerPauseFB(passthroughLayer)); } - passthroughRunning = VR_GetConfig(VR_CONFIG_PASSTHROUGH); + passthroughRunning = (VR_GetConfig(VR_CONFIG_PASSTHROUGH) != 0); } // NOTE: OpenXR does not use the concept of frame indices. Instead, diff --git a/Core/RetroAchievements.cpp b/Core/RetroAchievements.cpp index 5bdcdb7d34..7185adb529 100644 --- a/Core/RetroAchievements.cpp +++ b/Core/RetroAchievements.cpp @@ -530,9 +530,9 @@ static void load_integration_callback(int result, const char *error_message, rc_ rc_client_raintegration_set_event_handler(g_rcClient, &raintegration_event_handler); rc_client_raintegration_set_write_memory_function(g_rcClient, &raintegration_write_memory_handler); rc_client_raintegration_set_get_game_name_function(g_rcClient, &raintegration_get_game_name_handler); + HWND hWnd = (HWND)userdata; rc_client_raintegration_rebuild_submenu(g_rcClient, GetMenu(hWnd)); - DrawMenuBar(hWnd); break; } case RC_MISSING_VALUE: diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 85151fc1b5..235856423a 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -354,7 +354,7 @@ bool MainUI::HandleCustomEvent(QEvent *e) { return true; } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int64_t param3, int64_t param4) { switch (type) { case SystemRequestType::EXIT_APP: qApp->exit(0); @@ -388,7 +388,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } case SystemRequestType::BROWSE_FOR_IMAGE: // Fall back to file browser. - return System_MakeRequest(SystemRequestType::BROWSE_FOR_FILE, requestId, param1, param2, (int)BrowseFileType::IMAGE); + return System_MakeRequest(SystemRequestType::BROWSE_FOR_FILE, requestId, param1, param2, (int)BrowseFileType::IMAGE, 0); case SystemRequestType::BROWSE_FOR_FILE: g_requestId = requestId; g_param1 = param1; diff --git a/SDL/CocoaBarItems.mm b/SDL/CocoaBarItems.mm index 90703899f4..ed064c6428 100644 --- a/SDL/CocoaBarItems.mm +++ b/SDL/CocoaBarItems.mm @@ -548,7 +548,7 @@ TOGGLE_METHOD_INVERSE(BreakOnLoad, g_Config.bAutoRun) TOGGLE_METHOD(IgnoreIllegalRWs, g_Config.bIgnoreBadMemAccess) TOGGLE_METHOD(AutoFrameSkip, g_Config.bAutoFrameSkip, g_Config.UpdateAfterSettingAutoFrameSkip()) TOGGLE_METHOD(SoftwareRendering, g_Config.bSoftwareRendering) -TOGGLE_METHOD(FullScreen, g_Config.bFullScreen, System_MakeRequest(SystemRequestType::TOGGLE_FULLSCREEN_STATE, 0, g_Config.UseFullScreen() ? "1" : "0", "", 3)) +TOGGLE_METHOD(FullScreen, g_Config.bFullScreen, System_MakeRequest(SystemRequestType::TOGGLE_FULLSCREEN_STATE, 0, g_Config.UseFullScreen() ? "1" : "0", "", 3, 0)) // TOGGLE_METHOD(VSync, g_Config.bVSync) #undef TOGGLE_METHOD diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 9a5044be8a..ce527a2a14 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -223,7 +223,7 @@ void System_Vibrate(int length_ms) { // Ignore on PC } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int64_t param3, int64_t param4) { switch (type) { case SystemRequestType::RESTART_APP: g_RestartRequested = true; diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 17ab3a38ab..ccd510d4a9 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -460,7 +460,7 @@ void System_Notify(SystemNotification notification) { } } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int64_t param3, int64_t param4) { switch (type) { case SystemRequestType::EXIT_APP: @@ -478,7 +478,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ExecuteTask(error, Windows::ApplicationModel::Core::CoreApplication::RequestRestartAsync(nullptr)); if (error != Windows::ApplicationModel::Core::AppRestartFailureReason::RestartPending) { // Shutdown - System_MakeRequest(SystemRequestType::EXIT_APP, requestId, param1, param2, param3); + System_MakeRequest(SystemRequestType::EXIT_APP, requestId, param1, param2, param3, param4); } return true; } diff --git a/Windows/main.cpp b/Windows/main.cpp index 12c259ce70..7bdda88582 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -488,7 +488,7 @@ std::wstring MakeFilter(std::wstring filter) { return filter; } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int64_t param3, int64_t param4) { switch (type) { case SystemRequestType::EXIT_APP: if (!NativeIsRestarting()) { @@ -636,6 +636,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } case SystemRequestType::CREATE_GAME_SHORTCUT: return W32Util::CreateDesktopShortcut(param1, param2); + default: return false; } diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index c81cf9efeb..74a30bfc94 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -1097,7 +1097,7 @@ void System_Notify(SystemNotification notification) { } } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int64_t param3, int64_t param4) { switch (type) { case SystemRequestType::EXIT_APP: PushCommand("finish", ""); diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 2a802a2cc2..a396c591a0 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -117,7 +117,7 @@ bool System_GetPropertyBool(SystemProperty prop) { } void System_Notify(SystemNotification notification) {} void System_PostUIMessage(UIMessage message, const std::string ¶m) {} -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int64_t param3, int64_t param4) { switch (type) { case SystemRequestType::SEND_DEBUG_OUTPUT: if (g_headlessHost) { diff --git a/ios/main.mm b/ios/main.mm index 2425469e6e..5be93aae33 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -363,7 +363,7 @@ void System_Notify(SystemNotification notification) { } } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int64_t param3, int64_t param4) { switch (type) { case SystemRequestType::EXIT_APP: exit(0); diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 220afbda3a..4788a15964 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1709,7 +1709,7 @@ void System_Notify(SystemNotification notification) { break; } } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int64_t param3, int64_t param4) { return false; } void System_PostUIMessage(UIMessage message, const std::string ¶m) {} void NativeFrame(GraphicsContext *graphicsContext) {} void NativeResized() {} diff --git a/unittest/JitHarness.cpp b/unittest/JitHarness.cpp index 088416e2bc..71dd8f92c5 100644 --- a/unittest/JitHarness.cpp +++ b/unittest/JitHarness.cpp @@ -41,7 +41,7 @@ void NativeFrame(GraphicsContext *graphicsContext) { } void NativeResized() { } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int64_t param3, int64_t param4) { return false; } void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } void System_AskForPermission(SystemPermission permission) {} PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } From 9ec5efdcc573291c10bc54b0126e5d19387cfbfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 6 Apr 2024 12:14:29 +0200 Subject: [PATCH 2/4] Add facility to run callbacks on the window thread --- Common/System/Request.cpp | 6 ++++++ Common/System/Request.h | 2 ++ Common/System/System.h | 2 ++ Windows/MainWindow.cpp | 11 +++++++++++ Windows/MainWindow.h | 4 +++- Windows/main.cpp | 8 +++++++- 6 files changed, 31 insertions(+), 2 deletions(-) diff --git a/Common/System/Request.cpp b/Common/System/Request.cpp index d6368c1042..436a02d216 100644 --- a/Common/System/Request.cpp +++ b/Common/System/Request.cpp @@ -144,3 +144,9 @@ void System_ShowFileInFolder(const Path &path) { void System_BrowseForFolder(RequesterToken token, std::string_view title, const Path &initialPath, RequestCallback callback, RequestFailedCallback failedCallback) { g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FOLDER, token, callback, failedCallback, title, initialPath.ToCString(), 0); } + +void System_RunCallbackInWndProc(void (*callback)(void *, void *), void *userdata) { + int64_t castPtr = (int64_t)callback; + int64_t castUserData = (int64_t)userdata; + g_requestManager.MakeSystemRequest(SystemRequestType::RUN_CALLBACK_IN_WNDPROC, NO_REQUESTER_TOKEN, nullptr, nullptr, "", "", castPtr, castUserData); +} diff --git a/Common/System/Request.h b/Common/System/Request.h index 6e6e922b2a..e9f23bab8b 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -176,6 +176,8 @@ inline void System_SendDebugScreenshot(std::string_view data, int height) { g_requestManager.MakeSystemRequest(SystemRequestType::SEND_DEBUG_SCREENSHOT, NO_REQUESTER_TOKEN, nullptr, nullptr, data, "", height); } +void System_RunCallbackInWndProc(void (*callback)(void *, void *), void *userdata); + // Non-inline to avoid including Path.h void System_CreateGameShortcut(const Path &path, std::string_view title); void System_ShowFileInFolder(const Path &path); diff --git a/Common/System/System.h b/Common/System/System.h index 6763f79dc4..763c31f517 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -86,6 +86,8 @@ enum class SystemRequestType { GPS_COMMAND, INFRARED_COMMAND, MICROPHONE_COMMAND, + + RUN_CALLBACK_IN_WNDPROC, }; // Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h). diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 0bfb82a7bf..c162a510ee 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -764,6 +764,13 @@ namespace MainWindow } break; + case WM_USER_RUN_CALLBACK: + { + auto callback = reinterpret_cast(wParam); + void *userdata = reinterpret_cast(lParam); + callback(hWnd, userdata); + break; + } case WM_USER_GET_BASE_POINTER: Reporting::NotifyDebugger(); switch (lParam) { @@ -1135,4 +1142,8 @@ namespace MainWindow return g_isFullscreen; } + void RunCallbackInWndProc(void (*callback)(void *, void *), void *userdata) { + PostMessage(hwndMain, WM_USER_RUN_CALLBACK, reinterpret_cast(callback), reinterpret_cast(userdata)); + } + } // namespace diff --git a/Windows/MainWindow.h b/Windows/MainWindow.h index c4ed9f81fd..b79a10b2af 100644 --- a/Windows/MainWindow.h +++ b/Windows/MainWindow.h @@ -18,7 +18,8 @@ namespace MainWindow WM_USER_WINDOW_TITLE_CHANGED = WM_USER + 103, WM_USER_TOGGLE_FULLSCREEN = WM_USER + 105, WM_USER_RESTART_EMUTHREAD = WM_USER + 106, - WM_USER_SWITCHUMD_UPDATED = WM_USER + 107 + WM_USER_SWITCHUMD_UPDATED = WM_USER + 107, + WM_USER_RUN_CALLBACK = WM_USER + 108, }; enum { @@ -79,6 +80,7 @@ namespace MainWindow void ToggleDebugConsoleVisibility(); void SetInternalResolution(int res = -1); void SetWindowSize(int zoom); + void RunCallbackInWndProc(void (*callback)(void *window, void *userdata), void *userdata); } #endif diff --git a/Windows/main.cpp b/Windows/main.cpp index 7bdda88582..5e273b423e 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -636,7 +636,13 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } case SystemRequestType::CREATE_GAME_SHORTCUT: return W32Util::CreateDesktopShortcut(param1, param2); - + case SystemRequestType::RUN_CALLBACK_IN_WNDPROC: + { + auto func = reinterpret_cast(param3); + void *userdata = reinterpret_cast(param4); + MainWindow::RunCallbackInWndProc(func, userdata); + return true; + } default: return false; } From 00acaa32996e05809b8f86371309f4553e91887b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 6 Apr 2024 12:14:53 +0200 Subject: [PATCH 3/4] Build the RAIntegration menu on the right thread --- Core/RetroAchievements.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/RetroAchievements.cpp b/Core/RetroAchievements.cpp index 7185adb529..d97d9427ba 100644 --- a/Core/RetroAchievements.cpp +++ b/Core/RetroAchievements.cpp @@ -531,8 +531,10 @@ static void load_integration_callback(int result, const char *error_message, rc_ rc_client_raintegration_set_write_memory_function(g_rcClient, &raintegration_write_memory_handler); rc_client_raintegration_set_get_game_name_function(g_rcClient, &raintegration_get_game_name_handler); - HWND hWnd = (HWND)userdata; - rc_client_raintegration_rebuild_submenu(g_rcClient, GetMenu(hWnd)); + System_RunCallbackInWndProc([](void *vhWnd, void *userdata) { + HWND hWnd = reinterpret_cast(vhWnd); + rc_client_raintegration_rebuild_submenu(g_rcClient, GetMenu(hWnd)); + }, nullptr); break; } case RC_MISSING_VALUE: From 80a12ca102d26a4fc1f80de6aadf4340fefebce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 6 Apr 2024 12:18:28 +0200 Subject: [PATCH 4/4] Run the update menu item thing on the window thread too. --- Core/RetroAchievements.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/RetroAchievements.cpp b/Core/RetroAchievements.cpp index d97d9427ba..5b85f08075 100644 --- a/Core/RetroAchievements.cpp +++ b/Core/RetroAchievements.cpp @@ -499,7 +499,10 @@ static void raintegration_event_handler(const rc_client_raintegration_event_t *e case RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED: // The checked state of one of the menu items has changed and should be reflected in the UI. // Call the handy helper function if the menu was created by rc_client_raintegration_rebuild_submenu. - rc_client_raintegration_update_menu_item(client, event->menu_item); + System_RunCallbackInWndProc([](void *vhWnd, void *userdata) { + auto menuItem = reinterpret_cast(userdata); + rc_client_raintegration_update_menu_item(g_rcClient, menuItem); + }, reinterpret_cast(reinterpret_cast(event->menu_item))); break; case RC_CLIENT_RAINTEGRATION_EVENT_PAUSE: // The toolkit has hit a breakpoint and wants to pause the emulator. Do so.