Fix potential crash in reporting screenshot functionality

This commit is contained in:
Henrik Rydgård 2024-09-17 11:24:22 +02:00
parent b1fae3ccda
commit 11210442ce
3 changed files with 22 additions and 11 deletions

View File

@ -185,6 +185,7 @@ ScreenRenderFlags ScreenManager::render() {
Screen *coveringScreen = nullptr;
Screen *foundBackgroundScreen = nullptr;
bool first = true;
do {
--iter;
ScreenRenderRole role = iter->screen->renderRole(first);

View File

@ -160,20 +160,20 @@ void CompatRatingChoice::SetupChoices() {
AddChoice(4, rp->T("Nothing"));
}
ReportScreen::ReportScreen(const Path &gamePath)
: UIDialogScreenWithGameBackground(gamePath) {
ReportScreen::ReportScreen(const Path &gamePath) // unused gamePath, after removing the background
: UIDialogScreen(), gamePath_(gamePath) {
enableReporting_ = Reporting::IsEnabled();
ratingEnabled_ = enableReporting_;
}
ScreenRenderFlags ReportScreen::render(ScreenRenderMode mode) {
ScreenRenderFlags flags = UIScreen::render(mode);
_dbg_assert_(mode & ScreenRenderMode::FIRST);
_dbg_assert_(mode & ScreenRenderMode::TOP);
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_) {
if (!tookScreenshot_ && !g_Config.bSkipBufferEffects) {
Path path = GetSysDirectory(DIRECTORY_SCREENSHOT);
if (!File::Exists(path)) {
File::CreateDir(path);
@ -189,6 +189,11 @@ ScreenRenderFlags ReportScreen::render(ScreenRenderMode mode) {
tookScreenshot_ = true;
}
}
// We take the screenshot first, then we start rendering.
// We are the only screen visible so this avoid starting and then trying to resume a backbuffer render pass.
ScreenRenderFlags flags = UIScreen::render(mode);
return flags;
}
@ -200,12 +205,12 @@ void ReportScreen::update() {
screenshot_->SetVisibility(V_GONE);
}
}
UIDialogScreenWithGameBackground::update();
UIDialogScreen::update();
UpdateCRCInfo();
}
void ReportScreen::resized() {
UIDialogScreenWithGameBackground::resized();
UIDialogScreen::resized();
RecreateViews();
}
@ -407,7 +412,7 @@ EventReturn ReportScreen::HandleShowCRC(EventParams &e) {
}
ReportFinishScreen::ReportFinishScreen(const Path &gamePath, ReportingOverallScore score)
: UIDialogScreenWithGameBackground(gamePath), score_(score) {
: UIDialogScreen(), gamePath_(gamePath), score_(score) {
}
void ReportFinishScreen::CreateViews() {
@ -468,7 +473,7 @@ void ReportFinishScreen::update() {
}
}
UIDialogScreenWithGameBackground::update();
UIDialogScreen::update();
}
void ReportFinishScreen::ShowSuggestions() {

View File

@ -33,12 +33,15 @@ enum class ReportingOverallScore : int {
INVALID = -1,
};
class ReportScreen : public UIDialogScreenWithGameBackground {
class ReportScreen : public UIDialogScreen {
public:
ReportScreen(const Path &gamePath);
const char *tag() const override { return "Report"; }
// For the screenshotting functionality to work.
ScreenRenderRole renderRole(bool isTop) const override { return ScreenRenderRole::MUST_BE_FIRST | ScreenRenderRole::CAN_BE_BACKGROUND; }
protected:
ScreenRenderFlags render(ScreenRenderMode mode) override;
void update() override;
@ -60,6 +63,7 @@ protected:
UI::TextView *overallDescription_ = nullptr;
UI::TextView *crcInfo_ = nullptr;
UI::Choice *showCrcButton_ = nullptr;
Path gamePath_;
Path screenshotFilename_;
ReportingOverallScore overall_ = ReportingOverallScore::INVALID;
@ -73,7 +77,7 @@ protected:
bool showCRC_ = false;
};
class ReportFinishScreen : public UIDialogScreenWithGameBackground {
class ReportFinishScreen : public UIDialogScreen {
public:
ReportFinishScreen(const Path &gamePath, ReportingOverallScore score);
@ -88,6 +92,7 @@ protected:
UI::TextView *resultNotice_ = nullptr;
UI::LinearLayout *resultItems_ = nullptr;
Path gamePath_;
ReportingOverallScore score_;
bool setStatus_ = false;
};