From 67ef7fea3ebaa85e976d48d67ed2273cfadf217a Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 23 Jun 2013 17:05:59 +0200 Subject: [PATCH] Various FBO-related fixes, hopefully reducing or removing the related crashes... --- GPU/GLES/Framebuffer.cpp | 37 ++++++++++++++++++++++++++++++++----- GPU/GLES/Framebuffer.h | 4 +++- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index c511789314..1082b0517d 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -324,6 +324,18 @@ void GuessDrawingSize(int &drawing_width, int &drawing_height) { drawing_height = std::min(drawing_height, 512); } +void FramebufferManager::NotifyDestroyed(VirtualFramebuffer *v) { + // Wipe some pointers + if (currentRenderVfb_ == v) + currentRenderVfb_ = 0; + if (displayFramebuf_ == v) + displayFramebuf_ = 0; + if (prevDisplayFramebuf_ == v) + prevDisplayFramebuf_ = 0; + if (prevPrevDisplayFramebuf_ == v) + prevPrevDisplayFramebuf_ = 0; +} + void FramebufferManager::SetRenderFrameBuffer() { if (!gstate_c.framebufChanged && currentRenderVfb_) { currentRenderVfb_->last_frame_used = gpuStats.numFrames; @@ -375,8 +387,16 @@ void FramebufferManager::SetRenderFrameBuffer() { // To do this right we should copy the data over too, but meh. buffer_width = std::max((int)v->width, drawing_width); buffer_height = std::max((int)v->height, drawing_height); + + textureCache_->NotifyFramebufferDestroyed(v->fb_address, v); + if (v->fbo) { + fbo_destroy(v->fbo); + v->fbo = 0; + } + NotifyDestroyed(v); + delete v; - vfbs_.erase(iter); + vfbs_.erase(iter++); break; } } @@ -432,7 +452,11 @@ void FramebufferManager::SetRenderFrameBuffer() { if (useBufferedRendering_) { vfb->fbo = fbo_create(vfb->renderWidth, vfb->renderHeight, 1, true, vfb->colorDepth); - fbo_bind_as_render_target(vfb->fbo); + if (vfb->fbo) { + fbo_bind_as_render_target(vfb->fbo); + } else { + ERROR_LOG(HLE, "Error creating FBO! %i x %i", vfb->renderWidth, vfb->renderHeight); + } } else { fbo_unbind(); // Let's ignore rendering to targets that have not (yet) been displayed. @@ -649,14 +673,14 @@ std::vector FramebufferManager::GetFramebufferList() { void FramebufferManager::DecimateFBOs() { fbo_unbind(); currentRenderVfb_ = 0; - + retry: for (auto iter = vfbs_.begin(); iter != vfbs_.end();) { VirtualFramebuffer *vfb = *iter; if (vfb == displayFramebuf_ || vfb == prevDisplayFramebuf_ || vfb == prevPrevDisplayFramebuf_) { ++iter; continue; } - int age = frameLastFramebufUsed - (*iter)->last_frame_used; + int age = frameLastFramebufUsed - (*iter)->last_frame_used; if (age > FBO_OLD_AGE) { textureCache_->NotifyFramebufferDestroyed(vfb->fb_address, vfb); INFO_LOG(HLE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age) @@ -664,8 +688,10 @@ void FramebufferManager::DecimateFBOs() { fbo_destroy(vfb->fbo); vfb->fbo = 0; } + NotifyDestroyed(vfb); delete vfb; - vfbs_.erase(iter++); + vfbs_.erase(iter); + goto retry; } else ++iter; @@ -687,6 +713,7 @@ void FramebufferManager::DestroyAllFBOs() { fbo_destroy(vfb->fbo); vfb->fbo = 0; } + NotifyDestroyed(vfb); delete vfb; } vfbs_.clear(); diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index 8abe456b7d..ba4a279530 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -124,6 +124,8 @@ public: return displayFramebuf_ ? (0x04000000 | displayFramebuf_->fb_address) : 0; } + void NotifyDestroyed(VirtualFramebuffer *vfb); + private: u32 ramDisplayFramebufPtr_; // workaround for MotoGP insanity u32 displayFramebufPtr_; @@ -135,7 +137,7 @@ private: VirtualFramebuffer *prevPrevDisplayFramebuf_; int frameLastFramebufUsed; - std::list vfbs_; + std::vector vfbs_; VirtualFramebuffer *currentRenderVfb_;