Merge pull request #18515 from hrydgard/run-behind-pause-screen

Run behind pause screen
This commit is contained in:
Henrik Rydgård 2023-12-11 17:00:07 +01:00 committed by GitHub
commit 65081da7f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 209 additions and 138 deletions

View File

@ -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<Screen *, 6> layers;
@ -167,18 +168,20 @@ void ScreenManager::render() {
auto iter = stack_.end();
Screen *coveringScreen = nullptr;
Screen *backgroundScreen = nullptr;
bool first = true;
do {
--iter;
if (!coveringScreen) {
layers.push_back(iter->screen);
} else if (!backgroundScreen && iter->screen->canBeBackground()) {
if (!backgroundScreen && iter->screen->canBeBackground(first)) {
// 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;
}
first = false;
} while (iter != stack_.begin());
// Confusing-looking expression, argh! Note the '_'
@ -188,15 +191,11 @@ void ScreenManager::render() {
}
// OK, now we iterate backwards over our little pile of collected screens.
bool first = true;
for (int i = (int)layers.size() - 1; i >= 0; i--) {
ScreenRenderMode mode = ScreenRenderMode::DEFAULT;
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 +204,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 +223,7 @@ void ScreenManager::render() {
}
processFinishDialog();
return flags;
}
void ScreenManager::getFocusPosition(float &x, float &y, float &z) {

View File

@ -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,13 +70,13 @@ public:
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) {}
virtual void deviceLost() {}
virtual void deviceRestored() {}
virtual bool canBeBackground() const { return false; }
virtual bool canBeBackground(bool isTop) const { return false; }
virtual bool wantBrightBackground() const { return false; } // special hack for DisplayLayoutScreen.
virtual void focusChanged(ScreenFocusChange focusChange);
@ -128,7 +133,7 @@ public:
postRenderUserdata_ = userdata;
}
void render();
ScreenRenderFlags render();
void resized();
void shutdown();

View File

@ -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.Begin();
DrawBackground(uiContext);
root_->Draw(uiContext);
uiContext.Flush();
uiContext.PopTransform();
}
uiContext.PushTransform({translation_, scale_, alpha_});
uiContext.Begin();
DrawBackground(uiContext);
if (root_) {
root_->Draw(uiContext);
}
uiContext.Flush();
DrawForeground(uiContext);
uiContext.Flush();
uiContext.PopTransform();
return ScreenRenderFlags::NONE;
}
TouchInput UIScreen::transformTouch(const TouchInput &touch) {

View File

@ -36,7 +36,7 @@ public:
~UIScreen();
void update() override;
void render(ScreenRenderMode mode) override;
ScreenRenderFlags render(ScreenRenderMode mode) override;
void deviceLost() override;
void deviceRestored() override;
@ -72,6 +72,8 @@ protected:
protected:
virtual void DrawBackground(UIContext &ui) {}
virtual void DrawForeground(UIContext &ui) {}
void SetupViewport();
void DoRecreateViews();

View File

@ -903,6 +903,18 @@ public:
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override {
w = size_; h = size_;
}
void GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const override {
if (horiz.type == AT_MOST || horiz.type == EXACTLY)
w = horiz.size;
else
w = size_;
if (vert.type == AT_MOST || vert.type == EXACTLY)
h = vert.size;
else
h = size_;
}
void Draw(UIContext &dc) override {}
std::string DescribeText() const override { return ""; }

View File

@ -25,7 +25,7 @@ namespace UI {
static constexpr Size ITEM_HEIGHT = 64.f;
void ApplyGravity(const Bounds outer, const Margins &margins, float w, float h, int gravity, Bounds &inner) {
void ApplyGravity(const Bounds &outer, const Margins &margins, float w, float h, int gravity, Bounds &inner) {
inner.w = w;
inner.h = h;
@ -495,6 +495,10 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v
if (views_.empty())
return;
if (tag_ == "debug") {
tag_ = "debug";
}
float sum = 0.0f;
float maxOther = 0.0f;
float totalWeight = 0.0f;
@ -666,6 +670,10 @@ void LinearLayout::Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec v
void LinearLayout::Layout() {
const Bounds &bounds = bounds_;
if (tag_ == "debug") {
tag_ = "debug";
}
Bounds itemBounds;
float pos;

View File

@ -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() {

View File

@ -99,9 +99,10 @@ public:
// Not used on mobile devices.
bool bPauseExitsEmulator;
bool bPauseMenuExitsEmulator;
bool bRunBehindPauseMenu;
// Core
bool bIgnoreBadMemAccess;

View File

@ -123,10 +123,14 @@ void FramebufferManagerCommon::CheckPostShaders() {
void FramebufferManagerCommon::BeginFrame() {
DecimateFBOs();
presentation_->BeginFrame();
currentRenderVfb_ = nullptr;
}
bool FramebufferManagerCommon::PresentedThisFrame() const {
return presentation_->PresentedThisFrame();
}
void FramebufferManagerCommon::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) {
displayFramebufPtr_ = framebuf & 0x3FFFFFFF;
if (Memory::IsVRAMAddress(displayFramebufPtr_))

View File

@ -485,6 +485,8 @@ public:
currentFramebufferCopy_ = nullptr;
}
bool PresentedThisFrame() const;
protected:
virtual void ReadbackFramebuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode);
// Used for when a shader is required, such as GLES.

View File

@ -931,6 +931,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
previousUniforms_ = uniforms;
presentedThisFrame_ = true;
}
void PresentationCommon::CalculateRenderResolution(int *width, int *height, int *scaleFactor, bool *upscaling, bool *ssaa) const {

View File

@ -98,6 +98,13 @@ public:
bool UpdatePostShader();
void BeginFrame() {
presentedThisFrame_ = false;
}
bool PresentedThisFrame() const {
return presentedThisFrame_;
}
void DeviceLost();
void DeviceRestore(Draw::DrawContext *draw);
@ -159,6 +166,7 @@ protected:
bool usePostShader_ = false;
bool restorePostShader_ = false;
bool presentedThisFrame_ = false;
ShaderLanguage lang_;
struct PrevFBO {

View File

@ -722,6 +722,10 @@ void GPUCommon::BeginFrame() {
GPURecord::NotifyBeginFrame();
}
bool GPUCommon::PresentedThisFrame() const {
return framebufferManager_ ? framebufferManager_->PresentedThisFrame() : true;
}
void GPUCommon::SlowRunLoop(DisplayList &list) {
const bool dumpThisFrame = dumpThisFrame_;
while (downcount > 0) {

View File

@ -226,6 +226,8 @@ public:
fullInfo = reportingFullInfo_;
}
bool PresentedThisFrame() const override;
protected:
void ClearCacheNextFrame() override {}

View File

@ -503,7 +503,6 @@ void GPUCommonHW::UpdateCmdInfo() {
void GPUCommonHW::BeginFrame() {
GPUCommon::BeginFrame();
if (drawEngineCommon_->EverUsedExactEqualDepth() && !sawExactEqualDepth_) {
sawExactEqualDepth_ = true;
gstate_c.SetUseFlags(CheckGPUFeatures());

View File

@ -253,6 +253,7 @@ public:
virtual bool FramebufferDirty() = 0;
virtual bool FramebufferReallyDirty() = 0;
virtual bool BusyDrawing() = 0;
virtual bool PresentedThisFrame() const = 0;
// If any jit is being used inside the GPU.
virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) = 0;

View File

@ -302,10 +302,6 @@ void BackgroundAudio::SetGame(const Path &path) {
}
bool BackgroundAudio::Play() {
if (GetUIState() == UISTATE_INGAME) {
return false;
}
std::lock_guard<std::mutex> lock(mutex_);
// Immediately stop the sound if it is turned off while playing.

View File

@ -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) {

View File

@ -147,7 +147,7 @@ public:
}
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;

View File

@ -1415,9 +1415,10 @@ static void DrawFPS(UIContext *ctx, const Bounds &bounds) {
ctx->RebindTexture();
}
bool EmuScreen::canBeBackground() const {
if (g_Config.bSkipBufferEffects)
return false;
bool EmuScreen::canBeBackground(bool isTop) const {
if (g_Config.bSkipBufferEffects) {
return isTop || (g_Config.bTransparentBackground && g_Config.bRunBehindPauseMenu);
}
bool forceTransparent = false; // this needs to be true somehow on the display layout screen.
@ -1438,12 +1439,19 @@ 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..
bool skipBufferEffects = g_Config.bSkipBufferEffects;
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
@ -1467,23 +1475,19 @@ void EmuScreen::render(ScreenRenderMode mode) {
viewport.MaxDepth = 1.0;
viewport.MinDepth = 0.0;
draw->SetViewport(viewport);
skipBufferEffects = true;
}
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 +1495,7 @@ void EmuScreen::render(ScreenRenderMode mode) {
PSP_EndHostFrame();
darken();
}
return;
return flags;
}
if (invalid_) {
@ -1502,9 +1506,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 +1532,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 +1549,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);
@ -1567,15 +1573,29 @@ void EmuScreen::render(ScreenRenderMode mode) {
PSP_EndHostFrame();
}
// 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");
if (gpu && !gpu->PresentedThisFrame() && !skipBufferEffects) {
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR }, "EmuScreen_NoFrame");
Viewport viewport{ 0.0f, 0.0f, (float)g_display.pixel_xres, (float)g_display.pixel_yres, 0.0f, 1.0f };
draw->SetViewport(viewport);
draw->SetScissorRect(0, 0, g_display.pixel_xres, g_display.pixel_yres);
}
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.
if (skipBufferEffects) {
// Need to reset viewport/scissor.
Viewport viewport{ 0.0f, 0.0f, (float)g_display.pixel_xres, (float)g_display.pixel_yres, 0.0f, 1.0f };
draw->SetViewport(viewport);
draw->SetScissorRect(0, 0, g_display.pixel_xres, g_display.pixel_yres);
}
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 +1610,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() {

View File

@ -42,11 +42,11 @@ public:
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;
bool canBeBackground() const override;
bool canBeBackground(bool isTop) const override;
// Note: Unlike your average boring UIScreen, here we override the Unsync* functions
// to get minimal latency and full control. We forward to UIScreen when needed.

View File

@ -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;
}
}

View File

@ -15,13 +15,13 @@ public:
~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;

View File

@ -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<GameInfo> info = g_gameInfoCache->GetInfo(thin3d, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE | GAMEINFO_WANTUNCOMPRESSEDSIZE);
std::shared_ptr<GameInfo> 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) {

View File

@ -38,7 +38,7 @@ public:
void update() override;
void render(ScreenRenderMode mode) override;
ScreenRenderFlags render(ScreenRenderMode mode) override;
const char *tag() const override { return "Game"; }

View File

@ -52,14 +52,15 @@ protected:
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:

View File

@ -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();

View File

@ -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 @@ public:
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;

View File

@ -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<PendingMessage> 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();

View File

@ -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.

View File

@ -41,7 +41,7 @@ public:
bool UnsyncTouch(const TouchInput &touch) override;
void CreateViews() override;
void render(ScreenRenderMode mode) override;
void DrawForeground(UIContext &ui) override;
void update() override;
private:

View File

@ -356,8 +356,12 @@ void GamePauseScreen::CreateViews() {
leftColumnItems->Add(new NoticeView(NoticeLevel::INFO, notAvailable, ""));
}
ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(vertical ? 200 : 300, FILL_PARENT, actionMenuMargins));
root_->Add(rightColumn);
ViewGroup *rightColumnHolder = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(vertical ? 200 : 300, FILL_PARENT, actionMenuMargins));
ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0f));
rightColumnHolder->Add(rightColumn);
root_->Add(rightColumnHolder);
LinearLayout *rightColumnItems = new LinearLayout(ORIENT_VERTICAL);
rightColumn->Add(rightColumnItems);
@ -414,6 +418,17 @@ void GamePauseScreen::CreateViews() {
} else {
rightColumnItems->Add(new Choice(pa->T("Exit to menu")))->OnClick.Handle(this, &GamePauseScreen::OnExitToMenu);
}
ViewGroup *playControls = rightColumnHolder->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
playControls->SetTag("debug");
playControls->Add(new Spacer(new LinearLayoutParams(1.0f)));
playButton_ = playControls->Add(new Button("", g_Config.bRunBehindPauseMenu ? ImageID("I_PAUSE") : ImageID("I_PLAY"), new LinearLayoutParams(0.0f, G_RIGHT)));
playButton_->OnClick.Add([=](UI::EventParams &e) {
g_Config.bRunBehindPauseMenu = !g_Config.bRunBehindPauseMenu;
playButton_->SetImageID(g_Config.bRunBehindPauseMenu ? ImageID("I_PAUSE") : ImageID("I_PLAY"));
return UI::EVENT_DONE;
});
rightColumnHolder->Add(new Spacer(10.0f));
}
UI::EventReturn GamePauseScreen::OnGameSettings(UI::EventParams &e) {

View File

@ -65,4 +65,6 @@ private:
// hack
bool finishNextFrame_ = false;
PauseScreenMode mode_ = PauseScreenMode::MAIN;
UI::Button *playButton_ = nullptr;
};

View File

@ -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() {

View File

@ -40,7 +40,7 @@ public:
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;

Binary file not shown.

Binary file not shown.

View File

@ -1,9 +1,9 @@
# Note that we do not copy the big font atlas to Android assets. No longer needed!
./ext/native/tools/build/atlastool ui_atlasscript.txt ui 8888 && cp ui_atlas.zim ui_atlas.meta assets && rm ui_atlas.cpp ui_atlas.h
./ext/native/tools/build/atlastool font_atlasscript.txt font 8888 && cp font_atlas.zim font_atlas.meta assets && rm font_atlas.cpp font_atlas.h
./ext/native/tools/build/atlastool asciifont_atlasscript.txt asciifont 8888 && cp asciifont_atlas.zim asciifont_atlas.meta assets && rm asciifont_atlas.cpp asciifont_atlas.h
#./ext/native/tools/build/atlastool font_atlasscript.txt font 8888 && cp font_atlas.zim font_atlas.meta assets && rm font_atlas.cpp font_atlas.h
#./ext/native/tools/build/atlastool asciifont_atlasscript.txt asciifont 8888 && cp asciifont_atlas.zim asciifont_atlas.meta assets && rm asciifont_atlas.cpp asciifont_atlas.h
rm ui_atlas.zim ui_atlas.meta
rm font_atlas.zim font_atlas.meta
rm asciifont_atlas.zim asciifont_atlas.meta
#rm font_atlas.zim font_atlas.meta
#rm asciifont_atlas.zim asciifont_atlas.meta

View File

Before

Width:  |  Height:  |  Size: 396 B

After

Width:  |  Height:  |  Size: 396 B

View File

@ -74,6 +74,7 @@ image I_RETROACHIEVEMENTS_LOGO source_assets/image/retroachievements_logo.png co
image I_CHECKMARK source_assets/image/checkmark.png copy
image I_PLAY source_assets/image/play.png copy
image I_STOP source_assets/image/stop.png copy
image I_PAUSE source_assets/image/pause.png copy
image I_FASTFORWARD source_assets/image/fast_forward.png copy
image I_RECORD source_assets/image/record.png copy
image I_SPEAKER source_assets/image/speaker.png copy