diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index de218d395e..cc3d465b19 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -1231,7 +1231,7 @@ void FramebufferManager::ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool s } } -void FramebufferManager::BlitFramebuffer_(VirtualFramebuffer *src, VirtualFramebuffer *dst, bool flip, float upscale, float vscale) { +void FramebufferManager::BlitFramebuffer_(VirtualFramebuffer *src, VirtualFramebuffer *dst, bool flip, float uscale, float vscale) { if (dst->fbo) { fbo_bind_as_render_target(dst->fbo); } else { @@ -1260,12 +1260,13 @@ void FramebufferManager::BlitFramebuffer_(VirtualFramebuffer *src, VirtualFrameb return; } + // It's pretty obvious that this CenterRect is incorrect. float x, y, w, h; CenterRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight); CompileDraw2DProgram(); - DrawActiveTexture(0, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, flip, upscale, vscale, draw2dprogram_); + DrawActiveTexture(0, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, flip, uscale, vscale, draw2dprogram_); glBindTexture(GL_TEXTURE_2D, 0); fbo_unbind(); @@ -1572,8 +1573,10 @@ void FramebufferManager::EndFrame() { } #ifndef USING_GLES2 - // We flush to memory last requested framebuffer, if any - PackFramebufferAsync_(NULL); + // We flush to memory last requested framebuffer, if any. + // Only do this in the read-framebuffer modes. + if (g_Config.iRenderingMode == FB_READFBOMEMORY_CPU || g_Config.iRenderingMode == FB_READFBOMEMORY_GPU) + PackFramebufferAsync_(NULL); #endif } @@ -1726,34 +1729,35 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size, bool safe) { } } -void FramebufferManager::NotifyBlockTransfer(u32 dst, u32 src) { +bool FramebufferManager::NotifyBlockTransfer(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h) { + // The stuff in the #ifdef is JUST for reporting, not used for anything else. #ifndef MOBILE_DEVICE - if (!reportedBlits_.insert(std::make_pair(dst, src)).second) { + if (reportedBlits_.insert(std::make_pair(dstBasePtr, srcBasePtr)).second) { // Already reported/checked. - return; - } - - bool dstBuffer = false; - bool srcBuffer = false; - - for (size_t i = 0; i < vfbs_.size(); ++i) { - VirtualFramebuffer *vfb = vfbs_[i]; - if (MaskedEqual(vfb->fb_address, dst)) { - dstBuffer = true; + bool dstBuffer = false; + bool srcBuffer = false; + for (size_t i = 0; i < vfbs_.size(); ++i) { + VirtualFramebuffer *vfb = vfbs_[i]; + if (MaskedEqual(vfb->fb_address, dstBasePtr)) { + dstBuffer = true; + } + if (MaskedEqual(vfb->fb_address, srcBasePtr)) { + srcBuffer = true; + } } - if (MaskedEqual(vfb->fb_address, src)) { - srcBuffer = true; + + if (dstBuffer && srcBuffer) { + WARN_LOG_REPORT(G3D, "Intra buffer block transfer (not supported) %08x -> %08x", srcBasePtr, dstBasePtr); + } else if (dstBuffer) { + WARN_LOG_REPORT(G3D, "Block transfer upload (not supported) %08x -> %08x", srcBasePtr, dstBasePtr); + } else if (srcBuffer && g_Config.iRenderingMode == FB_BUFFERED_MODE) { + WARN_LOG_REPORT(G3D, "Block transfer download (not supported) %08x -> %08x", srcBasePtr, dstBasePtr); } } - if (dstBuffer && srcBuffer) { - WARN_LOG_REPORT(G3D, "Intra buffer block transfer (not supported) %08x -> %08x", src, dst); - } else if (dstBuffer) { - WARN_LOG_REPORT(G3D, "Block transfer upload (not supported) %08x -> %08x", src, dst); - } else if (srcBuffer && g_Config.iRenderingMode == FB_BUFFERED_MODE) { - WARN_LOG_REPORT(G3D, "Block transfer download (not supported) %08x -> %08x", src, dst); - } #endif + + return false; } void FramebufferManager::Resized() { diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index 4d96c7f4a8..dfb7cc5d70 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -159,8 +159,10 @@ public: // For use when texturing from a framebuffer. May create a duplicate if target. void BindFramebufferColor(VirtualFramebuffer *framebuffer); - // Just for logging right now. Might remove/change. - void NotifyBlockTransfer(u32 dst, u32 src); + // Returns true if it's sure this is a direct FBO->FBO transfer and it has already handle it. + // In that case we hardly need to actually copy the bytes in VRAM, they will be wrong anyway (unless + // read framebuffers is on, in which case this should always return false). + bool NotifyBlockTransfer(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h); #ifdef USING_GLES2 void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync = true); @@ -262,5 +264,7 @@ private: u8 currentPBO_; #endif + // This is to be used only for reporting of strange blits. Don't control behaviour as + // this is "permanent" while framebuffers aren't. std::set> reportedBlits_; }; diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index e0eb6d5a2e..ddf351f7cb 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -1929,8 +1929,10 @@ void GLES_GPU::DoBlockTransfer() { } } - // TODO: Notify all overlapping FBOs that they need to reload. - framebufferManager_.NotifyBlockTransfer(dstBasePtr, srcBasePtr); + // Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return. + if (framebufferManager_.NotifyBlockTransfer(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height)) { + goto doMemChecks; + } textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT); if (Memory::IsRAMAddress(srcBasePtr) && Memory::IsVRAMAddress(dstBasePtr)) { @@ -1953,9 +1955,12 @@ void GLES_GPU::DoBlockTransfer() { framebufferManager_.DrawPixels(Memory::GetPointerUnchecked(dstBasePtr), GE_FORMAT_8888, 512); } +doMemChecks: #ifndef MOBILE_DEVICE CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc); CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc); +#else + ; #endif }