diff --git a/Common/UI/Screen.cpp b/Common/UI/Screen.cpp index b1fe507cfe4a..1bf1d32f95f4 100644 --- a/Common/UI/Screen.cpp +++ b/Common/UI/Screen.cpp @@ -154,7 +154,8 @@ void ScreenManager::resized() { } } -void ScreenManager::render() { +ScreenRenderFlags ScreenManager::render() { + ScreenRenderFlags flags = ScreenRenderFlags::NONE; if (!stack_.empty()) { // Collect the screens to render TinySet layers; @@ -169,12 +170,12 @@ void ScreenManager::render() { Screen *backgroundScreen = nullptr; do { --iter; - if (!coveringScreen) { - layers.push_back(iter->screen); - } else if (!backgroundScreen && iter->screen->canBeBackground()) { + if (!backgroundScreen && iter->screen->canBeBackground()) { // There still might be a screen that wants to be background - generally the EmuScreen if present. layers.push_back(iter->screen); backgroundScreen = iter->screen; + } else if (!coveringScreen) { + layers.push_back(iter->screen); } if (iter->flags != LAYER_TRANSPARENT) { coveringScreen = iter->screen; @@ -194,9 +195,6 @@ void ScreenManager::render() { if (i == (int)layers.size() - 1) { // Bottom. mode = ScreenRenderMode::FIRST; - if (layers[i] == backgroundScreen && coveringScreen != layers[i]) { - mode |= ScreenRenderMode::BACKGROUND; - } if (i == 0) { mode |= ScreenRenderMode::TOP; } @@ -205,12 +203,12 @@ void ScreenManager::render() { } else { mode = ScreenRenderMode::BEHIND; } - layers[i]->render(mode); + flags |= layers[i]->render(mode); } if (overlayScreen_) { // It doesn't care about mode. - overlayScreen_->render(ScreenRenderMode::TOP); + flags |= overlayScreen_->render(ScreenRenderMode::TOP); } getUIContext()->Flush(); @@ -224,6 +222,7 @@ void ScreenManager::render() { } processFinishDialog(); + return flags; } void ScreenManager::getFocusPosition(float &x, float &y, float &z) { diff --git a/Common/UI/Screen.h b/Common/UI/Screen.h index ed5b2a957aa7..e65b0d8d7993 100644 --- a/Common/UI/Screen.h +++ b/Common/UI/Screen.h @@ -50,12 +50,17 @@ enum class ScreenFocusChange { enum class ScreenRenderMode { DEFAULT = 0, FIRST = 1, - BACKGROUND = 2, BEHIND = 4, TOP = 8, }; ENUM_CLASS_BITOPS(ScreenRenderMode); +enum class ScreenRenderFlags { + NONE = 0, + HANDLED_THROTTLING = 1, +}; +ENUM_CLASS_BITOPS(ScreenRenderFlags); + class Screen { public: Screen() : screenManager_(nullptr) { } @@ -65,7 +70,7 @@ class Screen { virtual void onFinish(DialogResult reason) {} virtual void update() {} - virtual void render(ScreenRenderMode mode) {} + virtual ScreenRenderFlags render(ScreenRenderMode mode) = 0; virtual void resized() {} virtual void dialogFinished(const Screen *dialog, DialogResult result) {} virtual void sendMessage(UIMessage message, const char *value) {} @@ -128,7 +133,7 @@ class ScreenManager { postRenderUserdata_ = userdata; } - void render(); + ScreenRenderFlags render(); void resized(); void shutdown(); diff --git a/Common/UI/UIScreen.cpp b/Common/UI/UIScreen.cpp index 99bb251c31df..927d8bdb4a24 100644 --- a/Common/UI/UIScreen.cpp +++ b/Common/UI/UIScreen.cpp @@ -212,27 +212,32 @@ void UIScreen::SetupViewport() { draw->SetTargetSize(g_display.pixel_xres, g_display.pixel_yres); } -void UIScreen::render(ScreenRenderMode mode) { +ScreenRenderFlags UIScreen::render(ScreenRenderMode mode) { if (mode & ScreenRenderMode::FIRST) { SetupViewport(); } DoRecreateViews(); + UIContext &uiContext = *screenManager()->getUIContext(); if (root_) { - UIContext &uiContext = *screenManager()->getUIContext(); - UI::LayoutViewHierarchy(uiContext, root_, ignoreInsets_); + } - uiContext.PushTransform({translation_, scale_, alpha_}); + uiContext.PushTransform({translation_, scale_, alpha_}); - uiContext.Begin(); - DrawBackground(uiContext); + uiContext.Begin(); + DrawBackground(uiContext); + if (root_) { root_->Draw(uiContext); - uiContext.Flush(); - - uiContext.PopTransform(); } + uiContext.Flush(); + DrawForeground(uiContext); + uiContext.Flush(); + + uiContext.PopTransform(); + + return ScreenRenderFlags::NONE; } TouchInput UIScreen::transformTouch(const TouchInput &touch) { diff --git a/Common/UI/UIScreen.h b/Common/UI/UIScreen.h index a5fb9604ad70..d7487bee717d 100644 --- a/Common/UI/UIScreen.h +++ b/Common/UI/UIScreen.h @@ -36,7 +36,7 @@ class UIScreen : public Screen { ~UIScreen(); void update() override; - void render(ScreenRenderMode mode) override; + ScreenRenderFlags render(ScreenRenderMode mode) override; void deviceLost() override; void deviceRestored() override; @@ -72,6 +72,8 @@ class UIScreen : public Screen { protected: virtual void DrawBackground(UIContext &ui) {} + virtual void DrawForeground(UIContext &ui) {} + void SetupViewport(); void DoRecreateViews(); diff --git a/Core/Config.cpp b/Core/Config.cpp index eec83a23e87c..c7b194a3a35f 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -297,6 +297,8 @@ static const ConfigSetting generalSettings[] = { ConfigSetting("EnablePlugins", &g_Config.bLoadPlugins, true, CfgFlag::PER_GAME), ConfigSetting("IgnoreCompatSettings", &g_Config.sIgnoreCompatSettings, "", CfgFlag::PER_GAME | CfgFlag::REPORT), + + ConfigSetting("RunBehindPauseMenu", &g_Config.bRunBehindPauseMenu, false, CfgFlag::DEFAULT), }; static bool DefaultSasThread() { diff --git a/Core/Config.h b/Core/Config.h index 1b5a737e3020..de2d6971cbfe 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -99,9 +99,10 @@ struct Config { // Not used on mobile devices. bool bPauseExitsEmulator; - bool bPauseMenuExitsEmulator; + bool bRunBehindPauseMenu; + // Core bool bIgnoreBadMemAccess; diff --git a/UI/BackgroundAudio.cpp b/UI/BackgroundAudio.cpp index c990da8a68bc..08090f88e496 100644 --- a/UI/BackgroundAudio.cpp +++ b/UI/BackgroundAudio.cpp @@ -302,10 +302,6 @@ void BackgroundAudio::SetGame(const Path &path) { } bool BackgroundAudio::Play() { - if (GetUIState() == UISTATE_INGAME) { - return false; - } - std::lock_guard lock(mutex_); // Immediately stop the sound if it is turned off while playing. diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index 4df546bb4ca8..6181a9f429ca 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -713,27 +713,25 @@ void TouchTestScreen::axis(const AxisInput &axis) { UpdateLogView(); } -void TouchTestScreen::render(ScreenRenderMode mode) { - UIDialogScreenWithGameBackground::render(mode); - UIContext *ui_context = screenManager()->getUIContext(); - Bounds bounds = ui_context->GetLayoutBounds(); +void TouchTestScreen::DrawForeground(UIContext &dc) { + Bounds bounds = dc.GetLayoutBounds(); - ui_context->BeginNoTex(); + dc.BeginNoTex(); for (int i = 0; i < MAX_TOUCH_POINTS; i++) { if (touches_[i].id != -1) { - ui_context->Draw()->Circle(touches_[i].x, touches_[i].y, 100.0, 3.0, 80, 0.0f, 0xFFFFFFFF, 1.0); + dc.Draw()->Circle(touches_[i].x, touches_[i].y, 100.0, 3.0, 80, 0.0f, 0xFFFFFFFF, 1.0); } } - ui_context->Flush(); + dc.Flush(); - ui_context->Begin(); + dc.Begin(); char buffer[4096]; for (int i = 0; i < MAX_TOUCH_POINTS; i++) { if (touches_[i].id != -1) { - ui_context->Draw()->Circle(touches_[i].x, touches_[i].y, 100.0, 3.0, 80, 0.0f, 0xFFFFFFFF, 1.0); + dc.Draw()->Circle(touches_[i].x, touches_[i].y, 100.0, 3.0, 80, 0.0f, 0xFFFFFFFF, 1.0); snprintf(buffer, sizeof(buffer), "%0.1fx%0.1f", touches_[i].x, touches_[i].y); - ui_context->DrawText(buffer, touches_[i].x, touches_[i].y + (touches_[i].y > g_display.dp_yres - 100.0f ? -135.0f : 95.0f), 0xFFFFFFFF, ALIGN_HCENTER | FLAG_DYNAMIC_ASCII); + dc.DrawText(buffer, touches_[i].x, touches_[i].y + (touches_[i].y > g_display.dp_yres - 100.0f ? -135.0f : 95.0f), 0xFFFFFFFF, ALIGN_HCENTER | FLAG_DYNAMIC_ASCII); } } @@ -762,8 +760,8 @@ void TouchTestScreen::render(ScreenRenderMode mode) { // On Android, also add joystick debug data. - ui_context->DrawTextShadow(buffer, bounds.centerX(), bounds.y + 20.0f, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); - ui_context->Flush(); + dc.DrawTextShadow(buffer, bounds.centerX(), bounds.y + 20.0f, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); + dc.Flush(); } void RecreateActivity() { @@ -799,8 +797,7 @@ UI::EventReturn TouchTestScreen::OnRecreateActivity(UI::EventParams &e) { class Backplate : public UI::InertView { public: - Backplate(float scale, UI::LayoutParams *layoutParams = nullptr) : InertView(layoutParams), scale_(scale) { - } + Backplate(float scale, UI::LayoutParams *layoutParams = nullptr) : InertView(layoutParams), scale_(scale) {} void Draw(UIContext &dc) override { for (float dy = 0.0f; dy <= 4.0f; dy += 1.0f) { diff --git a/UI/ControlMappingScreen.h b/UI/ControlMappingScreen.h index 69c8a4d449d2..d096fdec531d 100644 --- a/UI/ControlMappingScreen.h +++ b/UI/ControlMappingScreen.h @@ -147,7 +147,7 @@ class TouchTestScreen : public UIDialogScreenWithGameBackground { } void touch(const TouchInput &touch) override; - void render(ScreenRenderMode mode) override; + void DrawForeground(UIContext &dc) override; bool key(const KeyInput &key) override; void axis(const AxisInput &axis) override; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index ec7542c22d93..5620f90639e9 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1438,12 +1438,17 @@ void EmuScreen::darken() { } } -void EmuScreen::render(ScreenRenderMode mode) { +ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) { + ScreenRenderFlags flags = ScreenRenderFlags::NONE; + using namespace Draw; + + DrawContext *draw = screenManager()->getDrawContext(); + if (!draw) + return flags; // shouldn't really happen but I've seen a suspicious stack trace.. + if (mode & ScreenRenderMode::FIRST) { // Actually, always gonna be first when it exists (?) - using namespace Draw; - DrawContext *draw = screenManager()->getDrawContext(); // Here we do NOT bind the backbuffer or clear the screen, unless non-buffered. // The emuscreen is different than the others - we really want to allow the game to render to framebuffers // before we ever bind the backbuffer for rendering. On mobile GPUs, switching back and forth between render @@ -1471,19 +1476,13 @@ void EmuScreen::render(ScreenRenderMode mode) { draw->SetTargetSize(g_display.pixel_xres, g_display.pixel_yres); } - using namespace Draw; - - DrawContext *thin3d = screenManager()->getDrawContext(); - if (!thin3d) - return; // shouldn't really happen but I've seen a suspicious stack trace.. - g_OSD.NudgeSidebar(); if (mode & ScreenRenderMode::TOP) { System_Notify(SystemNotification::KEEP_SCREEN_AWAKE); - } else { + } else if (!g_Config.bRunBehindPauseMenu) { // Not on top. Let's not execute, only draw the image. - thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE }, "EmuScreen_Stepping"); + draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE }, "EmuScreen_Stepping"); // Just to make sure. if (PSP_IsInited() && !g_Config.bSkipBufferEffects) { PSP_BeginHostFrame(); @@ -1491,7 +1490,7 @@ void EmuScreen::render(ScreenRenderMode mode) { PSP_EndHostFrame(); darken(); } - return; + return flags; } if (invalid_) { @@ -1502,9 +1501,9 @@ void EmuScreen::render(ScreenRenderMode mode) { // It's possible this might be set outside PSP_RunLoopFor(). // In this case, we need to double check it here. checkPowerDown(); - thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR }, "EmuScreen_Invalid"); + draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR }, "EmuScreen_Invalid"); renderUI(); - return; + return flags; } // Freeze-frame functionality (loads a savestate on every frame). @@ -1528,6 +1527,8 @@ void EmuScreen::render(ScreenRenderMode mode) { PSP_BeginHostFrame(); PSP_RunLoopWhileState(); + flags |= ScreenRenderFlags::HANDLED_THROTTLING; + // Hopefully coreState is now CORE_NEXTFRAME switch (coreState) { case CORE_NEXTFRAME: @@ -1543,12 +1544,12 @@ void EmuScreen::render(ScreenRenderMode mode) { // Clear to blue background screen bool dangerousSettings = !Reporting::IsSupported(); uint32_t color = dangerousSettings ? 0xFF900050 : 0xFF900000; - thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE, color }, "EmuScreen_RuntimeError"); + draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE, color }, "EmuScreen_RuntimeError"); // The info is drawn later in renderUI } else { // If we're stepping, it's convenient not to clear the screen entirely, so we copy display to output. // This won't work in non-buffered, but that's fine. - thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE }, "EmuScreen_Stepping"); + draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE }, "EmuScreen_Stepping"); // Just to make sure. if (PSP_IsInited()) { gpu->CopyDisplayToOutput(true); @@ -1570,12 +1571,19 @@ void EmuScreen::render(ScreenRenderMode mode) { // This must happen after PSP_EndHostFrame so that things like push buffers are end-frame'd before we start destroying stuff. if (checkPowerDown() || rebind) { // Shutting down can end up ending the current render pass - thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR }, "EmuScreen_NoFrame"); + draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR }, "EmuScreen_NoFrame"); + } + + if (!(mode & ScreenRenderMode::TOP)) { + // We're in run-behind mode, but we don't want to draw chat, debug UI and stuff. + // So, darken and bail here. + darken(); + return flags; } if (hasVisibleUI()) { // In most cases, this should already be bound and a no-op. - thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::KEEP, RPAction::DONT_CARE, RPAction::DONT_CARE }, "EmuScreen_UI"); + draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::KEEP, RPAction::DONT_CARE, RPAction::DONT_CARE }, "EmuScreen_UI"); cardboardDisableButton_->SetVisibility(g_Config.bEnableCardboardVR ? UI::V_VISIBLE : UI::V_GONE); screenManager()->getUIContext()->BeginFrame(); renderUI(); @@ -1590,10 +1598,11 @@ void EmuScreen::render(ScreenRenderMode mode) { if (mode & ScreenRenderMode::TOP) { // TODO: Replace this with something else. if (stopRender_) - thin3d->WipeQueue(); - } else if (!screenManager()->topScreen()->wantBrightBackground()) { + draw->WipeQueue(); + } else { darken(); } + return flags; } bool EmuScreen::hasVisibleUI() { diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index a050fd92660c..a97273027450 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -42,7 +42,7 @@ class EmuScreen : public UIScreen { const char *tag() const override { return "Emu"; } void update() override; - void render(ScreenRenderMode mode) override; + ScreenRenderFlags render(ScreenRenderMode mode) override; void dialogFinished(const Screen *dialog, DialogResult result) override; void sendMessage(UIMessage message, const char *value) override; void resized() override; diff --git a/UI/GPUDriverTestScreen.cpp b/UI/GPUDriverTestScreen.cpp index c10faf17ba85..326383dd1d03 100644 --- a/UI/GPUDriverTestScreen.cpp +++ b/UI/GPUDriverTestScreen.cpp @@ -311,7 +311,7 @@ void GPUDriverTestScreen::CreateViews() { anchor->Add(back); } -void GPUDriverTestScreen::DiscardTest() { +void GPUDriverTestScreen::DiscardTest(UIContext &dc) { using namespace UI; using namespace Draw; if (!discardWriteDepthStencil_) { @@ -440,7 +440,6 @@ void GPUDriverTestScreen::DiscardTest() { rasterNoCull->Release(); } - UIContext &dc = *screenManager()->getUIContext(); Draw::DrawContext *draw = dc.GetDrawContext(); static const char * const writeModeNames[] = { "Stencil+Depth", "Stencil", "Depth" }; @@ -529,10 +528,9 @@ void GPUDriverTestScreen::DiscardTest() { dc.Flush(); } -void GPUDriverTestScreen::ShaderTest() { +void GPUDriverTestScreen::ShaderTest(UIContext &dc) { using namespace Draw; - UIContext &dc = *screenManager()->getUIContext(); Draw::DrawContext *draw = dc.GetDrawContext(); if (!adrenoLogicDiscardPipeline_) { @@ -629,17 +627,13 @@ void GPUDriverTestScreen::ShaderTest() { dc.Flush(); } - -void GPUDriverTestScreen::render(ScreenRenderMode mode) { - using namespace Draw; - UIScreen::render(mode); - +void GPUDriverTestScreen::DrawForeground(UIContext &dc) { switch (tabHolder_->GetCurrentTab()) { case 0: - DiscardTest(); + DiscardTest(dc); break; case 1: - ShaderTest(); + ShaderTest(dc); break; } } diff --git a/UI/GPUDriverTestScreen.h b/UI/GPUDriverTestScreen.h index 16c1f8d7c63c..5c8b67cfa460 100644 --- a/UI/GPUDriverTestScreen.h +++ b/UI/GPUDriverTestScreen.h @@ -15,13 +15,13 @@ class GPUDriverTestScreen : public UIDialogScreenWithBackground { ~GPUDriverTestScreen(); void CreateViews() override; - void render(ScreenRenderMode mode) override; + void DrawForeground(UIContext &dc) override; const char *tag() const override { return "GPUDriverTest"; } private: - void DiscardTest(); - void ShaderTest(); + void DiscardTest(UIContext &dc); + void ShaderTest(UIContext &dc); // Common objects Draw::SamplerState *samplerNearest_ = nullptr; diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index aae67e8be313..76ebc4efc6c7 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -276,14 +276,14 @@ UI::EventReturn GameScreen::OnDeleteConfig(UI::EventParams &e) return UI::EVENT_DONE; } -void GameScreen::render(ScreenRenderMode mode) { - UIScreen::render(mode); +ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) { + ScreenRenderFlags flags = UIScreen::render(mode); auto ga = GetI18NCategory(I18NCat::GAME); - Draw::DrawContext *thin3d = screenManager()->getDrawContext(); + Draw::DrawContext *draw = screenManager()->getDrawContext(); - std::shared_ptr info = g_gameInfoCache->GetInfo(thin3d, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE | GAMEINFO_WANTUNCOMPRESSEDSIZE); + std::shared_ptr info = g_gameInfoCache->GetInfo(draw, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE | GAMEINFO_WANTUNCOMPRESSEDSIZE); if (tvTitle_) { tvTitle_->SetText(info->GetTitle()); @@ -416,6 +416,7 @@ void GameScreen::render(ScreenRenderMode mode) { choice->SetVisibility(UI::V_VISIBLE); } } + return flags; } UI::EventReturn GameScreen::OnShowInFolder(UI::EventParams &e) { diff --git a/UI/GameScreen.h b/UI/GameScreen.h index 4340fae811bd..b8fd92fe784f 100644 --- a/UI/GameScreen.h +++ b/UI/GameScreen.h @@ -38,7 +38,7 @@ class GameScreen : public UIDialogScreenWithGameBackground { void update() override; - void render(ScreenRenderMode mode) override; + ScreenRenderFlags render(ScreenRenderMode mode) override; const char *tag() const override { return "Game"; } diff --git a/UI/MemStickScreen.h b/UI/MemStickScreen.h index f409e958153a..cf0eecbc1b6a 100644 --- a/UI/MemStickScreen.h +++ b/UI/MemStickScreen.h @@ -52,14 +52,15 @@ class MemStickScreen : public UIDialogScreenWithBackground { void dialogFinished(const Screen *dialog, DialogResult result) override; void update() override; - void render(ScreenRenderMode mode) override { + ScreenRenderFlags render(ScreenRenderMode mode) override { // Simple anti-flicker due to delayed finish. if (!done_) { // render as usual. - UIDialogScreenWithBackground::render(mode); + return UIDialogScreenWithBackground::render(mode); } else { // no render. black frame insertion is better than flicker. } + return ScreenRenderFlags::NONE; } private: diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 76218bf27a07..a5dce8b7935a 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -429,7 +429,7 @@ void HandleCommonMessages(UIMessage message, const char *value, ScreenManager *m } } -void BackgroundScreen::render(ScreenRenderMode mode) { +ScreenRenderFlags BackgroundScreen::render(ScreenRenderMode mode) { if (mode & ScreenRenderMode::FIRST) { SetupViewport(); } else { @@ -453,6 +453,8 @@ void BackgroundScreen::render(ScreenRenderMode mode) { uiContext->Flush(); uiContext->PopTransform(); + + return ScreenRenderFlags::NONE; } void BackgroundScreen::sendMessage(UIMessage message, const char *value) { @@ -732,12 +734,9 @@ void LogoScreen::touch(const TouchInput &touch) { } } -void LogoScreen::render(ScreenRenderMode mode) { +void LogoScreen::DrawForeground(UIContext &dc) { using namespace Draw; - UIScreen::render(mode); - UIContext &dc = *screenManager()->getUIContext(); - const Bounds &bounds = dc.GetBounds(); dc.Begin(); @@ -752,10 +751,6 @@ void LogoScreen::render(ScreenRenderMode mode) { alphaText = 3.0f - t; uint32_t textColor = colorAlpha(dc.theme->infoStyle.fgColor, alphaText); - float x, y, z; - screenManager()->getFocusPosition(x, y, z); - ::DrawBackground(dc, alpha, x, y, z); - auto cr = GetI18NCategory(I18NCat::PSPCREDITS); auto gr = GetI18NCategory(I18NCat::GRAPHICS); char temp[256]; @@ -871,9 +866,7 @@ void CreditsScreen::update() { UpdateUIState(UISTATE_MENU); } -void CreditsScreen::render(ScreenRenderMode mode) { - UIScreen::render(mode); - +void CreditsScreen::DrawForeground(UIContext &dc) { auto cr = GetI18NCategory(I18NCat::PSPCREDITS); std::string specialthanksMaxim = "Maxim "; @@ -1020,7 +1013,6 @@ void CreditsScreen::render(ScreenRenderMode mode) { } credits[0] = (const char *)temp; - UIContext &dc = *screenManager()->getUIContext(); dc.Begin(); const Bounds &bounds = dc.GetLayoutBounds(); diff --git a/UI/MiscScreens.h b/UI/MiscScreens.h index cc4a6b595f77..da816c686156 100644 --- a/UI/MiscScreens.h +++ b/UI/MiscScreens.h @@ -38,10 +38,9 @@ inline void NoOpVoidBool(bool) {} class BackgroundScreen : public UIScreen { public: - void render(ScreenRenderMode mode) override; + ScreenRenderFlags render(ScreenRenderMode mode) override; void sendMessage(UIMessage message, const char *value) override; - private: void CreateViews() override {} const char *tag() const override { return "bg"; } @@ -146,7 +145,7 @@ class LogoScreen : public UIScreen { bool key(const KeyInput &key) override; void touch(const TouchInput &touch) override; void update() override; - void render(ScreenRenderMode mode) override; + void DrawForeground(UIContext &ui) override; void sendMessage(UIMessage message, const char *value) override; void CreateViews() override {} @@ -164,7 +163,7 @@ class CreditsScreen : public UIDialogScreenWithBackground { public: CreditsScreen(); void update() override; - void render(ScreenRenderMode mode) override; + void DrawForeground(UIContext &ui) override; void CreateViews() override; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 05e7ec97d82c..ad47de968baa 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1077,12 +1077,7 @@ static void SendMouseDeltaAxis(); void NativeFrame(GraphicsContext *graphicsContext) { PROFILE_END_FRAME(); - bool menuThrottle = (GetUIState() != UISTATE_INGAME || !PSP_IsInited()) && GetUIState() != UISTATE_EXIT; - - double startTime; - if (menuThrottle) { - startTime = time_now_d(); - } + double startTime = time_now_d(); std::vector toProcess; { @@ -1107,7 +1102,6 @@ void NativeFrame(GraphicsContext *graphicsContext) { g_DownloadManager.Update(); g_Discord.Update(); - g_BackgroundAudio.Play(); g_OSD.Update(); @@ -1147,7 +1141,7 @@ void NativeFrame(GraphicsContext *graphicsContext) { g_screenManager->getUIContext()->SetTintSaturation(g_Config.fUITint, g_Config.fUISaturation); // All actual rendering happen in here. - g_screenManager->render(); + ScreenRenderFlags renderFlags = g_screenManager->render(); if (g_screenManager->getUIContext()->Text()) { g_screenManager->getUIContext()->Text()->OncePerFrame(); } @@ -1200,7 +1194,7 @@ void NativeFrame(GraphicsContext *graphicsContext) { graphicsContext->Poll(); } - if (menuThrottle) { + if (!(renderFlags & ScreenRenderFlags::HANDLED_THROTTLING)) { float refreshRate = System_GetPropertyFloat(SYSPROP_DISPLAY_REFRESH_RATE); // Simple throttling to not burn the GPU in the menu. // TODO: This should move into NativeFrame. Also, it's only necessary in MAILBOX or IMMEDIATE presentation modes. @@ -1208,6 +1202,9 @@ void NativeFrame(GraphicsContext *graphicsContext) { int sleepTime = (int)(1000.0 / refreshRate) - (int)(diffTime * 1000.0); if (sleepTime > 0) sleep_ms(sleepTime); + + // TODO: We should ideally mix this with game audio. + g_BackgroundAudio.Play(); } SendMouseDeltaAxis(); diff --git a/UI/OnScreenDisplay.cpp b/UI/OnScreenDisplay.cpp index 0edaa36b0203..9781a251a604 100644 --- a/UI/OnScreenDisplay.cpp +++ b/UI/OnScreenDisplay.cpp @@ -517,9 +517,7 @@ void OSDOverlayScreen::CreateViews() { osmView_ = root_->Add(new OnScreenMessagesView(new UI::AnchorLayoutParams(0.0f, 0.0f, 0.0f, 0.0f))); } -void OSDOverlayScreen::render(ScreenRenderMode mode) { - UIScreen::render(mode); - +void OSDOverlayScreen::DrawForeground(UIContext &ui) { DebugOverlay debugOverlay = (DebugOverlay)g_Config.iDebugOverlay; // Special case control for now, since it uses the control mapper that's owned by EmuScreen. diff --git a/UI/OnScreenDisplay.h b/UI/OnScreenDisplay.h index 1440fdca635b..85159e0d50fa 100644 --- a/UI/OnScreenDisplay.h +++ b/UI/OnScreenDisplay.h @@ -41,7 +41,7 @@ class OSDOverlayScreen : public UIScreen { bool UnsyncTouch(const TouchInput &touch) override; void CreateViews() override; - void render(ScreenRenderMode mode) override; + void DrawForeground(UIContext &ui) override; void update() override; private: diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index d2bf2e78b5b9..bf329710eb2d 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -414,6 +414,8 @@ void GamePauseScreen::CreateViews() { } else { rightColumnItems->Add(new Choice(pa->T("Exit to menu")))->OnClick.Handle(this, &GamePauseScreen::OnExitToMenu); } + rightColumnItems->Add(new Spacer(25.0f)); + rightColumnItems->Add(new CheckBox(&g_Config.bRunBehindPauseMenu, "Run Behind")); } UI::EventReturn GamePauseScreen::OnGameSettings(UI::EventParams &e) { diff --git a/UI/PauseScreen.h b/UI/PauseScreen.h index c7e32dc180bc..ec8d1d2bdc28 100644 --- a/UI/PauseScreen.h +++ b/UI/PauseScreen.h @@ -65,4 +65,6 @@ class GamePauseScreen : public UIDialogScreenWithGameBackground { // hack bool finishNextFrame_ = false; PauseScreenMode mode_ = PauseScreenMode::MAIN; + + UI::Button *pauseButton_ = nullptr; }; diff --git a/UI/ReportScreen.cpp b/UI/ReportScreen.cpp index 5ec3415785ef..cff056929065 100644 --- a/UI/ReportScreen.cpp +++ b/UI/ReportScreen.cpp @@ -166,8 +166,8 @@ ReportScreen::ReportScreen(const Path &gamePath) ratingEnabled_ = enableReporting_; } -void ReportScreen::render(ScreenRenderMode mode) { - UIScreen::render(mode); +ScreenRenderFlags ReportScreen::render(ScreenRenderMode mode) { + ScreenRenderFlags flags = UIScreen::render(mode); if (mode & ScreenRenderMode::TOP) { @@ -189,6 +189,7 @@ void ReportScreen::render(ScreenRenderMode mode) { tookScreenshot_ = true; } } + return flags; } void ReportScreen::update() { diff --git a/UI/ReportScreen.h b/UI/ReportScreen.h index cd7c55ab10d6..c287042dead4 100644 --- a/UI/ReportScreen.h +++ b/UI/ReportScreen.h @@ -40,7 +40,7 @@ class ReportScreen : public UIDialogScreenWithGameBackground { const char *tag() const override { return "Report"; } protected: - void render(ScreenRenderMode mode) override; + ScreenRenderFlags render(ScreenRenderMode mode) override; void update() override; void resized() override; void CreateViews() override;