diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 01290f53e653..0c2ee25ad86e 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -305,7 +305,8 @@ FramebufferManager::FramebufferManager() : shaderManager_(0), usePostShader_(false), postShaderAtOutputResolution_(false), - resized_(false) + resized_(false), + renderCopy_(0) #ifndef USING_GLES2 , pixelBufObj_(0), @@ -919,6 +920,48 @@ void FramebufferManager::SetLineWidth() { #endif } +void FramebufferManager::BindFramebufferColor(VirtualFramebuffer *framebuffer) { + if (!framebuffer->fbo || !useBufferedRendering_) { + glBindTexture(GL_TEXTURE_2D, 0); + gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE; + return; + } + + if (MaskedEqual(framebuffer->fb_address, gstate.getFrameBufRawAddress())) { +#ifndef USING_GLES2 + if (gl_extensions.FBO_ARB) { +#else + if (gl_extensions.GLES3) { +#endif +#ifdef MAY_HAVE_GLES3 + + // TODO: Maybe merge with bvfbs_? Not sure if those could be packing, and they're created at a different size. + if (!renderCopy_ || renderCopyWidth_ != framebuffer->renderWidth || renderCopyHeight_ != framebuffer->renderHeight) { + if (renderCopy_) + fbo_destroy(renderCopy_); + renderCopy_ = fbo_create(framebuffer->renderWidth, framebuffer->renderHeight, 1, true, framebuffer->colorDepth); + renderCopyWidth_ = framebuffer->renderWidth; + renderCopyHeight_ = framebuffer->renderHeight; + } + + fbo_bind_as_render_target(renderCopy_); + glViewport(0, 0, framebuffer->renderWidth, framebuffer->renderHeight); + fbo_bind_for_read(framebuffer->fbo); + glBlitFramebuffer(0, 0, framebuffer->renderWidth, framebuffer->renderHeight, 0, 0, framebuffer->renderWidth, framebuffer->renderHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + fbo_bind_as_render_target(currentRenderVfb_->fbo); + if (gl_extensions.gpuVendor != GPU_VENDOR_POWERVR) + glstate.viewport.restore(); + fbo_bind_color_as_texture(renderCopy_, 0); +#endif + } else { + fbo_bind_color_as_texture(framebuffer->fbo, 0); + } + } else { + fbo_bind_color_as_texture(framebuffer->fbo, 0); + } +} + void FramebufferManager::CopyDisplayToOutput() { fbo_unbind(); glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index 0cbc2a093a8a..6a0bce31c3aa 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -138,6 +138,9 @@ class FramebufferManager { void UpdateFromMemory(u32 addr, int size, bool safe); void SetLineWidth(); + // For use when texturing from a framebuffer. May create a duplicate if target. + void BindFramebufferColor(VirtualFramebuffer *framebuffer); + #ifdef USING_GLES2 void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync = true); #else @@ -223,6 +226,9 @@ class FramebufferManager { bool useBufferedRendering_; std::vector bvfbs_; // blitting FBOs + FBO *renderCopy_; + int renderCopyWidth_; + int renderCopyHeight_; std::set> knownFramebufferCopies_; diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index 55b8b99e1bf9..e738479f64dc 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -397,6 +397,7 @@ GLES_GPU::GLES_GPU() transformDraw_.SetFramebufferManager(&framebufferManager_); framebufferManager_.SetTextureCache(&textureCache_); framebufferManager_.SetShaderManager(shaderManager_); + textureCache_.SetFramebufferManager(&framebufferManager_); // Sanity check gstate if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) { diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index edcfa0241f7c..fc7c23f4bab1 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -830,22 +830,15 @@ bool SetDebugTexture() { } #endif -void TextureCache::SetTextureFramebuffer(TexCacheEntry *entry) -{ +void TextureCache::SetTextureFramebuffer(TexCacheEntry *entry) { entry->framebuffer->usageFlags |= FB_USAGE_TEXTURE; bool useBufferedRendering = g_Config.iRenderingMode != FB_NON_BUFFERED_MODE; if (useBufferedRendering) { - // For now, let's not bind FBOs that we know are off (invalidHint will be -1.) - // But let's still not use random memory. - if (entry->framebuffer->fbo) { - fbo_bind_color_as_texture(entry->framebuffer->fbo, 0); - // Keep the framebuffer alive. - // TODO: Dangerous if it sets a new one? - entry->framebuffer->last_frame_used = gpuStats.numFlips; - } else { - glBindTexture(GL_TEXTURE_2D, 0); - gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE; - } + framebufferManager_->BindFramebufferColor(entry->framebuffer); + + // Keep the framebuffer alive. + entry->framebuffer->last_frame_used = gpuStats.numFlips; + // We need to force it, since we may have set it on a texture before attaching. UpdateSamplingParams(*entry, true); gstate_c.curTextureWidth = entry->framebuffer->width; @@ -883,11 +876,6 @@ void TextureCache::SetTexture(bool force) { int w = gstate.getTextureWidth(0); int h = gstate.getTextureHeight(0); - u32 fb_addr = gstate.getFrameBufRawAddress() | 0x04000000; - if (fb_addr == gstate.getTextureAddress(0)) { - WARN_LOG_REPORT(HLE, "Texturing from same buffer as target (%08x : %ix%i)", fb_addr, w, h); - } - GETextureFormat format = gstate.getTextureFormat(); if (format >= 11) { ERROR_LOG_REPORT(G3D, "Unknown texture format %i", format); diff --git a/GPU/GLES/TextureCache.h b/GPU/GLES/TextureCache.h index c48474851b55..5516f7f301c2 100644 --- a/GPU/GLES/TextureCache.h +++ b/GPU/GLES/TextureCache.h @@ -24,6 +24,7 @@ #include "TextureScaler.h" struct VirtualFramebuffer; +class FramebufferManager; enum TextureFiltering { AUTO = 1, @@ -56,6 +57,10 @@ class TextureCache { // are being rendered to. This is barebones so far. void NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer, FramebufferNotification msg); + void SetFramebufferManager(FramebufferManager *fbManager) { + framebufferManager_ = fbManager; + } + size_t NumLoadedTextures() const { return cache.size(); } @@ -160,5 +165,6 @@ class TextureCache { float maxAnisotropyLevel; int decimationCounter_; + FramebufferManager *framebufferManager_; };