diff --git a/Common/UI/ScreenManager.cpp b/Common/UI/ScreenManager.cpp index 38246c348a..1f994a57a8 100644 --- a/Common/UI/ScreenManager.cpp +++ b/Common/UI/ScreenManager.cpp @@ -2,6 +2,8 @@ #include "Common/System/System.h" #include "Common/Data/Collections/TinySet.h" #include "Common/UI/ScreenManager.h" +#include "Common/UI/Context.h" +#include "Common/Render/DrawBuffer.h" #include "Common/UI/Root.h" #include "Common/UI/View.h" #include "Common/UI/ScrollView.h" @@ -278,7 +280,11 @@ ScreenRenderFlags ScreenManager::Render(std::function afterPreRender) { afterPreRender(); - // Secondary outputs. The topmost screen with something for one draws it, otherwise it's left cleared. + // Secondary outputs. The topmost screen with something for one draws it, then the background screen. + UIContext *ui = getUIContext(); + if (!outputs_.empty()) { + ui->BeginFrame(); + } for (const Output &output : outputs_) { Draw::Swapchain *swapchain = output.display.swapchain; if (!swapchain) { @@ -289,11 +295,26 @@ ScreenRenderFlags ScreenManager::Render(std::function afterPreRender) { draw_->GetFramebufferDimensions(swapchain, &w, &h); draw_->SetViewport(Draw::Viewport{0.0f, 0.0f, (float)w, (float)h, 0.0f, 1.0f}); draw_->SetScissorRect(0, 0, w, h); + + // UI drawn there gets the primary's DPI scale, over the whole output. + const float dpWidth = w * g_display.dpi_scale_x; + const float dpHeight = h * g_display.dpi_scale_y; + const Bounds primaryBounds = ui->GetBounds(); + ui->SetBounds(Bounds(0, 0, dpWidth, dpHeight)); + ui->Draw()->PushDrawMatrix(ComputeOrthoMatrix(dpWidth, dpHeight, draw_->GetDeviceCaps().coordConvention)); + bool drawn = false; for (auto iter = stack_.rbegin(); iter != stack_.rend(); ++iter) { if (iter->screen->renderOutput(output.display)) { + drawn = true; break; } } + if (!drawn && backgroundScreen_) { + backgroundScreen_->renderOutput(output.display); + } + ui->Flush(); + ui->Draw()->PopDrawMatrix(); + ui->SetBounds(primaryBounds); } // Now, start the final render pass. This is now the ONLY place where binding the backbuffer is allowed. diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index dede720f6d..3c2e9cc6ab 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -97,6 +97,20 @@ void HandleCommonMessages(UIMessage message, const char *value, ScreenManager *m } } +// Nothing on the stack shows anything there, so we're in the menus. +bool BackgroundScreen::renderOutput(const OutputDisplay &output) { + if (output.role != OutputRole::Game) { + return false; + } + UIContext &dc = *screenManager()->getUIContext(); + auto di = GetI18NCategory(I18NCat::DIALOG); + const Bounds &bounds = dc.GetBounds(); + dc.Begin(); + dc.DrawText(di->T("Menus are on your device"), bounds.centerX(), bounds.centerY(), 0xFF505050, ALIGN_CENTER); + dc.Flush(); + return true; +} + ScreenRenderFlags BackgroundScreen::render(ScreenRenderMode mode) { UIContext *uiContext = screenManager()->getUIContext(); diff --git a/UI/MiscScreens.h b/UI/MiscScreens.h index 9e9fc8cd0d..ceb8b35ae8 100644 --- a/UI/MiscScreens.h +++ b/UI/MiscScreens.h @@ -37,6 +37,7 @@ inline void NoOpVoidBool(bool) {} class BackgroundScreen : public UIScreen { public: ScreenRenderFlags render(ScreenRenderMode mode) override; + bool renderOutput(const OutputDisplay &output) override; void sendMessage(UIMessage message, const char *value) override; private: