diff --git a/Common/UI/TabHolder.cpp b/Common/UI/TabHolder.cpp index 2e39b588e9..4bab2c019a 100644 --- a/Common/UI/TabHolder.cpp +++ b/Common/UI/TabHolder.cpp @@ -209,7 +209,10 @@ bool TabHolder::SetCurrentTab(int tab, bool skipTween) { tabs_[tab]->SetVisibility(V_VISIBLE); currentTab_ = tab; - + UI::EventParams e{}; + e.v = this; + e.a = currentTab_; + OnChangeTab.Trigger(e); return created; } diff --git a/Common/UI/TabHolder.h b/Common/UI/TabHolder.h index f88f2946eb..a4ca99ccbd 100644 --- a/Common/UI/TabHolder.h +++ b/Common/UI/TabHolder.h @@ -52,6 +52,8 @@ public: } bool EnsureTab(int index); // return true if it actually created a tab. + Event OnChangeTab; + private: void AddTabContents(std::string_view title, ImageID imageId, ViewGroup *tabContents); void OnTabClick(EventParams &e); diff --git a/Core/Screenshot.cpp b/Core/Screenshot.cpp index 4396f4902a..a037a31740 100644 --- a/Core/Screenshot.cpp +++ b/Core/Screenshot.cpp @@ -394,6 +394,10 @@ bool ScreenshotNotifyPostGameRender(Draw::DrawContext *draw) { if (buf.IsBackBuffer()) { w = buf.GetStride(); h = buf.GetHeight(); + } else if (maxRes < 0 && buf.GetScaleFactor() > 0) { + // Normal case. Crop to the current screen size if it's larger (some games render to large buffers and display a subset). + w = 480 * buf.GetScaleFactor(); + h = 272 * buf.GetScaleFactor(); } else { w = maxRes > 0 ? 480 * maxRes : buf.GetStride(); h = maxRes > 0 ? 272 * maxRes : buf.GetHeight(); @@ -491,7 +495,7 @@ bool Save8888RGBAScreenshot(std::vector &bufferPNG, const u8 *bufferRGB return success; } -void TakeUserScreenshotImpl() { +void TakeUserScreenshot() { Path path = GetSysDirectory(DIRECTORY_SCREENSHOT); // Make sure the screenshot directory exists. File::CreateDir(path); @@ -553,9 +557,3 @@ void TakeUserScreenshotImpl() { // TODO: What to do about ScreenshotNotPossible? }); } - -void TakeUserScreenshot() { - System_RunOnMainThread([]() { - TakeUserScreenshotImpl(); - }); -} diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 30481af93b..18bc85c092 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -3043,6 +3043,7 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB return false; // If there's no vfb and we're drawing there, must be memory? buffer = GPUDebugBuffer(Memory::GetPointerWriteUnchecked(fb_address), fb_stride, 512, format); + buffer.SetScaleFactor(1); return true; } @@ -3083,6 +3084,7 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB buffer.Allocate(w, h, GE_FORMAT_8888, flipY); bool retval = draw_->CopyFramebufferToMemory(bound, Draw::Aspect::COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetFramebuffer"); + buffer.SetScaleFactor(vfb->renderScaleFactor); // Don't need to increment gpu stats for readback count here, this is a debugger-only function. // After a readback we'll have flushed and started over, need to dirty a bunch of things to be safe. @@ -3103,6 +3105,7 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32 return false; // If there's no vfb and we're drawing there, must be memory? buffer = GPUDebugBuffer(Memory::GetPointerWriteUnchecked(z_address), z_stride, 512, GPU_DBG_FORMAT_16BIT); + buffer.SetScaleFactor(1); return true; } @@ -3134,6 +3137,7 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32 gstate_c.Dirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); // That may have unbound the framebuffer, rebind to avoid crashes when debugging. RebindFramebuffer("RebindFramebuffer - GetDepthbuffer"); + buffer.SetScaleFactor(vfb->renderScaleFactor); return retval; } diff --git a/GPU/Common/GPUDebugInterface.h b/GPU/Common/GPUDebugInterface.h index 00b4488425..a76db41bf5 100644 --- a/GPU/Common/GPUDebugInterface.h +++ b/GPU/Common/GPUDebugInterface.h @@ -123,6 +123,7 @@ struct GPUDebugBuffer { stride_ = other.stride_; flipped_ = other.flipped_; isBackBuffer_ = other.isBackBuffer_; + scaleFactor_ = other.scaleFactor_; fmt_ = other.fmt_; other.alloc_ = false; other.data_ = nullptr; @@ -142,6 +143,7 @@ struct GPUDebugBuffer { flipped_ = other.flipped_; fmt_ = other.fmt_; isBackBuffer_ = other.isBackBuffer_; + scaleFactor_ = other.scaleFactor_; other.alloc_ = false; other.data_ = nullptr; } @@ -186,6 +188,8 @@ struct GPUDebugBuffer { void SetIsBackbuffer(bool isBackBuffer) { isBackBuffer_ = isBackBuffer; } bool IsBackBuffer() const { return isBackBuffer_; } + void SetScaleFactor(int scaleFactor) { scaleFactor_ = scaleFactor; } + int GetScaleFactor() const { return scaleFactor_; } private: bool alloc_ = false; @@ -195,6 +199,7 @@ private: GPUDebugBufferFormat fmt_ = GPU_DBG_FORMAT_INVALID; bool flipped_ = false; bool isBackBuffer_ = false; + int scaleFactor_ = 0; }; struct GPUDebugVertex { diff --git a/UI/TabbedDialogScreen.cpp b/UI/TabbedDialogScreen.cpp index 03e4f93a64..c56f81caa7 100644 --- a/UI/TabbedDialogScreen.cpp +++ b/UI/TabbedDialogScreen.cpp @@ -13,6 +13,9 @@ #include "Common/UI/Context.h" #include "UI/TabbedDialogScreen.h" +UITabbedBaseDialogScreen::UITabbedBaseDialogScreen(const Path &gamePath, int *currentTabSetting, TabDialogFlags flags) + : UIBaseDialogScreen(gamePath), currentTabSetting_(currentTabSetting), flags_(flags) {} + void UITabbedBaseDialogScreen::AddTab(const char *tag, std::string_view title, ImageID imageId, std::function createCallback, TabFlags flags) { using namespace UI; @@ -106,6 +109,12 @@ void UITabbedBaseDialogScreen::CreateViews() { } tabHolder_->EnsureTab(tabHolder_->GetCurrentTab()); + tabHolder_->OnChangeTab.Add([this](UI::EventParams &e) { + if (currentTabSetting_) { + *currentTabSetting_ = e.a; + } + }); + if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD) || System_GetPropertyBool(SYSPROP_HAS_TEXT_INPUT_DIALOG)) { // Hide search if screen is too small. int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE); @@ -137,12 +146,6 @@ void UITabbedBaseDialogScreen::CreateViews() { } } -UITabbedBaseDialogScreen::~UITabbedBaseDialogScreen() { - if (currentTabSetting_) { - *currentTabSetting_ = GetCurrentTab(); - } -} - void UITabbedBaseDialogScreen::sendMessage(UIMessage message, const char *value) { UIBaseDialogScreen::sendMessage(message, value); if (message == UIMessage::GAMESETTINGS_SEARCH) { diff --git a/UI/TabbedDialogScreen.h b/UI/TabbedDialogScreen.h index 423f1dfc7a..0e02f067d0 100644 --- a/UI/TabbedDialogScreen.h +++ b/UI/TabbedDialogScreen.h @@ -31,8 +31,7 @@ ENUM_CLASS_BITOPS(TabFlags); class UITabbedBaseDialogScreen : public UIBaseDialogScreen { public: // currentTabSetting can be null if you don't want to persist the current tab. - UITabbedBaseDialogScreen(const Path &gamePath, int *currentTabSetting = nullptr, TabDialogFlags flags = TabDialogFlags::Default) : UIBaseDialogScreen(gamePath), currentTabSetting_(currentTabSetting), flags_(flags) {} - ~UITabbedBaseDialogScreen() override; + UITabbedBaseDialogScreen(const Path &gamePath, int *currentTabSetting = nullptr, TabDialogFlags flags = TabDialogFlags::Default); void AddTab(const char *tag, std::string_view title, ImageID imageId, std::function createCallback, TabFlags flags = TabFlags::Default); void AddTab(const char *tag, std::string_view title, std::function createCallback, TabFlags flags = TabFlags::Default) { AddTab(tag, title, ImageID::invalid(), createCallback, flags);