From 33e1d2736d034dceb8b23c2385b5b409b1bd76f9 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 25 Apr 2015 21:32:10 -0300 Subject: [PATCH] Removed restrictions preventing sRGB and non-sRGB canvases from being used together when doing multi-canvas rendering. --- src/modules/graphics/opengl/Canvas.cpp | 63 ++++++++++++------------ src/modules/graphics/opengl/Graphics.cpp | 7 +-- src/modules/graphics/opengl/OpenGL.cpp | 23 +++++++++ src/modules/graphics/opengl/OpenGL.h | 12 +++++ 4 files changed, 68 insertions(+), 37 deletions(-) diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index 2e9f9aa16..bb363382c 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -397,15 +397,6 @@ void Canvas::setupGrab() // Set up the projection matrix gl.matrices.projection.push_back(Matrix::ortho(0.0, (float) width, 0.0, (float) height)); - - // Make sure the correct sRGB setting is used when drawing to the canvas. - if (GLAD_VERSION_1_0 || GLAD_EXT_sRGB_write_control) - { - if (format == FORMAT_SRGB) - glEnable(GL_FRAMEBUFFER_SRGB); - else if (screenHasSRGB) - glDisable(GL_FRAMEBUFFER_SRGB); - } } void Canvas::startGrab(const std::vector &canvases) @@ -413,6 +404,7 @@ void Canvas::startGrab(const std::vector &canvases) // Whether the new canvas list is different from the old one. // A more thorough check is done below. bool canvaseschanged = canvases.size() != attachedCanvases.size(); + bool hasSRGBcanvas = (format == FORMAT_SRGB); if (canvases.size() > 0) { @@ -435,26 +427,32 @@ void Canvas::startGrab(const std::vector &canvases) Format otherformat = canvases[i]->getTextureFormat(); - if (otherformat != format) - { - if (!multiformatsupported) - throw love::Exception("This system doesn't support multi-canvas rendering with different canvas formats."); - else if (otherformat == FORMAT_SRGB || format == FORMAT_SRGB) - // Driver bugs related to enabling GL_FRAMEBUFFER_SRGB... - throw love::Exception("sRGB and non-sRGB canvas formats cannot be mixed when using multi-canvas rendering."); - } + if (otherformat != format && !multiformatsupported) + throw love::Exception("This system doesn't support multi-canvas rendering with different canvas formats."); if (canvases[i]->getMSAA() != 0) throw love::Exception("Multi-canvas rendering is not supported with MSAA."); if (!canvaseschanged && canvases[i] != attachedCanvases[i]) canvaseschanged = true; + + if (otherformat == FORMAT_SRGB) + hasSRGBcanvas = true; } OpenGL::TempDebugGroup debuggroup("Canvas set"); setupGrab(); + // Make sure the correct sRGB setting is used when drawing to the canvases. + if (GLAD_VERSION_1_0 || GLAD_EXT_sRGB_write_control) + { + if (hasSRGBcanvas && !gl.hasFramebufferSRGB()) + gl.setFramebufferSRGB(true); + else if (!hasSRGBcanvas && gl.hasFramebufferSRGB()) + gl.setFramebufferSRGB(false); + } + // Don't attach anything if there's nothing to change. if (!canvaseschanged) return; @@ -489,10 +487,19 @@ void Canvas::startGrab() setupGrab(); + // Make sure the correct sRGB setting is used when drawing to the canvas. + if (GLAD_VERSION_1_0 || GLAD_EXT_sRGB_write_control) + { + if (format == FORMAT_SRGB && !gl.hasFramebufferSRGB()) + gl.setFramebufferSRGB(true); + else if (format != FORMAT_SRGB && gl.hasFramebufferSRGB()) + gl.setFramebufferSRGB(false); + } + if (attachedCanvases.size() == 0) return; - // make sure the FBO is only using a single draw buffer + // Make sure the FBO is only using a single draw buffer. glDrawBuffer(GL_COLOR_ATTACHMENT0); attachedCanvases.clear(); @@ -511,15 +518,7 @@ void Canvas::stopGrab(bool switchingToOtherCanvas) gl.matrices.projection.pop_back(); - if (switchingToOtherCanvas) - { - if (GLAD_VERSION_1_0 || GLAD_EXT_sRGB_write_control) - { - if (format == FORMAT_SRGB) - glDisable(GL_FRAMEBUFFER_SRGB); - } - } - else + if (!switchingToOtherCanvas) { // bind system framebuffer. gl.bindFramebuffer(GL_FRAMEBUFFER, gl.getDefaultFBO()); @@ -528,10 +527,10 @@ void Canvas::stopGrab(bool switchingToOtherCanvas) if (GLAD_VERSION_1_0 || GLAD_EXT_sRGB_write_control) { - if (format == FORMAT_SRGB && !screenHasSRGB) - glDisable(GL_FRAMEBUFFER_SRGB); - else if (format != FORMAT_SRGB && screenHasSRGB) - glEnable(GL_FRAMEBUFFER_SRGB); + if (screenHasSRGB && !gl.hasFramebufferSRGB()) + gl.setFramebufferSRGB(true); + else if (!screenHasSRGB && gl.hasFramebufferSRGB()) + gl.setFramebufferSRGB(false); } } } @@ -631,6 +630,8 @@ bool Canvas::resolveMSAA(bool restoreprev) if (resolve_fbo == 0 || msaa_buffer == 0) return false; + OpenGL::TempDebugGroup debuggroup("Canvas MSAA resolve"); + GLint w = width; GLint h = height; diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 830fad24f..dc8419d17 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -270,12 +270,7 @@ bool Graphics::setMode(int width, int height, bool &sRGB) || GLAD_ES_VERSION_3_0 || GLAD_EXT_sRGB) { if (GLAD_VERSION_1_0 || GLAD_EXT_sRGB_write_control) - { - if (sRGB) - glEnable(GL_FRAMEBUFFER_SRGB); - else - glDisable(GL_FRAMEBUFFER_SRGB); - } + gl.setFramebufferSRGB(sRGB); } else sRGB = false; diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 8bfd89479..a98ba93d5 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -103,6 +103,14 @@ void OpenGL::setupContext() else state.pointSize = 1.0f; + if (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB + || GLAD_EXT_sRGB_write_control) + { + state.framebufferSRGBEnabled = (glIsEnabled(GL_FRAMEBUFFER_SRGB) == GL_TRUE); + } + else + state.framebufferSRGBEnabled = false; + // Initialize multiple texture unit support for shaders. state.boundTextures.clear(); state.boundTextures.resize(maxTextureUnits, 0); @@ -427,6 +435,21 @@ float OpenGL::getPointSize() const return state.pointSize; } +void OpenGL::setFramebufferSRGB(bool enable) +{ + if (enable) + glEnable(GL_FRAMEBUFFER_SRGB); + else + glDisable(GL_FRAMEBUFFER_SRGB); + + state.framebufferSRGBEnabled = enable; +} + +bool OpenGL::hasFramebufferSRGB() const +{ + return state.framebufferSRGBEnabled; +} + void OpenGL::bindFramebuffer(GLenum target, GLuint framebuffer) { glBindFramebuffer(target, framebuffer); diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index 62d60ca1d..466c9aa33 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -238,6 +238,16 @@ public: **/ float getPointSize() const; + /** + * Calls glEnable/glDisable(GL_FRAMEBUFFER_SRGB). + **/ + void setFramebufferSRGB(bool enable); + + /** + * Equivalent to glIsEnabled(GL_FRAMEBUFFER_SRGB). + **/ + bool hasFramebufferSRGB() const; + /** * Binds a Framebuffer Object to the specified target. **/ @@ -360,6 +370,8 @@ private: float pointSize; + bool framebufferSRGBEnabled; + GLuint defaultTexture; Matrix lastProjectionMatrix;