diff --git a/Core/AVIDump.cpp b/Core/AVIDump.cpp index a9822224f..834a622ba 100644 --- a/Core/AVIDump.cpp +++ b/Core/AVIDump.cpp @@ -142,7 +142,7 @@ static void PreparePacket(AVPacket* pkt) void AVIDump::AddFrame() { - gpuDebug->GetCurrentFramebuffer(buf); + gpuDebug->GetCurrentFramebuffer(buf, GPU_DBG_FRAMEBUF_DISPLAY); u32 w = buf.GetStride(); u32 h = buf.GetHeight(); CheckResolution(w, h); diff --git a/Core/Screenshot.cpp b/Core/Screenshot.cpp index 35cd517c9..c512832e5 100644 --- a/Core/Screenshot.cpp +++ b/Core/Screenshot.cpp @@ -223,7 +223,7 @@ bool TakeGameScreenshot(const char *filename, ScreenshotFormat fmt, ScreenshotTy if (type == SCREENSHOT_RENDER) { if (gpuDebug) { - success = gpuDebug->GetCurrentFramebuffer(buf, maxRes); + success = gpuDebug->GetCurrentFramebuffer(buf, GPU_DBG_FRAMEBUF_DISPLAY, maxRes); } // Only crop to the top left when using a render screenshot. diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 7fa99ff9d..c3c5069df 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -191,6 +191,13 @@ public: return displayFramebuf_ ? (0x04000000 | displayFramebuf_->fb_address) : 0; } + u32 DisplayFramebufStride() { + return displayFramebuf_ ? displayStride_ : 0; + } + GEBufferFormat DisplayFramebufFormat() { + return displayFramebuf_ ? displayFormat_ : GE_FORMAT_INVALID; + } + bool MayIntersectFramebuffer(u32 start) { // Clear the cache/kernel bits. start = start & 0x3FFFFFFF; diff --git a/GPU/Common/GPUDebugInterface.h b/GPU/Common/GPUDebugInterface.h index d1fc39c5a..9997437f2 100644 --- a/GPU/Common/GPUDebugInterface.h +++ b/GPU/Common/GPUDebugInterface.h @@ -66,6 +66,13 @@ enum GPUDebugBufferFormat { GPU_DBG_FORMAT_888_RGB = 0x20, }; +enum GPUDebugFramebufferType { + // The current render target. + GPU_DBG_FRAMEBUF_RENDER, + // The current display target (not the displayed screen, though.) + GPU_DBG_FRAMEBUF_DISPLAY, +}; + inline GPUDebugBufferFormat &operator |=(GPUDebugBufferFormat &lhs, const GPUDebugBufferFormat &rhs) { lhs = GPUDebugBufferFormat((int)lhs | (int)rhs); return lhs; @@ -206,7 +213,7 @@ public: // Needs to be called from the GPU thread, so on the same thread as a notification is fine. // Calling from a separate thread (e.g. UI) may fail. - virtual bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes = -1) { + virtual bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes = -1) { // False means unsupported. return false; } diff --git a/GPU/Debugger/Stepping.cpp b/GPU/Debugger/Stepping.cpp index 312bb6b55..d2407b880 100644 --- a/GPU/Debugger/Stepping.cpp +++ b/GPU/Debugger/Stepping.cpp @@ -49,6 +49,7 @@ static volatile bool actionComplete; // Below are values used to perform actions that return results. static bool bufferResult; +static GPUDebugFramebufferType bufferType = GPU_DBG_FRAMEBUF_RENDER; static GPUDebugBuffer bufferFrame; static GPUDebugBuffer bufferDepth; static GPUDebugBuffer bufferStencil; @@ -84,7 +85,7 @@ static void RunPauseAction() { break; case PAUSE_GETFRAMEBUF: - bufferResult = gpuDebug->GetCurrentFramebuffer(bufferFrame); + bufferResult = gpuDebug->GetCurrentFramebuffer(bufferFrame, bufferType); break; case PAUSE_GETDEPTHBUF: @@ -160,7 +161,8 @@ static bool GetBuffer(const GPUDebugBuffer *&buffer, PauseAction type, const GPU return bufferResult; } -bool GPU_GetCurrentFramebuffer(const GPUDebugBuffer *&buffer) { +bool GPU_GetCurrentFramebuffer(const GPUDebugBuffer *&buffer, GPUDebugFramebufferType type) { + bufferType = type; return GetBuffer(buffer, PAUSE_GETFRAMEBUF, bufferFrame); } @@ -201,4 +203,4 @@ void ForceUnpause() { actionWait.notify_one(); } -}; \ No newline at end of file +}; diff --git a/GPU/Debugger/Stepping.h b/GPU/Debugger/Stepping.h index 9db652257..5c9e1835e 100644 --- a/GPU/Debugger/Stepping.h +++ b/GPU/Debugger/Stepping.h @@ -28,7 +28,7 @@ namespace GPUStepping { bool EnterStepping(std::function callback); bool IsStepping(); - bool GPU_GetCurrentFramebuffer(const GPUDebugBuffer *&buffer); + bool GPU_GetCurrentFramebuffer(const GPUDebugBuffer *&buffer, GPUDebugFramebufferType type); bool GPU_GetCurrentDepthbuffer(const GPUDebugBuffer *&buffer); bool GPU_GetCurrentStencilbuffer(const GPUDebugBuffer *&buffer); bool GPU_GetCurrentTexture(const GPUDebugBuffer *&buffer, int level); @@ -37,4 +37,4 @@ namespace GPUStepping { void ResumeFromStepping(); void ForceUnpause(); -}; \ No newline at end of file +}; diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index b934d4bfd..1fd08877a 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -1311,9 +1311,10 @@ namespace DX9 { resized_ = true; } - bool FramebufferManagerDX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes) { - u32 fb_address = gstate.getFrameBufRawAddress(); - int fb_stride = gstate.FrameBufStride(); + bool FramebufferManagerDX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { + u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : displayFramebufPtr_; + int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : displayStride_; + GEBufferFormat fb_format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : displayFormat_; VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { @@ -1322,7 +1323,7 @@ namespace DX9 { if (!vfb) { // If there's no vfb and we're drawing there, must be memory? - buffer = GPUDebugBuffer(Memory::GetPointer(fb_address | 0x04000000), fb_stride, 512, gstate.FrameBufFormat()); + buffer = GPUDebugBuffer(Memory::GetPointer(fb_address | 0x04000000), fb_stride, 512, fb_format); return true; } diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index 3835b9669..612d3c3be 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -82,7 +82,7 @@ public: void DestroyFramebuf(VirtualFramebuffer *vfb) override; void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) override; - bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes); + bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes); bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer); bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); static bool GetDisplayFramebuffer(GPUDebugBuffer &buffer); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index ee8113837..07ca205f9 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -2146,8 +2146,8 @@ void GPU_DX9::DoState(PointerWrap &p) { } } -bool GPU_DX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes) { - return framebufferManager_.GetCurrentFramebuffer(buffer, maxRes); +bool GPU_DX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { + return framebufferManager_.GetCurrentFramebuffer(buffer, type, maxRes); } bool GPU_DX9::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 65f180674..5939fa06d 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -76,7 +76,7 @@ public: } std::vector GetFramebufferList() override; - bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes = -1) override; + bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes = -1) override; bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 30f0672a8..df0c3b89a 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -2417,10 +2417,10 @@ void GPU_GLES::DoState(PointerWrap &p) { } } -bool GPU_GLES::GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes) { - u32 fb_address = gstate.getFrameBufRawAddress(); - int fb_stride = gstate.FrameBufStride(); - GEBufferFormat format = gstate.FrameBufFormat(); +bool GPU_GLES::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { + u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : framebufferManager_.DisplayFramebufAddr(); + int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManager_.DisplayFramebufStride(); + GEBufferFormat format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : framebufferManager_.DisplayFramebufFormat(); return framebufferManager_.GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes); } diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 64d682a80..34c5d27fa 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -81,7 +81,7 @@ public: } std::vector GetFramebufferList() override; - bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes) override; + bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) override; bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override; diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 27a262af2..39ab036a0 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -825,19 +825,34 @@ bool SoftGPU::FramebufferDirty() { return true; } -bool SoftGPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes) +bool SoftGPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { - const int w = gstate.getRegionX2() - gstate.getRegionX1() + 1; - const int h = gstate.getRegionY2() - gstate.getRegionY1() + 1; - buffer.Allocate(w, h, gstate.FrameBufFormat()); + int x1 = gstate.getRegionX1(); + int y1 = gstate.getRegionY1(); + int x2 = gstate.getRegionX2() + 1; + int y2 = gstate.getRegionY2() + 1; + int stride = gstate.FrameBufStride(); + GEBufferFormat fmt = gstate.FrameBufFormat(); - const int depth = gstate.FrameBufFormat() == GE_FORMAT_8888 ? 4 : 2; - const u8 *src = fb.data + gstate.FrameBufStride() * depth * gstate.getRegionY1(); + if (type == GPU_DBG_FRAMEBUF_DISPLAY) { + x1 = 0; + y1 = 0; + x2 = 480; + y2 = 272; + stride = displayStride_; + fmt = displayFormat_; + } + + buffer.Allocate(x2 - x1, y2 - y1, fmt); + + const int depth = fmt == GE_FORMAT_8888 ? 4 : 2; + const u8 *src = fb.data + stride * depth * y1; u8 *dst = buffer.GetData(); - for (int y = gstate.getRegionY1(); y <= gstate.getRegionY2(); ++y) { - memcpy(dst, src + gstate.getRegionX1(), (gstate.getRegionX2() + 1) * depth); - dst += w * depth; - src += gstate.FrameBufStride() * depth; + const int byteWidth = (x2 - x1) * depth; + for (int y = y1; y < y2; ++y) { + memcpy(dst, src + x1, byteWidth); + dst += byteWidth; + src += stride * depth; } return true; } diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 053ee9b54..cd958bbb6 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -84,7 +84,7 @@ public: return !(gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME); } - bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes = -1) override; + bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes = -1) override; bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override; diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 6b3d707cf..ed71dc20f 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -256,7 +256,7 @@ void CGEDebugger::UpdatePrimaryPreview(const GPUgstate &state) { } else { switch (PrimaryDisplayType(fbTabs->CurrentTabIndex())) { case PRIMARY_FRAMEBUF: - bufferResult = GPU_GetCurrentFramebuffer(primaryBuffer_); + bufferResult = GPU_GetCurrentFramebuffer(primaryBuffer_, GPU_DBG_FRAMEBUF_RENDER); break; case PRIMARY_DEPTHBUF: diff --git a/headless/WindowsHeadlessHost.cpp b/headless/WindowsHeadlessHost.cpp index 229aa547d..62edd1e27 100644 --- a/headless/WindowsHeadlessHost.cpp +++ b/headless/WindowsHeadlessHost.cpp @@ -100,7 +100,7 @@ void WindowsHeadlessHost::SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) const static u32 FRAME_HEIGHT = 272; GPUDebugBuffer buffer; - gpuDebug->GetCurrentFramebuffer(buffer); + gpuDebug->GetCurrentFramebuffer(buffer, GPU_DBG_FRAMEBUF_RENDER); const std::vector pixels = TranslateDebugBufferToCompare(&buffer, 512, 272); std::string error;