mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Convert FramebufferBlit from the GL backend to use thin3d
This commit is contained in:
1 parent
64a8a3f7d3
commit
1ab9293cb3
6 files changed
+110
-128
No files matched your search
@@ -174,91 +174,6 @@ void FramebufferManagerGLES::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb)
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp, const char *tag) {
|
||||
if (!dst->fbo || !src->fbo || !useBufferedRendering_) {
|
||||
// This can happen if they recently switched from non-buffered.
|
||||
if (useBufferedRendering_)
|
||||
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "BlitFramebuffer");
|
||||
return;
|
||||
}
|
||||
|
||||
bool useBlit = draw_->GetDeviceCaps().framebufferBlitSupported;
|
||||
bool useCopy = draw_->GetDeviceCaps().framebufferCopySupported;
|
||||
if (dst == currentRenderVfb_) {
|
||||
// If already bound, using either a blit or a copy is unlikely to be an optimization.
|
||||
useBlit = false;
|
||||
useCopy = false;
|
||||
}
|
||||
|
||||
float srcXFactor = useBlit ? src->renderScaleFactor : 1.0f;
|
||||
float srcYFactor = useBlit ? src->renderScaleFactor : 1.0f;
|
||||
const int srcBpp = src->format == GE_FORMAT_8888 ? 4 : 2;
|
||||
if (srcBpp != bpp && bpp != 0) {
|
||||
srcXFactor = (srcXFactor * bpp) / srcBpp;
|
||||
}
|
||||
int srcX1 = srcX * srcXFactor;
|
||||
int srcX2 = (srcX + w) * srcXFactor;
|
||||
int srcY1 = srcY * srcYFactor;
|
||||
int srcY2 = (srcY + h) * srcYFactor;
|
||||
|
||||
float dstXFactor = useBlit ? dst->renderScaleFactor : 1.0f;
|
||||
float dstYFactor = useBlit ? dst->renderScaleFactor : 1.0f;
|
||||
const int dstBpp = dst->format == GE_FORMAT_8888 ? 4 : 2;
|
||||
if (dstBpp != bpp && bpp != 0) {
|
||||
dstXFactor = (dstXFactor * bpp) / dstBpp;
|
||||
}
|
||||
int dstX1 = dstX * dstXFactor;
|
||||
int dstX2 = (dstX + w) * dstXFactor;
|
||||
int dstY1 = dstY * dstYFactor;
|
||||
int dstY2 = (dstY + h) * dstYFactor;
|
||||
|
||||
if (src == dst && srcX == dstX && srcY == dstY) {
|
||||
// Let's just skip a copy where the destination is equal to the source.
|
||||
WARN_LOG_REPORT_ONCE(blitSame, G3D, "Skipped blit with equal dst and src");
|
||||
return;
|
||||
}
|
||||
|
||||
if (useCopy && draw_->GetDeviceCaps().framebufferCopySupported) {
|
||||
// glBlitFramebuffer can clip, but glCopyImageSubData is more restricted.
|
||||
// In case the src goes outside, we just skip the optimization in that case.
|
||||
const bool sameSize = dstX2 - dstX1 == srcX2 - srcX1 && dstY2 - dstY1 == srcY2 - srcY1;
|
||||
const bool srcInsideBounds = srcX2 <= src->renderWidth && srcY2 <= src->renderHeight;
|
||||
const bool dstInsideBounds = dstX2 <= dst->renderWidth && dstY2 <= dst->renderHeight;
|
||||
const bool xOverlap = src == dst && srcX2 > dstX1 && srcX1 < dstX2;
|
||||
const bool yOverlap = src == dst && srcY2 > dstY1 && srcY1 < dstY2;
|
||||
if (sameSize && srcInsideBounds && dstInsideBounds && !(xOverlap && yOverlap)) {
|
||||
draw_->CopyFramebufferImage(src->fbo, 0, srcX1, srcY1, 0, dst->fbo, 0, dstX1, dstY1, 0, dstX2 - dstX1, dstY2 - dstY1, 1, Draw::FB_COLOR_BIT, tag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (useBlit) {
|
||||
draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, Draw::FB_COLOR_BIT, Draw::FB_BLIT_NEAREST, tag);
|
||||
} else {
|
||||
// TODO: Use thin3d for this, instead of dirtying up the code here.
|
||||
draw_->BindFramebufferAsRenderTarget(dst->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, tag);
|
||||
draw_->BindFramebufferAsTexture(src->fbo, 0, Draw::FB_COLOR_BIT, 0);
|
||||
|
||||
// Make sure our 2D drawing program is ready. Compiles only if not already compiled.
|
||||
CompileDraw2DProgram();
|
||||
|
||||
render_->SetViewport({ 0, 0, (float)dst->renderWidth, (float)dst->renderHeight, 0, 1.0f });
|
||||
render_->SetStencilDisabled();
|
||||
render_->SetDepth(false, false, GL_ALWAYS);
|
||||
render_->SetNoBlendAndMask(0xF);
|
||||
|
||||
// The first four coordinates are relative to the 6th and 7th arguments of DrawActiveTexture.
|
||||
// Should maybe revamp that interface.
|
||||
float srcW = src->bufferWidth;
|
||||
float srcH = src->bufferHeight;
|
||||
render_->BindProgram(draw2dprogram_);
|
||||
DrawActiveTexture(dstX1, dstY1, w * dstXFactor, h * dstYFactor, dst->bufferWidth, dst->bufferHeight, srcX1 / srcW, srcY1 / srcH, srcX2 / srcW, srcY2 / srcH, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST);
|
||||
textureCache_->ForgetLastTexture();
|
||||
}
|
||||
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_RASTER_STATE);
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::EndFrame() {
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user