diff --git a/Common/System/NativeApp.h b/Common/System/NativeApp.h index 3f1a74a6a4a4..2c8439127973 100644 --- a/Common/System/NativeApp.h +++ b/Common/System/NativeApp.h @@ -84,3 +84,10 @@ inline bool NativeClearSecret(std::string_view nameOfSecret) { } // On failure, returns an empty string. Good enough since any real secret is non-empty. std::string NativeLoadSecret(std::string_view nameOfSecret); + +// Don't run the core when minimized etc. +void Native_NotifyWindowHidden(bool hidden); +bool Native_IsWindowHidden(); + +// TODO: Feels like this belongs elsewhere. +bool Native_UpdateScreenScale(int width, int height); diff --git a/Core/Core.cpp b/Core/Core.cpp index 367a2dea713e..dffe87817767 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -79,7 +79,6 @@ static int steppingCounter = 0; static std::set lifecycleFuncs; static std::set stopFuncs; -static bool windowHidden = false; static bool powerSaving = false; static MIPSExceptionInfo g_exceptionInfo; @@ -88,15 +87,6 @@ void Core_SetGraphicsContext(GraphicsContext *ctx) { PSP_CoreParameter().graphicsContext = ctx; } -void Core_NotifyWindowHidden(bool hidden) { - windowHidden = hidden; - // TODO: Wait until we can react? -} - -bool Core_IsWindowHidden() { - return windowHidden; -} - void Core_ListenLifecycle(CoreLifecycleFunc func) { lifecycleFuncs.insert(func); } @@ -144,7 +134,7 @@ bool Core_IsInactive() { return coreState != CORE_RUNNING_CPU && coreState != CORE_NEXTFRAME && !coreStatePending; } -static inline void Core_StateProcessed() { +void Core_StateProcessed() { if (coreStatePending) { std::lock_guard guard(m_hInactiveMutex); coreStatePending = false; @@ -174,67 +164,6 @@ bool Core_GetPowerSaving() { return powerSaving; } -static bool IsWindowSmall(int pixelWidth, int pixelHeight) { - // Can't take this from config as it will not be set if windows is maximized. - int w = (int)(pixelWidth * g_display.dpi_scale_x); - int h = (int)(pixelHeight * g_display.dpi_scale_y); - return g_Config.IsPortrait() ? (h < 480 + 80) : (w < 480 + 80); -} - -// TODO: Feels like this belongs elsewhere. -bool UpdateScreenScale(int width, int height) { - bool smallWindow; - - float g_logical_dpi = System_GetPropertyFloat(SYSPROP_DISPLAY_LOGICAL_DPI); - g_display.dpi = System_GetPropertyFloat(SYSPROP_DISPLAY_DPI); - - if (g_display.dpi < 0.0f) { - g_display.dpi = 96.0f; - } - if (g_logical_dpi < 0.0f) { - g_logical_dpi = 96.0f; - } - - g_display.dpi_scale_x = g_logical_dpi / g_display.dpi; - g_display.dpi_scale_y = g_logical_dpi / g_display.dpi; - g_display.dpi_scale_real_x = g_display.dpi_scale_x; - g_display.dpi_scale_real_y = g_display.dpi_scale_y; - - smallWindow = IsWindowSmall(width, height); - if (smallWindow) { - g_display.dpi /= 2.0f; - g_display.dpi_scale_x *= 2.0f; - g_display.dpi_scale_y *= 2.0f; - } - g_display.pixel_in_dps_x = 1.0f / g_display.dpi_scale_x; - g_display.pixel_in_dps_y = 1.0f / g_display.dpi_scale_y; - - int new_dp_xres = (int)(width * g_display.dpi_scale_x); - int new_dp_yres = (int)(height * g_display.dpi_scale_y); - - bool dp_changed = new_dp_xres != g_display.dp_xres || new_dp_yres != g_display.dp_yres; - bool px_changed = g_display.pixel_xres != width || g_display.pixel_yres != height; - - if (dp_changed || px_changed) { - g_display.dp_xres = new_dp_xres; - g_display.dp_yres = new_dp_yres; - g_display.pixel_xres = width; - g_display.pixel_yres = height; - NativeResized(); - return true; - } - return false; -} - -// Used by Windows, SDL, Qt. Doesn't belong in this file. -void Core_RunLoop(GraphicsContext *ctx) { - if (windowHidden && g_Config.bPauseWhenMinimized) { - sleep_ms(16, "window-hidden"); - return; - } - NativeFrame(ctx); -} - bool Core_RequestSingleStep(CPUStepType type, int stepSize) { std::lock_guard guard(g_stepMutex); if (g_stepCommand.type != CPUStepType::None) { @@ -389,50 +318,6 @@ void Core_ProcessStepping(MIPSDebugInterface *cpu) { System_Notify(SystemNotification::MEM_VIEW); } -// Many platforms, like Android, do not call this function but handle things on their own. -// Instead they simply call NativeFrame directly. -bool Core_Run(GraphicsContext *ctx) { - System_Notify(SystemNotification::DISASSEMBLY); - while (true) { - if (GetUIState() != UISTATE_INGAME) { - Core_StateProcessed(); - if (GetUIState() == UISTATE_EXIT) { - // Not sure why we do a final frame here? - NativeFrame(ctx); - return false; - } - Core_RunLoop(ctx); - continue; - } - - switch (coreState) { - case CORE_RUNNING_CPU: - case CORE_STEPPING_CPU: - case CORE_RUNNING_GE: - case CORE_STEPPING_GE: - // enter a fast runloop - Core_RunLoop(ctx); - if (coreState == CORE_POWERDOWN) { - return true; - } - break; - case CORE_POWERDOWN: - // Need to step the loop. - Core_RunLoop(ctx); - return true; - - case CORE_POWERUP: - case CORE_BOOT_ERROR: - case CORE_RUNTIME_ERROR: - // Exit loop!! - return true; - - case CORE_NEXTFRAME: - return true; - } - } -} - // Free-threaded (hm, possibly except tracing). void Core_Break(const char *reason, u32 relatedAddress) { // Stop the tracer diff --git a/Core/Core.h b/Core/Core.h index 586f3bd1652b..574fea3b22ff 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -25,13 +25,10 @@ class GraphicsContext; -void Core_RunLoop(GraphicsContext *ctx); - // For platforms that don't call Core_Run void Core_SetGraphicsContext(GraphicsContext *ctx); // Returns false when an UI exit state is detected. -bool Core_Run(GraphicsContext *ctx); void Core_Stop(); // X11, sigh. @@ -95,16 +92,12 @@ bool Core_IsStepping(); bool Core_IsActive(); bool Core_IsInactive(); -// Warning: these currently work only on Windows. + +// Warning: these three are only used on Windows - debugger integration. +void Core_StateProcessed(); void Core_WaitInactive(); void Core_WaitInactive(int milliseconds); -bool UpdateScreenScale(int width, int height); - -// Don't run the core when minimized etc. -void Core_NotifyWindowHidden(bool hidden); -bool Core_IsWindowHidden(); - void Core_SetPowerSaving(bool mode); bool Core_GetPowerSaving(); diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 5452b0f66413..df9587aa3b35 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -482,7 +482,7 @@ void MainUI::EmuThreadFunc() { emuThreadState = (int)EmuThreadState::RUNNING; while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) { updateAccelerometer(); - Core_RunLoop(graphicsContext); + NativeFrame(graphicsContext); } emuThreadState = (int)EmuThreadState::STOPPED; @@ -548,7 +548,7 @@ QString MainUI::InputBoxGetQString(QString title, QString defaultValue) { } void MainUI::resizeGL(int w, int h) { - if (UpdateScreenScale(w, h)) { + if (Native_UpdateScreenScale(w, h)) { System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); } xscale = w / this->width(); @@ -566,7 +566,7 @@ void MainUI::timerEvent(QTimerEvent *) { void MainUI::changeEvent(QEvent *e) { QGLWidget::changeEvent(e); if (e->type() == QEvent::WindowStateChange) - Core_NotifyWindowHidden(isMinimized()); + Native_NotifyWindowHidden(isMinimized()); } bool MainUI::event(QEvent *e) { @@ -726,7 +726,7 @@ void MainUI::paintGL() { #endif updateAccelerometer(); if (emuThreadState == (int)EmuThreadState::DISABLED) { - Core_RunLoop(graphicsContext); + NativeFrame(graphicsContext); } else { graphicsContext->ThreadFrame(); // Do the rest in EmuThreadFunc diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index edda066b1c35..24bd0f1ef419 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -67,7 +67,7 @@ class MainWindow : public QMainWindow QMainWindow::changeEvent(e); // Does not work on Linux for Qt5.2 or Qt5.3 (Qt bug) if(e->type() == QEvent::WindowStateChange) - Core_NotifyWindowHidden(isMinimized()); + Native_NotifyWindowHidden(isMinimized()); } void closeEvent(QCloseEvent *) { exitAct(); } diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 85b5ac617017..ee290a8467d6 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -695,7 +695,7 @@ static void EmuThreadFunc(GraphicsContext *graphicsContext) { NativeInitGraphics(graphicsContext); while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) { - Core_RunLoop(graphicsContext); + NativeFrame(graphicsContext); } emuThreadState = (int)EmuThreadState::STOPPED; graphicsContext->StopThread(); @@ -737,7 +737,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta // We have to juggle around 3 kinds of "DPI spaces" if a logical DPI is // provided (through --dpi, it is equal to system DPI if unspecified): // - SDL gives us motion events in "system DPI" points - // - UpdateScreenScale expects pixels, so in a way "96 DPI" points + // - Native_UpdateScreenScale expects pixels, so in a way "96 DPI" points // - The UI code expects motion events in "logical DPI" points float mx = event.motion.x * g_DesktopDPI * g_display.dpi_scale_x; float my = event.motion.y * g_DesktopDPI * g_display.dpi_scale_x; @@ -756,17 +756,17 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta int new_height = event.window.data2; // The size given by SDL is in point-units, convert these to - // pixels before passing to UpdateScreenScale() + // pixels before passing to Native_UpdateScreenScale() int new_width_px = new_width * g_DesktopDPI; int new_height_px = new_height * g_DesktopDPI; - Core_NotifyWindowHidden(false); + Native_NotifyWindowHidden(false); Uint32 window_flags = SDL_GetWindowFlags(window); bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN); // This one calls NativeResized if the size changed. - UpdateScreenScale(new_width_px, new_height_px); + Native_UpdateScreenScale(new_width_px, new_height_px); // Set variable here in case fullscreen was toggled by hotkey if (g_Config.UseFullScreen() != fullscreen) { @@ -804,11 +804,11 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta case SDL_WINDOWEVENT_MINIMIZED: case SDL_WINDOWEVENT_HIDDEN: - Core_NotifyWindowHidden(true); + Native_NotifyWindowHidden(true); break; case SDL_WINDOWEVENT_EXPOSED: case SDL_WINDOWEVENT_SHOWN: - Core_NotifyWindowHidden(false); + Native_NotifyWindowHidden(false); break; default: break; @@ -1426,7 +1426,7 @@ int main(int argc, char *argv[]) { float dpi_scale = 1.0f / (g_ForcedDPI == 0.0f ? g_DesktopDPI : g_ForcedDPI); - UpdateScreenScale(w * g_DesktopDPI, h * g_DesktopDPI); + Native_UpdateScreenScale(w * g_DesktopDPI, h * g_DesktopDPI); bool mainThreadIsRender = g_Config.iGPUBackend == (int)GPUBackend::OPENGL; @@ -1535,7 +1535,7 @@ int main(int argc, char *argv[]) { if (g_QuitRequested || g_RestartRequested) break; if (emuThreadState == (int)EmuThreadState::DISABLED) { - Core_RunLoop(graphicsContext); + NativeFrame(graphicsContext); } if (g_QuitRequested || g_RestartRequested) break; @@ -1545,7 +1545,7 @@ int main(int argc, char *argv[]) { inputTracker.MouseCaptureControl(); - bool renderThreadPaused = Core_IsWindowHidden() && g_Config.bPauseWhenMinimized && emuThreadState != (int)EmuThreadState::DISABLED; + bool renderThreadPaused = Native_IsWindowHidden() && g_Config.bPauseWhenMinimized && emuThreadState != (int)EmuThreadState::DISABLED; if (emuThreadState != (int)EmuThreadState::DISABLED && !renderThreadPaused) { if (!graphicsContext->ThreadFrame()) break; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index e8b7cb265b0f..c164a23a3fb3 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -185,6 +185,7 @@ static Draw::Pipeline *colorPipeline; static Draw::Pipeline *texColorPipeline; static UIContext *uiContext; static int g_restartGraphics; +static bool g_windowHidden = false; #ifdef _WIN32 WindowsAudioBackend *winAudioBackend; @@ -1022,6 +1023,13 @@ static void SendMouseDeltaAxis(); void NativeFrame(GraphicsContext *graphicsContext) { PROFILE_END_FRAME(); + if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_DESKTOP) { + if (g_windowHidden && g_Config.bPauseWhenMinimized) { + sleep_ms(16, "window-hidden"); + return; + } + } + // This can only be accessed from Windows currently, and causes linking errors with headless etc. if (g_restartGraphics == 1) { // Used for debugging only. @@ -1528,3 +1536,63 @@ std::string NativeLoadSecret(std::string_view nameOfSecret) { } return data; } + +void Native_NotifyWindowHidden(bool hidden) { + g_windowHidden = hidden; + // TODO: Wait until we can react? +} + +bool Native_IsWindowHidden() { + return g_windowHidden; +} + +static bool IsWindowSmall(int pixelWidth, int pixelHeight) { + // Can't take this from config as it will not be set if windows is maximized. + int w = (int)(pixelWidth * g_display.dpi_scale_x); + int h = (int)(pixelHeight * g_display.dpi_scale_y); + return g_Config.IsPortrait() ? (h < 480 + 80) : (w < 480 + 80); +} + +bool Native_UpdateScreenScale(int width, int height) { + bool smallWindow; + + float g_logical_dpi = System_GetPropertyFloat(SYSPROP_DISPLAY_LOGICAL_DPI); + g_display.dpi = System_GetPropertyFloat(SYSPROP_DISPLAY_DPI); + + if (g_display.dpi < 0.0f) { + g_display.dpi = 96.0f; + } + if (g_logical_dpi < 0.0f) { + g_logical_dpi = 96.0f; + } + + g_display.dpi_scale_x = g_logical_dpi / g_display.dpi; + g_display.dpi_scale_y = g_logical_dpi / g_display.dpi; + g_display.dpi_scale_real_x = g_display.dpi_scale_x; + g_display.dpi_scale_real_y = g_display.dpi_scale_y; + + smallWindow = IsWindowSmall(width, height); + if (smallWindow) { + g_display.dpi /= 2.0f; + g_display.dpi_scale_x *= 2.0f; + g_display.dpi_scale_y *= 2.0f; + } + g_display.pixel_in_dps_x = 1.0f / g_display.dpi_scale_x; + g_display.pixel_in_dps_y = 1.0f / g_display.dpi_scale_y; + + int new_dp_xres = (int)(width * g_display.dpi_scale_x); + int new_dp_yres = (int)(height * g_display.dpi_scale_y); + + bool dp_changed = new_dp_xres != g_display.dp_xres || new_dp_yres != g_display.dp_yres; + bool px_changed = g_display.pixel_xres != width || g_display.pixel_yres != height; + + if (dp_changed || px_changed) { + g_display.dp_xres = new_dp_xres; + g_display.dp_yres = new_dp_yres; + g_display.pixel_xres = width; + g_display.pixel_yres = height; + NativeResized(); + return true; + } + return false; +} diff --git a/UWP/App.cpp b/UWP/App.cpp index 937021eff848..5548b30991c2 100644 --- a/UWP/App.cpp +++ b/UWP/App.cpp @@ -330,7 +330,7 @@ void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ ar PSP_CoreParameter().pixelWidth = (int)(width * scale); PSP_CoreParameter().pixelHeight = (int)(height * scale); - if (UpdateScreenScale((int)width, (int)height)) { + if (Native_UpdateScreenScale((int)width, (int)height)) { System_PostUIMessage(UIMessage::GPU_DISPLAY_RESIZED); } } diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 7e574c434682..e3a5868a90d5 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -75,6 +75,48 @@ bool MainThread_Ready() { return g_inLoop; } +static bool Core_Run(GraphicsContext *ctx) { + System_Notify(SystemNotification::DISASSEMBLY); + while (true) { + if (GetUIState() != UISTATE_INGAME) { + Core_StateProcessed(); + if (GetUIState() == UISTATE_EXIT) { + // Not sure why we do a final frame here? + NativeFrame(ctx); + return false; + } + NativeFrame(ctx); + continue; + } + + switch (coreState) { + case CORE_RUNNING_CPU: + case CORE_STEPPING_CPU: + case CORE_RUNNING_GE: // Shouldn't be in this state between frames + case CORE_STEPPING_GE: // This is OK though. + // enter a fast runloop + NativeFrame(ctx); + if (coreState == CORE_POWERDOWN) { + return true; + } + break; + case CORE_POWERDOWN: + // Need to step the loop. + NativeFrame(ctx); + return true; + + case CORE_POWERUP: + case CORE_BOOT_ERROR: + case CORE_RUNTIME_ERROR: + // Exit loop!! + return true; + + case CORE_NEXTFRAME: + return true; + } + } +} + static void EmuThreadFunc(GraphicsContext *graphicsContext) { SetCurrentThreadName("EmuThread"); diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 062a05220024..55aaaa5f9bdb 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -273,7 +273,7 @@ namespace MainWindow static void HandleSizeChange(int newSizingType) { SavePosition(); - Core_NotifyWindowHidden(false); + Native_NotifyWindowHidden(false); if (!g_Config.bPauseWhenMinimized) { System_PostUIMessage(UIMessage::WINDOW_MINIMIZED, "false"); } @@ -294,7 +294,7 @@ namespace MainWindow DEBUG_LOG(Log::System, "Pixel width/height: %dx%d", PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); - if (UpdateScreenScale(width, height)) { + if (Native_UpdateScreenScale(width, height)) { System_PostUIMessage(UIMessage::GPU_DISPLAY_RESIZED); System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); } @@ -936,7 +936,7 @@ namespace MainWindow break; case SIZE_MINIMIZED: - Core_NotifyWindowHidden(true); + Native_NotifyWindowHidden(true); if (!g_Config.bPauseWhenMinimized) { System_PostUIMessage(UIMessage::WINDOW_MINIMIZED, "true"); }