mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-28 02:41:18 +00:00
Add a flag to use the display vfb for screenshots.
This fixes proportions of reporting, savestate screenshots, and TAS recording for PS1 ports, mainly.
This commit is contained in:
parent
246f3aa68d
commit
fa0e88f1b7
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
@ -28,7 +28,7 @@ namespace GPUStepping {
|
||||
bool EnterStepping(std::function<void()> 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();
|
||||
};
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
}
|
||||
std::vector<FramebufferInfo> 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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ public:
|
||||
}
|
||||
std::vector<FramebufferInfo> 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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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<u32> pixels = TranslateDebugBufferToCompare(&buffer, 512, 272);
|
||||
|
||||
std::string error;
|
||||
|
Loading…
Reference in New Issue
Block a user