diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp index e64b4f3ad8..c356be9c61 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp @@ -385,19 +385,6 @@ XFBSource::~XFBSource() glDeleteTextures(1, &texture); } - -void XFBSource::Draw(const MathUtil::Rectangle &sourcerc, - const MathUtil::Rectangle &drawrc) const -{ - // Texture map xfbSource->texture onto the main buffer - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); - glBlitFramebuffer(sourcerc.left, sourcerc.bottom, sourcerc.right, sourcerc.top, - (int)drawrc.left, (int)drawrc.bottom, (int)drawrc.right, (int)drawrc.top, - GL_COLOR_BUFFER_BIT, GL_LINEAR); - - GL_REPORT_ERRORD(); -} - void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) { TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, texture); diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.h b/Source/Core/VideoBackends/OGL/FramebufferManager.h index 93aedb3501..1d0670408e 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.h +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.h @@ -52,8 +52,6 @@ struct XFBSource : public XFBSourceBase void CopyEFB(float Gamma) override; void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) override; - void Draw(const MathUtil::Rectangle &sourcerc, - const MathUtil::Rectangle &drawrc) const override; const GLuint texture; }; diff --git a/Source/Core/VideoBackends/OGL/PostProcessing.cpp b/Source/Core/VideoBackends/OGL/PostProcessing.cpp index 648ed5c76a..519406cb0f 100644 --- a/Source/Core/VideoBackends/OGL/PostProcessing.cpp +++ b/Source/Core/VideoBackends/OGL/PostProcessing.cpp @@ -19,65 +19,38 @@ namespace OGL static char s_vertex_shader[] = "out vec2 uv0;\n" + "uniform vec4 src_rect;\n" "void main(void) {\n" " vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n" " gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n" - " uv0 = rawpos;\n" + " uv0 = rawpos * src_rect.zw + src_rect.xy;\n" "}\n"; OpenGLPostProcessing::OpenGLPostProcessing() { - m_enable = false; - m_width = 0; - m_height = 0; - - glGenFramebuffers(1, &m_fbo); - glGenTextures(1, &m_texture); - glBindTexture(GL_TEXTURE_2D, m_texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); // disable mipmaps - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0); - FramebufferManager::SetFramebuffer(0); - CreateHeader(); + m_initialized = false; } OpenGLPostProcessing::~OpenGLPostProcessing() { m_shader.Destroy(); - - glDeleteFramebuffers(1, &m_fbo); - glDeleteTextures(1, &m_texture); } -void OpenGLPostProcessing::BindTargetFramebuffer() +void OpenGLPostProcessing::BlitFromTexture(TargetRectangle src, TargetRectangle dst, + int src_texture, int src_width, int src_height) { - if (m_enable) - { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo); - // Clear the buffer so there isn't any remaining garbage from the previous post processing shader frame - glClear(GL_COLOR_BUFFER_BIT); - } - else - { - // Bind to default framebuffer if we aren't post processing - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - } -} - -void OpenGLPostProcessing::BlitToScreen() -{ - if (!m_enable) return; + ApplyShader(); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glViewport(0, 0, m_width, m_height); + + glViewport(dst.left, dst.bottom, dst.GetWidth(), dst.GetHeight()); m_shader.Bind(); - glUniform4f(m_uniform_resolution, (float)m_width, (float)m_height, 1.0f/(float)m_width, 1.0f/(float)m_height); + glUniform4f(m_uniform_resolution, (float)src_width, (float)src_height, 1.0f / (float)src_width, 1.0f / (float)src_height); + glUniform4f(m_uniform_src_rect, src.left / (float) src_width, src.bottom / (float) src_height, + src.GetWidth() / (float) src_width, src.GetHeight() / (float) src_height); glUniform1ui(m_uniform_time, (GLuint)m_timer.GetTimeElapsed()); if (m_config.IsDirty()) @@ -151,45 +124,27 @@ void OpenGLPostProcessing::BlitToScreen() } glActiveTexture(GL_TEXTURE0+9); - glBindTexture(GL_TEXTURE_2D, m_texture); + glBindTexture(GL_TEXTURE_2D, src_texture); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } -void OpenGLPostProcessing::Update(u32 width, u32 height) -{ - ApplyShader(); - - if (m_enable && (width != m_width || height != m_height)) - { - m_width = width; - m_height = height; - - // alloc texture for framebuffer - glActiveTexture(GL_TEXTURE0+9); - glBindTexture(GL_TEXTURE_2D, m_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - } -} - void OpenGLPostProcessing::ApplyShader() { // shader didn't changed - if (m_config.GetShader() == g_ActiveConfig.sPostProcessingShader) + if (m_initialized && m_config.GetShader() == g_ActiveConfig.sPostProcessingShader) return; - m_enable = false; m_shader.Destroy(); m_uniform_bindings.clear(); - // shader disabled - if (g_ActiveConfig.sPostProcessingShader == "") - return; - - // so need to compile shader - std::string code = m_config.LoadShader(); + // load shader from disk + std::string default_shader = "void main() { SetOutput(Sample()); }"; + std::string code = ""; + if (g_ActiveConfig.sPostProcessingShader != "") + code = m_config.LoadShader(); if (code == "") - return; + code = default_shader; code = LoadShaderOptions(code); @@ -197,21 +152,22 @@ void OpenGLPostProcessing::ApplyShader() if (!ProgramShaderCache::CompileShader(m_shader, s_vertex_shader, code.c_str())) { ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", m_config.GetShader().c_str()); - return; + + code = LoadShaderOptions(default_shader); + ProgramShaderCache::CompileShader(m_shader, s_vertex_shader, code.c_str()); } // read uniform locations m_uniform_resolution = glGetUniformLocation(m_shader.glprogid, "resolution"); m_uniform_time = glGetUniformLocation(m_shader.glprogid, "time"); + m_uniform_src_rect = glGetUniformLocation(m_shader.glprogid, "src_rect"); for (const auto& it : m_config.GetOptions()) { std::string glsl_name = "option_" + it.first; m_uniform_bindings[it.first] = glGetUniformLocation(m_shader.glprogid, glsl_name.c_str()); } - - // successful - m_enable = true; + m_initialized = true; } void OpenGLPostProcessing::CreateHeader() diff --git a/Source/Core/VideoBackends/OGL/PostProcessing.h b/Source/Core/VideoBackends/OGL/PostProcessing.h index 6aa93cc9a5..58dcb53609 100644 --- a/Source/Core/VideoBackends/OGL/PostProcessing.h +++ b/Source/Core/VideoBackends/OGL/PostProcessing.h @@ -21,16 +21,15 @@ public: OpenGLPostProcessing(); ~OpenGLPostProcessing(); - void BindTargetFramebuffer() override; - void BlitToScreen() override; - void Update(u32 width, u32 height) override; + void BlitFromTexture(TargetRectangle src, TargetRectangle dst, + int src_texture, int src_width, int src_height) override; void ApplyShader() override; private: - GLuint m_fbo; - GLuint m_texture; + bool m_initialized; SHADER m_shader; GLuint m_uniform_resolution; + GLuint m_uniform_src_rect; GLuint m_uniform_time; std::string m_glsl_header; diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 6bd9004808..1511bad54d 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1395,7 +1395,6 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co ResetAPIState(); - m_post_processor->Update(s_backbuffer_width, s_backbuffer_height); UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height); TargetRectangle flipped_trc = GetTargetRectangle(); @@ -1412,29 +1411,20 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co GL_REPORT_ERRORD(); // Copy the framebuffer to screen. - - const XFBSourceBase* xfbSource = nullptr; + const XFBSource* xfbSource = nullptr; if (g_ActiveConfig.bUseXFB) { - // Render to the real/postprocessing buffer now. - m_post_processor->BindTargetFramebuffer(); - // draw each xfb source - glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer()); - for (u32 i = 0; i < xfbCount; ++i) { - xfbSource = xfbSourceList[i]; + xfbSource = (const XFBSource*) xfbSourceList[i]; - MathUtil::Rectangle drawRc; + TargetRectangle drawRc; if (g_ActiveConfig.bUseRealXFB) { - drawRc.top = static_cast(flipped_trc.top); - drawRc.bottom = static_cast(flipped_trc.bottom); - drawRc.left = static_cast(flipped_trc.left); - drawRc.right = static_cast(flipped_trc.right); + drawRc = flipped_trc; } else { @@ -1443,17 +1433,10 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co int xfbWidth = xfbSource->srcWidth; int hOffset = ((s32)xfbSource->srcAddr - (s32)xfbAddr) / ((s32)fbStride * 2); - MathUtil::Rectangle rect_u32; - - rect_u32.top = flipped_trc.top - hOffset * flipped_trc.GetHeight() / fbHeight; - rect_u32.bottom = flipped_trc.top - (hOffset + xfbHeight) * flipped_trc.GetHeight() / fbHeight; - rect_u32.left = flipped_trc.left + (flipped_trc.GetWidth() - xfbWidth * flipped_trc.GetWidth() / fbStride)/2; - rect_u32.right = flipped_trc.left + (flipped_trc.GetWidth() + xfbWidth * flipped_trc.GetWidth() / fbStride)/2; - - drawRc.top = static_cast(rect_u32.top); - drawRc.bottom = static_cast(rect_u32.bottom); - drawRc.left = static_cast(rect_u32.left); - drawRc.right = static_cast(rect_u32.right); + drawRc.top = flipped_trc.top - hOffset * flipped_trc.GetHeight() / fbHeight; + drawRc.bottom = flipped_trc.top - (hOffset + xfbHeight) * flipped_trc.GetHeight() / fbHeight; + drawRc.left = flipped_trc.left + (flipped_trc.GetWidth() - xfbWidth * flipped_trc.GetWidth() / fbStride) / 2; + drawRc.right = flipped_trc.left + (flipped_trc.GetWidth() + xfbWidth * flipped_trc.GetWidth() / fbStride) / 2; // The following code disables auto stretch. Kept for reference. // scale draw area for a 1 to 1 pixel mapping with the draw target @@ -1467,7 +1450,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co // Tell the OSD Menu about the current internal resolution OSDInternalW = xfbSource->sourceRc.GetWidth(); OSDInternalH = xfbSource->sourceRc.GetHeight(); - MathUtil::Rectangle sourceRc; + TargetRectangle sourceRc; sourceRc.left = xfbSource->sourceRc.left; sourceRc.right = xfbSource->sourceRc.right; sourceRc.top = xfbSource->sourceRc.top; @@ -1475,7 +1458,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co sourceRc.right -= fbStride - fbWidth; - xfbSource->Draw(sourceRc, drawRc); + m_post_processor->BlitFromTexture(sourceRc, drawRc, xfbSource->texture, xfbSource->texWidth, xfbSource->texHeight); } } else @@ -1483,22 +1466,11 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co TargetRectangle targetRc = ConvertEFBRectangle(rc); // for msaa mode, we must resolve the efb content to non-msaa - FramebufferManager::ResolveAndGetRenderTarget(rc); + GLuint tex = FramebufferManager::ResolveAndGetRenderTarget(rc); - // Render to the real/postprocessing buffer now. (resolve have changed this in msaa mode) - m_post_processor->BindTargetFramebuffer(); - - // always the non-msaa fbo - GLuint fb = s_MSAASamples>1?FramebufferManager::GetResolvedFramebuffer():FramebufferManager::GetEFBFramebuffer(); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, fb); - glBlitFramebuffer(targetRc.left, targetRc.bottom, targetRc.right, targetRc.top, - flipped_trc.left, flipped_trc.bottom, flipped_trc.right, flipped_trc.top, - GL_COLOR_BUFFER_BIT, GL_LINEAR); + m_post_processor->BlitFromTexture(targetRc, flipped_trc, tex, s_target_width, s_target_height); } - m_post_processor->BlitToScreen(); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); // Save screenshot diff --git a/Source/Core/VideoCommon/FramebufferManagerBase.h b/Source/Core/VideoCommon/FramebufferManagerBase.h index bd9eef5037..50813539ab 100644 --- a/Source/Core/VideoCommon/FramebufferManagerBase.h +++ b/Source/Core/VideoCommon/FramebufferManagerBase.h @@ -14,7 +14,7 @@ struct XFBSourceBase virtual ~XFBSourceBase() {} virtual void Draw(const MathUtil::Rectangle &sourcerc, - const MathUtil::Rectangle &drawrc) const = 0; + const MathUtil::Rectangle &drawrc) const {}; virtual void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) = 0; diff --git a/Source/Core/VideoCommon/PostProcessing.h b/Source/Core/VideoCommon/PostProcessing.h index 0f539dbb05..68ab47cff6 100644 --- a/Source/Core/VideoCommon/PostProcessing.h +++ b/Source/Core/VideoCommon/PostProcessing.h @@ -11,6 +11,8 @@ #include "Common/StringUtil.h" #include "Common/Timer.h" +#include "VideoCommon/VideoCommon.h" + class PostProcessingShaderConfiguration { public: @@ -88,15 +90,11 @@ public: PostProcessingShaderConfiguration* GetConfig() { return &m_config; } // Should be implemented by the backends for backend specific code - virtual void BindTargetFramebuffer() = 0; - virtual void BlitToScreen() = 0; - virtual void Update(u32 width, u32 height) = 0; + virtual void BlitFromTexture(TargetRectangle src, TargetRectangle dst, + int src_texture, int src_width, int src_height) = 0; virtual void ApplyShader() = 0; protected: - bool m_enable; - u32 m_width; - u32 m_height; // Timer for determining our time value Common::Timer m_timer;