diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 1d29463e2d..8cd31f2434 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -718,6 +718,32 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int DrawActiveTexture(dstX, dstY, width, height, vfb->bufferWidth, vfb->bufferHeight, u0, v0, u1, v1, ROTATION_LOCKED_HORIZONTAL, linearFilter); } +void FramebufferManagerCommon::CopyFramebufferForColorTexture(VirtualFramebuffer *dst, VirtualFramebuffer *src, int flags) { + int x = 0; + int y = 0; + int w = src->drawnWidth; + int h = src->drawnHeight; + + // If max is not > min, we probably could not detect it. Skip. + // See the vertex decoder, where this is updated. + if ((flags & BINDFBCOLOR_MAY_COPY_WITH_UV) == BINDFBCOLOR_MAY_COPY_WITH_UV && gstate_c.vertBounds.maxU > gstate_c.vertBounds.minU) { + x = std::max(gstate_c.vertBounds.minU, (u16)0); + y = std::max(gstate_c.vertBounds.minV, (u16)0); + w = std::min(gstate_c.vertBounds.maxU, src->drawnWidth) - x; + h = std::min(gstate_c.vertBounds.maxV, src->drawnHeight) - y; + + // If we bound a framebuffer, apply the byte offset as pixels to the copy too. + if (flags & BINDFBCOLOR_APPLY_TEX_OFFSET) { + x += gstate_c.curTextureXOffset; + y += gstate_c.curTextureYOffset; + } + } + + if (x < src->drawnWidth && y < src->drawnHeight && w > 0 && h > 0) { + BlitFramebuffer(dst, x, y, src, x, y, w, h, 0); + } +} + void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) { textureCache_->ForgetLastTexture(); shaderManager_->DirtyLastShader(); diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index f121db12e8..db4dd97886 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -292,6 +292,7 @@ protected: // Used by ReadFramebufferToMemory and later framebuffer block copies virtual void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) = 0; + void CopyFramebufferForColorTexture(VirtualFramebuffer *dst, VirtualFramebuffer *src, int flags); void EstimateDrawingSize(u32 fb_address, GEBufferFormat fb_format, int viewport_width, int viewport_height, int region_width, int region_height, int scissor_width, int scissor_height, int fb_stride, int &drawing_width, int &drawing_height); u32 FramebufferByteSize(const VirtualFramebuffer *vfb) const; diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 78dcf5d1d4..270cf4f392 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -572,28 +572,7 @@ void FramebufferManagerD3D11::BindFramebufferAsColorTexture(int stage, VirtualFr VirtualFramebuffer copyInfo = *framebuffer; copyInfo.fbo = renderCopy; - int x = 0; - int y = 0; - int w = framebuffer->drawnWidth; - int h = framebuffer->drawnHeight; - - // If max is not > min, we probably could not detect it. Skip. - // See the vertex decoder, where this is updated. - if ((flags & BINDFBCOLOR_MAY_COPY_WITH_UV) == BINDFBCOLOR_MAY_COPY_WITH_UV && gstate_c.vertBounds.maxU > gstate_c.vertBounds.minU) { - x = gstate_c.vertBounds.minU; - y = gstate_c.vertBounds.minV; - w = gstate_c.vertBounds.maxU - x; - h = gstate_c.vertBounds.maxV - y; - - // If we bound a framebuffer, apply the byte offset as pixels to the copy too. - if (flags & BINDFBCOLOR_APPLY_TEX_OFFSET) { - x += gstate_c.curTextureXOffset; - y += gstate_c.curTextureYOffset; - } - } - - BlitFramebuffer(©Info, x, y, framebuffer, x, y, w, h, 0); - + CopyFramebufferForColorTexture(©Info, framebuffer, flags); RebindFramebuffer(); draw_->BindFramebufferAsTexture(renderCopy, stage, Draw::FB_COLOR_BIT, 0); } else { diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index f50fbdb15a..e333a64052 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -481,28 +481,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { VirtualFramebuffer copyInfo = *framebuffer; copyInfo.fbo = renderCopy; - int x = 0; - int y = 0; - int w = framebuffer->drawnWidth; - int h = framebuffer->drawnHeight; - - // If max is not > min, we probably could not detect it. Skip. - // See the vertex decoder, where this is updated. - if ((flags & BINDFBCOLOR_MAY_COPY_WITH_UV) == BINDFBCOLOR_MAY_COPY_WITH_UV && gstate_c.vertBounds.maxU > gstate_c.vertBounds.minU) { - x = gstate_c.vertBounds.minU; - y = gstate_c.vertBounds.minV; - w = gstate_c.vertBounds.maxU - x; - h = gstate_c.vertBounds.maxV - y; - - // If we bound a framebuffer, apply the byte offset as pixels to the copy too. - if (flags & BINDFBCOLOR_APPLY_TEX_OFFSET) { - x += gstate_c.curTextureXOffset; - y += gstate_c.curTextureYOffset; - } - } - - BlitFramebuffer(©Info, x, y, framebuffer, x, y, w, h, 0); - + CopyFramebufferForColorTexture(©Info, framebuffer, flags); RebindFramebuffer(); draw_->BindFramebufferAsTexture(renderCopy, stage, Draw::FB_COLOR_BIT, 0); } else { diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index a6b9b57c3e..fa32795bfc 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -547,28 +547,7 @@ void FramebufferManagerGLES::BindFramebufferAsColorTexture(int stage, VirtualFra VirtualFramebuffer copyInfo = *framebuffer; copyInfo.fbo = renderCopy; - int x = 0; - int y = 0; - int w = framebuffer->drawnWidth; - int h = framebuffer->drawnHeight; - - // If max is not > min, we probably could not detect it. Skip. - // See the vertex decoder, where this is updated. - if ((flags & BINDFBCOLOR_MAY_COPY_WITH_UV) == BINDFBCOLOR_MAY_COPY_WITH_UV && gstate_c.vertBounds.maxU > gstate_c.vertBounds.minU) { - x = gstate_c.vertBounds.minU; - y = gstate_c.vertBounds.minV; - w = gstate_c.vertBounds.maxU - x; - h = gstate_c.vertBounds.maxV - y; - - // If we bound a framebuffer, apply the byte offset as pixels to the copy too. - if (flags & BINDFBCOLOR_APPLY_TEX_OFFSET) { - x += gstate_c.curTextureXOffset; - y += gstate_c.curTextureYOffset; - } - } - - BlitFramebuffer(©Info, x, y, framebuffer, x, y, w, h, 0); - + CopyFramebufferForColorTexture(©Info, framebuffer, flags); draw_->BindFramebufferAsTexture(renderCopy, stage, Draw::FB_COLOR_BIT, 0); } else { draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0);