mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Remove preRender/postRender methods from screens, in favor of a mode parameter.
This commit is contained in:
parent
22295a6412
commit
0ff0ad9140
8 changed files with 122 additions and 129 deletions
|
@ -155,52 +155,48 @@ void ScreenManager::resized() {
|
|||
|
||||
void ScreenManager::render() {
|
||||
if (!stack_.empty()) {
|
||||
switch (stack_.back().flags) {
|
||||
case LAYER_TRANSPARENT:
|
||||
if (stack_.size() == 1) {
|
||||
ERROR_LOG(SYSTEM, "Can't have sidemenu over nothing");
|
||||
break;
|
||||
} else {
|
||||
auto last = stack_.end();
|
||||
auto iter = last;
|
||||
iter--;
|
||||
while (iter->flags == LAYER_TRANSPARENT) {
|
||||
iter--;
|
||||
}
|
||||
auto first = iter;
|
||||
_assert_(iter->screen);
|
||||
// Collect the screens to render
|
||||
TinySet<Screen *, 6> layers;
|
||||
|
||||
// TODO: Make really sure that this "mismatched" pre/post only happens
|
||||
// when screens are "compatible" (both are UIScreens, for example).
|
||||
first->screen->preRender();
|
||||
while (iter < last) {
|
||||
iter->screen->render(ScreenRenderMode::TOP);
|
||||
iter++;
|
||||
}
|
||||
stack_.back().screen->render(ScreenRenderMode::TOP);
|
||||
if (overlayScreen_) {
|
||||
overlayScreen_->render(ScreenRenderMode::TOP);
|
||||
}
|
||||
if (postRenderCb_) {
|
||||
// Really can't render anything after this! Will crash the screenshot mechanism if we do.
|
||||
postRenderCb_(getUIContext(), postRenderUserdata_);
|
||||
}
|
||||
first->screen->postRender();
|
||||
break;
|
||||
// Start at the end, collect screens to form the transparency stack.
|
||||
// Then we'll iterate them in reverse order.
|
||||
// Note that we skip the overlay screen, we handle it separately.
|
||||
|
||||
bool foundCoveringScreen = false; // Note, can be separate from background screen!
|
||||
auto iter = stack_.end();
|
||||
do {
|
||||
--iter;
|
||||
if (!foundCoveringScreen) {
|
||||
layers.push_back(iter->screen);
|
||||
}
|
||||
default:
|
||||
_assert_(stack_.back().screen);
|
||||
stack_.back().screen->preRender();
|
||||
stack_.back().screen->render(ScreenRenderMode::TOP);
|
||||
if (overlayScreen_) {
|
||||
overlayScreen_->render(ScreenRenderMode::TOP);
|
||||
if (iter->flags != LAYER_TRANSPARENT) {
|
||||
foundCoveringScreen = true;
|
||||
}
|
||||
if (postRenderCb_) {
|
||||
// Really can't render anything after this! Will crash the screenshot mechanism if we do.
|
||||
postRenderCb_(getUIContext(), postRenderUserdata_);
|
||||
} while (iter != stack_.begin());
|
||||
|
||||
// OK, now we iterate backwards over our little pile of 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;
|
||||
} else if (i == 0) {
|
||||
mode = ScreenRenderMode::TOP;
|
||||
} else {
|
||||
mode = ScreenRenderMode::BEHIND;
|
||||
}
|
||||
stack_.back().screen->postRender();
|
||||
break;
|
||||
layers[i]->render(mode);
|
||||
}
|
||||
|
||||
if (overlayScreen_) {
|
||||
// It doesn't care about mode.
|
||||
overlayScreen_->render(ScreenRenderMode::TOP);
|
||||
}
|
||||
|
||||
if (postRenderCb_) {
|
||||
// Really can't render anything after this! Will crash the screenshot mechanism if we do.
|
||||
postRenderCb_(getUIContext(), postRenderUserdata_);
|
||||
}
|
||||
} else {
|
||||
ERROR_LOG(SYSTEM, "No current screen!");
|
||||
|
|
|
@ -48,6 +48,7 @@ enum class ScreenFocusChange {
|
|||
};
|
||||
|
||||
enum class ScreenRenderMode {
|
||||
DEFAULT = 0,
|
||||
FIRST = 1,
|
||||
BACKGROUND = 2,
|
||||
BEHIND = 4,
|
||||
|
@ -64,9 +65,7 @@ public:
|
|||
|
||||
virtual void onFinish(DialogResult reason) {}
|
||||
virtual void update() {}
|
||||
virtual void preRender() {}
|
||||
virtual void render(ScreenRenderMode mode) {}
|
||||
virtual void postRender() {}
|
||||
virtual void resized() {}
|
||||
virtual void dialogFinished(const Screen *dialog, DialogResult result) {}
|
||||
virtual void sendMessage(UIMessage message, const char *value) {}
|
||||
|
|
|
@ -193,30 +193,26 @@ void UIScreen::deviceRestored() {
|
|||
root_->DeviceRestored(screenManager()->getDrawContext());
|
||||
}
|
||||
|
||||
void UIScreen::preRender() {
|
||||
using namespace Draw;
|
||||
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
||||
_dbg_assert_(draw != nullptr);
|
||||
// Bind and clear the back buffer
|
||||
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, 0xFF000000 }, "UI");
|
||||
screenManager()->getUIContext()->BeginFrame();
|
||||
|
||||
Draw::Viewport viewport;
|
||||
viewport.TopLeftX = 0;
|
||||
viewport.TopLeftY = 0;
|
||||
viewport.Width = g_display.pixel_xres;
|
||||
viewport.Height = g_display.pixel_yres;
|
||||
viewport.MaxDepth = 1.0;
|
||||
viewport.MinDepth = 0.0;
|
||||
draw->SetViewport(viewport);
|
||||
draw->SetTargetSize(g_display.pixel_xres, g_display.pixel_yres);
|
||||
}
|
||||
|
||||
void UIScreen::postRender() {
|
||||
screenManager()->getUIContext()->Flush();
|
||||
}
|
||||
|
||||
void UIScreen::render(ScreenRenderMode mode) {
|
||||
if (mode & ScreenRenderMode::FIRST) {
|
||||
using namespace Draw;
|
||||
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
||||
_dbg_assert_(draw != nullptr);
|
||||
// Bind and clear the back buffer
|
||||
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, 0xFF000000 }, "UI");
|
||||
screenManager()->getUIContext()->BeginFrame();
|
||||
|
||||
Draw::Viewport viewport;
|
||||
viewport.TopLeftX = 0;
|
||||
viewport.TopLeftY = 0;
|
||||
viewport.Width = g_display.pixel_xres;
|
||||
viewport.Height = g_display.pixel_yres;
|
||||
viewport.MaxDepth = 1.0;
|
||||
viewport.MinDepth = 0.0;
|
||||
draw->SetViewport(viewport);
|
||||
draw->SetTargetSize(g_display.pixel_xres, g_display.pixel_yres);
|
||||
}
|
||||
|
||||
DoRecreateViews();
|
||||
|
||||
if (root_) {
|
||||
|
@ -235,6 +231,10 @@ void UIScreen::render(ScreenRenderMode mode) {
|
|||
|
||||
uiContext->PopTransform();
|
||||
}
|
||||
|
||||
if (mode & ScreenRenderMode::TOP) {
|
||||
screenManager()->getUIContext()->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
TouchInput UIScreen::transformTouch(const TouchInput &touch) {
|
||||
|
|
|
@ -36,9 +36,7 @@ public:
|
|||
~UIScreen();
|
||||
|
||||
void update() override;
|
||||
void preRender() override;
|
||||
void render(ScreenRenderMode mode) override;
|
||||
void postRender() override;
|
||||
void deviceLost() override;
|
||||
void deviceRestored() override;
|
||||
|
||||
|
|
|
@ -1409,45 +1409,39 @@ static void DrawFPS(UIContext *ctx, const Bounds &bounds) {
|
|||
ctx->RebindTexture();
|
||||
}
|
||||
|
||||
void EmuScreen::preRender() {
|
||||
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
|
||||
// targets is a mortal sin so it's very important that we don't bind the backbuffer unnecessarily here.
|
||||
// We only bind it in FramebufferManager::CopyDisplayToOutput (unless non-buffered)...
|
||||
// We do, however, start the frame in other ways.
|
||||
|
||||
if ((g_Config.bSkipBufferEffects && !g_Config.bSoftwareRendering) || Core_IsStepping()) {
|
||||
// We need to clear here already so that drawing during the frame is done on a clean slate.
|
||||
if (Core_IsStepping() && gpuStats.numFlips != 0) {
|
||||
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::KEEP, RPAction::DONT_CARE, RPAction::DONT_CARE }, "EmuScreen_BackBuffer");
|
||||
} else {
|
||||
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, 0xFF000000 }, "EmuScreen_BackBuffer");
|
||||
}
|
||||
|
||||
Viewport viewport;
|
||||
viewport.TopLeftX = 0;
|
||||
viewport.TopLeftY = 0;
|
||||
viewport.Width = g_display.pixel_xres;
|
||||
viewport.Height = g_display.pixel_yres;
|
||||
viewport.MaxDepth = 1.0;
|
||||
viewport.MinDepth = 0.0;
|
||||
draw->SetViewport(viewport);
|
||||
}
|
||||
draw->SetTargetSize(g_display.pixel_xres, g_display.pixel_yres);
|
||||
}
|
||||
|
||||
void EmuScreen::postRender() {
|
||||
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
||||
if (!draw)
|
||||
return;
|
||||
if (stopRender_)
|
||||
draw->WipeQueue();
|
||||
}
|
||||
|
||||
void EmuScreen::render(ScreenRenderMode mode) {
|
||||
if (mode == ScreenRenderMode::FIRST) {
|
||||
// Actually, always gonna be first (?)
|
||||
|
||||
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
|
||||
// targets is a mortal sin so it's very important that we don't bind the backbuffer unnecessarily here.
|
||||
// We only bind it in FramebufferManager::CopyDisplayToOutput (unless non-buffered)...
|
||||
// We do, however, start the frame in other ways.
|
||||
|
||||
if ((g_Config.bSkipBufferEffects && !g_Config.bSoftwareRendering) || Core_IsStepping()) {
|
||||
// We need to clear here already so that drawing during the frame is done on a clean slate.
|
||||
if (Core_IsStepping() && gpuStats.numFlips != 0) {
|
||||
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::KEEP, RPAction::DONT_CARE, RPAction::DONT_CARE }, "EmuScreen_BackBuffer");
|
||||
} else {
|
||||
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, 0xFF000000 }, "EmuScreen_BackBuffer");
|
||||
}
|
||||
|
||||
Viewport viewport;
|
||||
viewport.TopLeftX = 0;
|
||||
viewport.TopLeftY = 0;
|
||||
viewport.Width = g_display.pixel_xres;
|
||||
viewport.Height = g_display.pixel_yres;
|
||||
viewport.MaxDepth = 1.0;
|
||||
viewport.MinDepth = 0.0;
|
||||
draw->SetViewport(viewport);
|
||||
}
|
||||
draw->SetTargetSize(g_display.pixel_xres, g_display.pixel_yres);
|
||||
}
|
||||
|
||||
using namespace Draw;
|
||||
|
||||
DrawContext *thin3d = screenManager()->getDrawContext();
|
||||
|
@ -1552,6 +1546,11 @@ void EmuScreen::render(ScreenRenderMode mode) {
|
|||
} else {
|
||||
SetVRAppMode(screenManager()->topScreen() == this ? VRAppMode::VR_GAME_MODE : VRAppMode::VR_DIALOG_MODE);
|
||||
}
|
||||
|
||||
if (mode & ScreenRenderMode::TOP) {
|
||||
if (stopRender_)
|
||||
thin3d->WipeQueue();
|
||||
}
|
||||
}
|
||||
|
||||
bool EmuScreen::hasVisibleUI() {
|
||||
|
|
|
@ -43,8 +43,6 @@ public:
|
|||
|
||||
void update() override;
|
||||
void render(ScreenRenderMode mode) override;
|
||||
void preRender() override;
|
||||
void postRender() override;
|
||||
void dialogFinished(const Screen *dialog, DialogResult result) override;
|
||||
void sendMessage(UIMessage message, const char *value) override;
|
||||
void resized() override;
|
||||
|
|
|
@ -166,26 +166,29 @@ ReportScreen::ReportScreen(const Path &gamePath)
|
|||
ratingEnabled_ = enableReporting_;
|
||||
}
|
||||
|
||||
void ReportScreen::postRender() {
|
||||
// We do this after render because we need it to be within the frame (so the screenshot works).
|
||||
// We could do it mid frame, but then we have to reapply viewport/scissor.
|
||||
if (!tookScreenshot_) {
|
||||
Path path = GetSysDirectory(DIRECTORY_SCREENSHOT);
|
||||
if (!File::Exists(path)) {
|
||||
File::CreateDir(path);
|
||||
}
|
||||
screenshotFilename_ = path / ".reporting.jpg";
|
||||
if (TakeGameScreenshot(screenshotFilename_, ScreenshotFormat::JPG, SCREENSHOT_DISPLAY, nullptr, nullptr, 4)) {
|
||||
// Redo the views already, now with a screenshot included.
|
||||
RecreateViews();
|
||||
} else {
|
||||
// Good news (?), the views are good as-is without a screenshot.
|
||||
screenshotFilename_.clear();
|
||||
}
|
||||
tookScreenshot_ = true;
|
||||
}
|
||||
void ReportScreen::render(ScreenRenderMode mode) {
|
||||
UIScreen::render(mode);
|
||||
|
||||
UIDialogScreenWithGameBackground::postRender();
|
||||
if (mode & ScreenRenderMode::TOP) {
|
||||
|
||||
// We do this after render because we need it to be within the frame (so the screenshot works).
|
||||
// We could do it mid frame, but then we have to reapply viewport/scissor.
|
||||
if (!tookScreenshot_) {
|
||||
Path path = GetSysDirectory(DIRECTORY_SCREENSHOT);
|
||||
if (!File::Exists(path)) {
|
||||
File::CreateDir(path);
|
||||
}
|
||||
screenshotFilename_ = path / ".reporting.jpg";
|
||||
if (TakeGameScreenshot(screenshotFilename_, ScreenshotFormat::JPG, SCREENSHOT_DISPLAY, nullptr, nullptr, 4)) {
|
||||
// Redo the views already, now with a screenshot included.
|
||||
RecreateViews();
|
||||
} else {
|
||||
// Good news (?), the views are good as-is without a screenshot.
|
||||
screenshotFilename_.clear();
|
||||
}
|
||||
tookScreenshot_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReportScreen::update() {
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
const char *tag() const override { return "Report"; }
|
||||
|
||||
protected:
|
||||
void postRender() override;
|
||||
void render(ScreenRenderMode mode) override;
|
||||
void update() override;
|
||||
void resized() override;
|
||||
void CreateViews() override;
|
||||
|
|
Loading…
Add table
Reference in a new issue