From d21fef52aed17130ec56fbab05aa45aa09861f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 May 2024 21:01:03 +0200 Subject: [PATCH] Allow taking screenshots in the app menu --- Core/SaveState.cpp | 2 +- Core/Screenshot.cpp | 17 ++++++++++------- Core/Screenshot.h | 5 ++++- GPU/Common/FramebufferManagerCommon.cpp | 17 ++++++++++++----- GPU/Common/FramebufferManagerCommon.h | 3 +++ UI/NativeApp.cpp | 6 +++--- UI/ReportScreen.cpp | 2 +- Windows/MainWindowMenu.cpp | 1 - 8 files changed, 34 insertions(+), 19 deletions(-) diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 771785fd9829..fb42b68bdcd3 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -1056,7 +1056,7 @@ namespace SaveState case SAVESTATE_SAVE_SCREENSHOT: { int maxResMultiplier = 2; - tempResult = TakeGameScreenshot(op.filename, ScreenshotFormat::JPG, SCREENSHOT_DISPLAY, nullptr, nullptr, maxResMultiplier); + tempResult = TakeGameScreenshot(nullptr, op.filename, ScreenshotFormat::JPG, SCREENSHOT_DISPLAY, nullptr, nullptr, maxResMultiplier); callbackResult = tempResult ? Status::SUCCESS : Status::FAILURE; if (!tempResult) { ERROR_LOG(SAVESTATE, "Failed to take a screenshot for the savestate! %s", op.filename.c_str()); diff --git a/Core/Screenshot.cpp b/Core/Screenshot.cpp index a1bbaaafc8cf..9c267204a9cc 100644 --- a/Core/Screenshot.cpp +++ b/Core/Screenshot.cpp @@ -30,6 +30,7 @@ #include "Core/Screenshot.h" #include "Core/Core.h" #include "GPU/Common/GPUDebugInterface.h" +#include "GPU/Common/FramebufferManagerCommon.h" #include "GPU/GPUInterface.h" #include "GPU/GPUState.h" @@ -328,28 +329,30 @@ static GPUDebugBuffer ApplyRotation(const GPUDebugBuffer &buf, DisplayRotation r return rotated; } -bool TakeGameScreenshot(const Path &filename, ScreenshotFormat fmt, ScreenshotType type, int *width, int *height, int maxRes) { - if (!gpuDebug) { - ERROR_LOG(SYSTEM, "Can't take screenshots when GPU not running"); - return false; - } +bool TakeGameScreenshot(Draw::DrawContext *draw, const Path &filename, ScreenshotFormat fmt, ScreenshotType type, int *width, int *height, int maxRes) { GPUDebugBuffer buf; bool success = false; u32 w = (u32)-1; u32 h = (u32)-1; if (type == SCREENSHOT_DISPLAY || type == SCREENSHOT_RENDER) { + if (!gpuDebug) { + ERROR_LOG(SYSTEM, "Can't take screenshots when GPU not running"); + return false; + } success = gpuDebug->GetCurrentFramebuffer(buf, type == SCREENSHOT_RENDER ? GPU_DBG_FRAMEBUF_RENDER : GPU_DBG_FRAMEBUF_DISPLAY, maxRes); w = maxRes > 0 ? 480 * maxRes : PSP_CoreParameter().renderWidth; h = maxRes > 0 ? 272 * maxRes : PSP_CoreParameter().renderHeight; } else if (g_display.rotation != DisplayRotation::ROTATE_0) { + _dbg_assert_(draw); GPUDebugBuffer temp; - success = gpuDebug->GetOutputFramebuffer(temp); + success = ::GetOutputFramebuffer(draw, buf); if (success) { buf = ApplyRotation(temp, g_display.rotation); } } else { - success = gpuDebug->GetOutputFramebuffer(buf); + _dbg_assert_(draw); + success = ::GetOutputFramebuffer(draw, buf); } if (!success) { diff --git a/Core/Screenshot.h b/Core/Screenshot.h index ac124fef9a01..69794bb6de44 100644 --- a/Core/Screenshot.h +++ b/Core/Screenshot.h @@ -20,6 +20,9 @@ #include "Common/File/Path.h" struct GPUDebugBuffer; +namespace Draw { +class DrawContext; +} enum class ScreenshotFormat { PNG, @@ -38,7 +41,7 @@ enum ScreenshotType { const u8 *ConvertBufferToScreenshot(const GPUDebugBuffer &buf, bool alpha, u8 *&temp, u32 &w, u32 &h); // Can only be used while in game. -bool TakeGameScreenshot(const Path &filename, ScreenshotFormat fmt, ScreenshotType type, int *width = nullptr, int *height = nullptr, int maxRes = -1); +bool TakeGameScreenshot(Draw::DrawContext *draw, const Path &filename, ScreenshotFormat fmt, ScreenshotType type, int *width = nullptr, int *height = nullptr, int maxRes = -1); bool Save888RGBScreenshot(const Path &filename, ScreenshotFormat fmt, const u8 *bufferRGB888, int w, int h); bool Save8888RGBAScreenshot(const Path &filename, const u8 *bufferRGBA8888, int w, int h); diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index c4fbffd5493b..df309de01fb7 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -3076,15 +3076,22 @@ bool FramebufferManagerCommon::GetStencilbuffer(u32 fb_address, int fb_stride, G return retval; } -bool FramebufferManagerCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) { +bool GetOutputFramebuffer(Draw::DrawContext *draw, GPUDebugBuffer &buffer) { int w, h; - draw_->GetFramebufferDimensions(nullptr, &w, &h); - Draw::DataFormat fmt = draw_->PreferredFramebufferReadbackFormat(nullptr); + draw->GetFramebufferDimensions(nullptr, &w, &h); + Draw::DataFormat fmt = draw->PreferredFramebufferReadbackFormat(nullptr); // Ignore preferred formats other than BGRA. if (fmt != Draw::DataFormat::B8G8R8A8_UNORM) fmt = Draw::DataFormat::R8G8B8A8_UNORM; - buffer.Allocate(w, h, fmt == Draw::DataFormat::R8G8B8A8_UNORM ? GPU_DBG_FORMAT_8888 : GPU_DBG_FORMAT_8888_BGRA, false); - bool retval = draw_->CopyFramebufferToMemory(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, fmt, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetOutputFramebuffer"); + + bool flipped = g_Config.iGPUBackend == (int)GPUBackend::OPENGL; + + buffer.Allocate(w, h, fmt == Draw::DataFormat::R8G8B8A8_UNORM ? GPU_DBG_FORMAT_8888 : GPU_DBG_FORMAT_8888_BGRA, flipped); + return draw->CopyFramebufferToMemory(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, fmt, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetOutputFramebuffer"); +} + +bool FramebufferManagerCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) { + bool retval = ::GetOutputFramebuffer(draw_, buffer); // That may have unbound the framebuffer, rebind to avoid crashes when debugging. RebindFramebuffer("RebindFramebuffer - GetOutputFramebuffer"); return retval; diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 99c45295b0c1..994727dcfcff 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -647,3 +647,6 @@ class FramebufferManagerCommon { u8 *convBuf_ = nullptr; u32 convBufSize_ = 0; }; + +// Should probably live elsewhere. +bool GetOutputFramebuffer(Draw::DrawContext *draw, GPUDebugBuffer &buffer); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 3f022572c158..b1cefec60499 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -968,7 +968,7 @@ void NativeShutdownGraphics() { INFO_LOG(SYSTEM, "NativeShutdownGraphics done"); } -static void TakeScreenshot() { +static void TakeScreenshot(Draw::DrawContext *draw) { Path path = GetSysDirectory(DIRECTORY_SCREENSHOT); if (!File::Exists(path)) { File::CreateDir(path); @@ -991,7 +991,7 @@ static void TakeScreenshot() { i++; } - bool success = TakeGameScreenshot(filename, g_Config.bScreenshotsAsPNG ? ScreenshotFormat::PNG : ScreenshotFormat::JPG, SCREENSHOT_OUTPUT); + bool success = TakeGameScreenshot(draw, filename, g_Config.bScreenshotsAsPNG ? ScreenshotFormat::PNG : ScreenshotFormat::JPG, SCREENSHOT_OUTPUT); if (success) { g_OSD.Show(OSDType::MESSAGE_FILE_LINK, filename.ToString(), 0.0f, "screenshot_link"); if (System_GetPropertyBool(SYSPROP_CAN_SHOW_FILE)) { @@ -1012,7 +1012,7 @@ static void TakeScreenshot() { void CallbackPostRender(UIContext *dc, void *userdata) { if (g_TakeScreenshot) { - TakeScreenshot(); + TakeScreenshot(dc->GetDrawContext()); g_TakeScreenshot = false; } } diff --git a/UI/ReportScreen.cpp b/UI/ReportScreen.cpp index 361540bce76c..3701db3d6359 100644 --- a/UI/ReportScreen.cpp +++ b/UI/ReportScreen.cpp @@ -179,7 +179,7 @@ ScreenRenderFlags ReportScreen::render(ScreenRenderMode mode) { File::CreateDir(path); } screenshotFilename_ = path / ".reporting.jpg"; - if (TakeGameScreenshot(screenshotFilename_, ScreenshotFormat::JPG, SCREENSHOT_DISPLAY, nullptr, nullptr, 4)) { + if (TakeGameScreenshot(screenManager()->getDrawContext(), screenshotFilename_, ScreenshotFormat::JPG, SCREENSHOT_DISPLAY, nullptr, nullptr, 4)) { // Redo the views already, now with a screenshot included. RecreateViews(); } else { diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index af6a81f5c517..4a195cda3060 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -107,7 +107,6 @@ namespace MainWindow { EnableMenuItem(menu, ID_DEBUG_LOADSYMFILE, menuEnable); EnableMenuItem(menu, ID_DEBUG_SAVESYMFILE, menuEnable); EnableMenuItem(menu, ID_DEBUG_RESETSYMBOLTABLE, menuEnable); - EnableMenuItem(menu, ID_DEBUG_TAKESCREENSHOT, menuEnable); EnableMenuItem(menu, ID_DEBUG_SHOWDEBUGSTATISTICS, menuInGameEnable); EnableMenuItem(menu, ID_DEBUG_EXTRACTFILE, menuEnable); EnableMenuItem(menu, ID_DEBUG_MEMORYBASE, menuInGameEnable);