Allow taking screenshots with a clamped size.

Sometimes 10x is a little on the big side.
This commit is contained in:
Unknown W. Brackets committed 2016-06-12 07:09:01 -07:00
1 parent 16897bd19d
commit 6151f8ef9f
13 files changed
+81 -31

No files matched your search

+9 -4
View File
@@ -215,7 +215,7 @@ static const u8 *ConvertBufferTo888RGB(const GPUDebugBuffer &buf, u8 *&temp, u32
return buffer; return buffer;
} }
bool TakeGameScreenshot(const char *filename, ScreenshotFormat fmt, ScreenshotType type) { bool TakeGameScreenshot(const char *filename, ScreenshotFormat fmt, ScreenshotType type, int *width, int *height, int maxRes) {
GPUDebugBuffer buf; GPUDebugBuffer buf;
bool success = false; bool success = false;
u32 w = (u32)-1; u32 w = (u32)-1;
@@ -223,12 +223,12 @@ bool TakeGameScreenshot(const char *filename, ScreenshotFormat fmt, ScreenshotTy
if (type == SCREENSHOT_RENDER) { if (type == SCREENSHOT_RENDER) {
if (gpuDebug) { if (gpuDebug) {
success = gpuDebug->GetCurrentFramebuffer(buf); success = gpuDebug->GetCurrentFramebuffer(buf, maxRes);
} }
// Only crop to the top left when using a render screenshot. // Only crop to the top left when using a render screenshot.
w = PSP_CoreParameter().renderWidth; w = maxRes > 0 ? 480 * maxRes : PSP_CoreParameter().renderWidth;
h = PSP_CoreParameter().renderHeight; h = maxRes > 0 ? 272 * maxRes : PSP_CoreParameter().renderHeight;
} else { } else {
if (GetGPUBackend() == GPUBackend::OPENGL) { if (GetGPUBackend() == GPUBackend::OPENGL) {
success = GPU_GLES::GetDisplayFramebuffer(buf); success = GPU_GLES::GetDisplayFramebuffer(buf);
@@ -261,6 +261,11 @@ bool TakeGameScreenshot(const char *filename, ScreenshotFormat fmt, ScreenshotTy
success = false; success = false;
} }
if (width)
*width = w;
if (height)
*height = h;
if (success && fmt == SCREENSHOT_PNG) { if (success && fmt == SCREENSHOT_PNG) {
png_image png; png_image png;
memset(&png, 0, sizeof(png)); memset(&png, 0, sizeof(png));
+1 -1
View File
@@ -30,4 +30,4 @@ enum ScreenshotType {
SCREENSHOT_RENDER, SCREENSHOT_RENDER,
}; };
bool TakeGameScreenshot(const char *filename, ScreenshotFormat fmt, ScreenshotType type); bool TakeGameScreenshot(const char *filename, ScreenshotFormat fmt, ScreenshotType type, int *width = nullptr, int *height = nullptr, int maxRes = -1);
+1 -1
View File
@@ -206,7 +206,7 @@ public:
// Needs to be called from the GPU thread, so on the same thread as a notification is fine. // 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. // Calling from a separate thread (e.g. UI) may fail.
virtual bool GetCurrentFramebuffer(GPUDebugBuffer &buffer) { virtual bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes = -1) {
// False means unsupported. // False means unsupported.
return false; return false;
} }
+29 -6
View File
@@ -630,7 +630,11 @@ namespace DX9 {
return nullptr; return nullptr;
} }
u64 key = ((u64)desc.Format << 32) | (desc.Width << 16) | desc.Height; return GetOffscreenSurface(desc.Format, desc.Width, desc.Height);
}
LPDIRECT3DSURFACE9 FramebufferManagerDX9::GetOffscreenSurface(D3DFORMAT fmt, u32 w, u32 h) {
u64 key = ((u64)fmt << 32) | (w << 16) | h;
auto it = offscreenSurfaces_.find(key); auto it = offscreenSurfaces_.find(key);
if (it != offscreenSurfaces_.end()) { if (it != offscreenSurfaces_.end()) {
it->second.last_frame_used = gpuStats.numFlips; it->second.last_frame_used = gpuStats.numFlips;
@@ -639,9 +643,9 @@ namespace DX9 {
textureCache_->ForgetLastTexture(); textureCache_->ForgetLastTexture();
LPDIRECT3DSURFACE9 offscreen = nullptr; LPDIRECT3DSURFACE9 offscreen = nullptr;
hr = pD3Ddevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &offscreen, NULL); HRESULT hr = pD3Ddevice->CreateOffscreenPlainSurface(w, h, fmt, D3DPOOL_SYSTEMMEM, &offscreen, NULL);
if (FAILED(hr) || !offscreen) { if (FAILED(hr) || !offscreen) {
ERROR_LOG_REPORT(G3D, "Unable to create offscreen surface %dx%d @%d", desc.Width, desc.Height, desc.Format); ERROR_LOG_REPORT(G3D, "Unable to create offscreen surface %dx%d @%d", w, h, fmt);
return nullptr; return nullptr;
} }
const OffscreenSurface info = {offscreen, gpuStats.numFlips}; const OffscreenSurface info = {offscreen, gpuStats.numFlips};
@@ -1307,7 +1311,7 @@ namespace DX9 {
resized_ = true; resized_ = true;
} }
bool FramebufferManagerDX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer) { bool FramebufferManagerDX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes) {
u32 fb_address = gstate.getFrameBufRawAddress(); u32 fb_address = gstate.getFrameBufRawAddress();
int fb_stride = gstate.FrameBufStride(); int fb_stride = gstate.FrameBufStride();
@@ -1322,12 +1326,31 @@ namespace DX9 {
return true; return true;
} }
LPDIRECT3DSURFACE9 renderTarget = vfb->fbo ? fbo_get_color_for_read(vfb->fbo_dx9) : nullptr; LPDIRECT3DSURFACE9 renderTarget = vfb->fbo_dx9 ? fbo_get_color_for_read(vfb->fbo_dx9) : nullptr;
bool success = false; bool success = false;
if (renderTarget) { if (renderTarget) {
FBO_DX9 *tempFBO = nullptr;
int w = vfb->renderWidth, h = vfb->renderHeight;
if (maxRes > 0 && vfb->renderWidth > vfb->width * maxRes) {
// Let's resize. We must stretch to a render target first.
w = vfb->width * maxRes;
h = vfb->height * maxRes;
tempFBO = fbo_create(w, h, 1, false);
RECT srcRect = {0, 0, vfb->renderWidth, vfb->renderHeight};
D3DTEXTUREFILTERTYPE filt = g_Config.iBufFilter == SCALE_LINEAR ? D3DTEXF_LINEAR : D3DTEXF_POINT;
if (SUCCEEDED(fbo_blit_color(vfb->fbo_dx9, &srcRect, tempFBO, nullptr, filt))) {
renderTarget = fbo_get_color_for_read(tempFBO);
}
}
LPDIRECT3DSURFACE9 offscreen = GetOffscreenSurface(renderTarget, vfb); LPDIRECT3DSURFACE9 offscreen = GetOffscreenSurface(renderTarget, vfb);
if (offscreen) { if (offscreen) {
success = GetRenderTargetFramebuffer(renderTarget, offscreen, vfb->renderWidth, vfb->renderHeight, buffer); success = GetRenderTargetFramebuffer(renderTarget, offscreen, w, h, buffer);
}
if (tempFBO) {
fbo_destroy(tempFBO);
} }
} }
+2 -1
View File
@@ -82,7 +82,7 @@ public:
void DestroyFramebuf(VirtualFramebuffer *vfb); void DestroyFramebuf(VirtualFramebuffer *vfb);
void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false); void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false);
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer); bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes);
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer); bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer);
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer);
static bool GetDisplayFramebuffer(GPUDebugBuffer &buffer); static bool GetDisplayFramebuffer(GPUDebugBuffer &buffer);
@@ -91,6 +91,7 @@ public:
FBO_DX9 *GetTempFBO(u16 w, u16 h, FBOColorDepth depth = FBO_8888); FBO_DX9 *GetTempFBO(u16 w, u16 h, FBOColorDepth depth = FBO_8888);
LPDIRECT3DSURFACE9 GetOffscreenSurface(LPDIRECT3DSURFACE9 similarSurface, VirtualFramebuffer *vfb); LPDIRECT3DSURFACE9 GetOffscreenSurface(LPDIRECT3DSURFACE9 similarSurface, VirtualFramebuffer *vfb);
LPDIRECT3DSURFACE9 GetOffscreenSurface(D3DFORMAT fmt, u32 w, u32 h);
protected: protected:
void DisableState() override; void DisableState() override;
+2 -2
View File
@@ -2142,8 +2142,8 @@ void GPU_DX9::DoState(PointerWrap &p) {
} }
} }
bool GPU_DX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer) { bool GPU_DX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes) {
return framebufferManager_.GetCurrentFramebuffer(buffer); return framebufferManager_.GetCurrentFramebuffer(buffer, maxRes);
} }
bool GPU_DX9::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { bool GPU_DX9::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
+5 -5
View File
@@ -75,13 +75,13 @@ public:
} }
std::vector<FramebufferInfo> GetFramebufferList() override; std::vector<FramebufferInfo> GetFramebufferList() override;
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer); bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes = -1) override;
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer); bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override;
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override;
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level); bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override;
bool GetCurrentClut(GPUDebugBuffer &buffer) override; bool GetCurrentClut(GPUDebugBuffer &buffer) override;
static bool GetDisplayFramebuffer(GPUDebugBuffer &buffer); static bool GetDisplayFramebuffer(GPUDebugBuffer &buffer);
bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices); bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices) override;
typedef void (GPU_DX9::*CmdFunc)(u32 op, u32 diff); typedef void (GPU_DX9::*CmdFunc)(u32 op, u32 diff);
struct CommandInfo { struct CommandInfo {
+26 -5
View File
@@ -1970,7 +1970,7 @@ void FramebufferManager::Resized() {
resized_ = true; resized_ = true;
} }
bool FramebufferManager::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer) { bool FramebufferManager::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes) {
VirtualFramebuffer *vfb = currentRenderVfb_; VirtualFramebuffer *vfb = currentRenderVfb_;
if (!vfb) { if (!vfb) {
vfb = GetVFBAt(fb_address); vfb = GetVFBAt(fb_address);
@@ -1982,14 +1982,35 @@ bool FramebufferManager::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferF
return true; return true;
} }
buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GE_FORMAT_8888, !useBufferedRendering_, true); int w = vfb->renderWidth, h = vfb->renderHeight;
if (vfb->fbo) if (vfb->fbo) {
fbo_bind_for_read(vfb->fbo); if (maxRes > 0 && vfb->renderWidth > vfb->width * maxRes) {
w = vfb->width * maxRes;
h = vfb->height * maxRes;
FBO *tempFBO = GetTempFBO(w, h);
VirtualFramebuffer tempVfb = *vfb;
tempVfb.fbo = tempFBO;
tempVfb.bufferWidth = vfb->width;
tempVfb.bufferHeight = vfb->height;
tempVfb.renderWidth = w;
tempVfb.renderHeight = h;
BlitFramebuffer(&tempVfb, 0, 0, vfb, 0, 0, vfb->width, vfb->height, 0);
fbo_bind_for_read(tempFBO);
} else {
fbo_bind_for_read(vfb->fbo);
}
}
buffer.Allocate(w, h, GE_FORMAT_8888, !useBufferedRendering_, true);
if (gl_extensions.GLES3 || !gl_extensions.IsGLES) if (gl_extensions.GLES3 || !gl_extensions.IsGLES)
glReadBuffer(GL_COLOR_ATTACHMENT0); glReadBuffer(GL_COLOR_ATTACHMENT0);
glPixelStorei(GL_PACK_ALIGNMENT, 4); glPixelStorei(GL_PACK_ALIGNMENT, 4);
SafeGLReadPixels(0, 0, vfb->renderWidth, vfb->renderHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer.GetData()); SafeGLReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer.GetData());
fbo_unbind();
return true; return true;
} }
+1 -1
View File
@@ -108,7 +108,7 @@ public:
void DestroyFramebuf(VirtualFramebuffer *vfb) override; void DestroyFramebuf(VirtualFramebuffer *vfb) override;
void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false) override; void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false) override;
bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer); bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes);
bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer); bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer);
bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer); bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer);
static bool GetDisplayFramebuffer(GPUDebugBuffer &buffer); static bool GetDisplayFramebuffer(GPUDebugBuffer &buffer);
+2 -2
View File
@@ -2413,11 +2413,11 @@ void GPU_GLES::DoState(PointerWrap &p) {
} }
} }
bool GPU_GLES::GetCurrentFramebuffer(GPUDebugBuffer &buffer) { bool GPU_GLES::GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes) {
u32 fb_address = gstate.getFrameBufRawAddress(); u32 fb_address = gstate.getFrameBufRawAddress();
int fb_stride = gstate.FrameBufStride(); int fb_stride = gstate.FrameBufStride();
GEBufferFormat format = gstate.FrameBufFormat(); GEBufferFormat format = gstate.FrameBufFormat();
return framebufferManager_.GetFramebuffer(fb_address, fb_stride, format, buffer); return framebufferManager_.GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes);
} }
bool GPU_GLES::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { bool GPU_GLES::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) {
+1 -1
View File
@@ -80,7 +80,7 @@ public:
} }
std::vector<FramebufferInfo> GetFramebufferList() override; std::vector<FramebufferInfo> GetFramebufferList() override;
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer) override; bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes) override;
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override;
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override;
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override; bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override;
+1 -1
View File
@@ -821,7 +821,7 @@ bool SoftGPU::FramebufferDirty() {
return true; return true;
} }
bool SoftGPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer) bool SoftGPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes)
{ {
const int w = gstate.getRegionX2() - gstate.getRegionX1() + 1; const int w = gstate.getRegionX2() - gstate.getRegionX1() + 1;
const int h = gstate.getRegionY2() - gstate.getRegionY1() + 1; const int h = gstate.getRegionY2() - gstate.getRegionY1() + 1;
+1 -1
View File
@@ -83,7 +83,7 @@ public:
return !(gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME); return !(gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME);
} }
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer) override; bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes = -1) override;
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override;
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override;
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override; bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override;