From 1f21e5497b7c61d5262027da3c52b75ed684dea5 Mon Sep 17 00:00:00 2001 From: Guillaume Bertholon Date: Wed, 21 Apr 2021 14:52:18 +0200 Subject: [PATCH] Control GL_FRAMEBUFFER_SRGB flag in RenderTarget This fixes wrong rendering for RenderTexture that need sRGB encoding along a non-sRGB window. We cannot simply always enable GL_FRAMEBUFFER_SRGB because some drivers enable sRGB encoding on non-sRGB window surfaces. Also add a isSrgb() method to tell if a RenderTarget is encoding into sRGB color space. --- include/SFML/Graphics/RenderTarget.hpp | 8 ++++++++ include/SFML/Graphics/RenderTexture.hpp | 12 ++++++++++++ include/SFML/Graphics/RenderWindow.hpp | 11 +++++++++++ src/SFML/Graphics/RenderTarget.cpp | 18 ++++++++++++++++++ src/SFML/Graphics/RenderTexture.cpp | 7 +++++++ src/SFML/Graphics/RenderTextureImpl.hpp | 11 +++++++++++ src/SFML/Graphics/RenderTextureImplDefault.cpp | 7 +++++++ src/SFML/Graphics/RenderTextureImplDefault.hpp | 11 +++++++++++ src/SFML/Graphics/RenderTextureImplFBO.cpp | 15 ++++++++++++--- src/SFML/Graphics/RenderTextureImplFBO.hpp | 12 ++++++++++++ src/SFML/Graphics/RenderWindow.cpp | 7 +++++++ 11 files changed, 116 insertions(+), 3 deletions(-) diff --git a/include/SFML/Graphics/RenderTarget.hpp b/include/SFML/Graphics/RenderTarget.hpp index da5a4c2c8..f9320af66 100644 --- a/include/SFML/Graphics/RenderTarget.hpp +++ b/include/SFML/Graphics/RenderTarget.hpp @@ -276,6 +276,14 @@ public: //////////////////////////////////////////////////////////// virtual Vector2u getSize() const = 0; + //////////////////////////////////////////////////////////// + /// \brief Tell if the render target will use sRGB encoding when drawing on it + /// + /// \return True if the render target use sRGB encoding, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool isSrgb() const; + //////////////////////////////////////////////////////////// /// \brief Activate or deactivate the render target for rendering /// diff --git a/include/SFML/Graphics/RenderTexture.hpp b/include/SFML/Graphics/RenderTexture.hpp index f35e49bdf..536e02679 100644 --- a/include/SFML/Graphics/RenderTexture.hpp +++ b/include/SFML/Graphics/RenderTexture.hpp @@ -217,6 +217,18 @@ public: //////////////////////////////////////////////////////////// virtual Vector2u getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Tell if the render-texture will use sRGB encoding when drawing on it + /// + /// You can request sRGB encoding for a render-texture + /// by having the sRgbCapable flag set for the context parameter of create() method + /// + /// \return True if the render-texture use sRGB encoding, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool isSrgb() const; + //////////////////////////////////////////////////////////// /// \brief Get a read-only reference to the target texture /// diff --git a/include/SFML/Graphics/RenderWindow.hpp b/include/SFML/Graphics/RenderWindow.hpp index dc52002cf..cd96279ef 100644 --- a/include/SFML/Graphics/RenderWindow.hpp +++ b/include/SFML/Graphics/RenderWindow.hpp @@ -112,6 +112,17 @@ public: //////////////////////////////////////////////////////////// virtual Vector2u getSize() const; + + //////////////////////////////////////////////////////////// + /// \brief Tell if the window will use sRGB encoding when drawing on it + /// + /// You can request sRGB encoding for a window by having the sRgbCapable flag set in the ContextSettings + /// + /// \return True if the window use sRGB encoding, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool isSrgb() const; + //////////////////////////////////////////////////////////// /// \brief Activate or deactivate the window as the current target /// for OpenGL rendering diff --git a/src/SFML/Graphics/RenderTarget.cpp b/src/SFML/Graphics/RenderTarget.cpp index 4576946da..9066d9960 100644 --- a/src/SFML/Graphics/RenderTarget.cpp +++ b/src/SFML/Graphics/RenderTarget.cpp @@ -411,6 +411,14 @@ void RenderTarget::draw(const VertexBuffer& vertexBuffer, std::size_t firstVerte } +//////////////////////////////////////////////////////////// +bool RenderTarget::isSrgb() const +{ + // By default sRGB encoding is not enabled for an arbitrary RenderTarget + return false; +} + + //////////////////////////////////////////////////////////// bool RenderTarget::setActive(bool active) { @@ -680,6 +688,16 @@ void RenderTarget::applyShader(const Shader* shader) //////////////////////////////////////////////////////////// void RenderTarget::setupDraw(bool useVertexCache, const RenderStates& states) { + // Enable or disable sRGB encoding + // This is needed for drivers that do not check the format of the surface drawn to before applying sRGB conversion + if (!m_cache.enable) + { + if (isSrgb()) + glCheck(glEnable(GL_FRAMEBUFFER_SRGB)); + else + glCheck(glDisable(GL_FRAMEBUFFER_SRGB)); + } + // First set the persistent OpenGL states if it's the very first call if (!m_cache.glStatesSet) resetGLStates(); diff --git a/src/SFML/Graphics/RenderTexture.cpp b/src/SFML/Graphics/RenderTexture.cpp index d66c31d27..e6783b3e6 100644 --- a/src/SFML/Graphics/RenderTexture.cpp +++ b/src/SFML/Graphics/RenderTexture.cpp @@ -180,6 +180,13 @@ Vector2u RenderTexture::getSize() const } +//////////////////////////////////////////////////////////// +bool RenderTexture::isSrgb() const +{ + return m_impl->isSrgb(); +} + + //////////////////////////////////////////////////////////// const Texture& RenderTexture::getTexture() const { diff --git a/src/SFML/Graphics/RenderTextureImpl.hpp b/src/SFML/Graphics/RenderTextureImpl.hpp index 47e6ca525..a31fcc2c4 100644 --- a/src/SFML/Graphics/RenderTextureImpl.hpp +++ b/src/SFML/Graphics/RenderTextureImpl.hpp @@ -75,6 +75,17 @@ public: //////////////////////////////////////////////////////////// virtual bool activate(bool active) = 0; + //////////////////////////////////////////////////////////// + /// \brief Tell if the render-texture will use sRGB encoding when drawing on it + /// + /// You can request sRGB encoding for a render-texture + /// by having the sRgbCapable flag set for the context parameter of create() method + /// + /// \return True if the render-texture use sRGB encoding, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool isSrgb() const = 0; + //////////////////////////////////////////////////////////// /// \brief Update the pixels of the target texture /// diff --git a/src/SFML/Graphics/RenderTextureImplDefault.cpp b/src/SFML/Graphics/RenderTextureImplDefault.cpp index d2555eacb..c3a700e31 100644 --- a/src/SFML/Graphics/RenderTextureImplDefault.cpp +++ b/src/SFML/Graphics/RenderTextureImplDefault.cpp @@ -85,6 +85,13 @@ bool RenderTextureImplDefault::activate(bool active) } +//////////////////////////////////////////////////////////// +bool RenderTextureImplDefault::isSrgb() const +{ + return m_context->getSettings().sRgbCapable; +} + + //////////////////////////////////////////////////////////// void RenderTextureImplDefault::updateTexture(unsigned int textureId) { diff --git a/src/SFML/Graphics/RenderTextureImplDefault.hpp b/src/SFML/Graphics/RenderTextureImplDefault.hpp index 5cdd65eb1..2507c8583 100644 --- a/src/SFML/Graphics/RenderTextureImplDefault.hpp +++ b/src/SFML/Graphics/RenderTextureImplDefault.hpp @@ -91,6 +91,17 @@ private: //////////////////////////////////////////////////////////// virtual bool activate(bool active); + //////////////////////////////////////////////////////////// + /// \brief Tell if the render-texture will use sRGB encoding when drawing on it + /// + /// You can request sRGB encoding for a render-texture + /// by having the sRgbCapable flag set for the context parameter of create() method + /// + /// \return True if the render-texture use sRGB encoding, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool isSrgb() const; + //////////////////////////////////////////////////////////// /// \brief Update the pixels of the target texture /// diff --git a/src/SFML/Graphics/RenderTextureImplFBO.cpp b/src/SFML/Graphics/RenderTextureImplFBO.cpp index bd83d6a52..9651d1f7b 100644 --- a/src/SFML/Graphics/RenderTextureImplFBO.cpp +++ b/src/SFML/Graphics/RenderTextureImplFBO.cpp @@ -120,7 +120,8 @@ m_height (0), m_context (NULL), m_textureId (0), m_multisample (false), -m_stencil (false) +m_stencil (false), +m_sRgb (false) { Lock lock(mutex); @@ -228,6 +229,8 @@ bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsig if (settings.stencilBits && !GLEXT_packed_depth_stencil) return false; + m_sRgb = settings.sRgbCapable && GL_EXT_texture_sRGB; + #ifndef SFML_OPENGL_ES // Check if the requested anti-aliasing level is supported @@ -296,7 +299,6 @@ bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsig #ifndef SFML_OPENGL_ES // Create the multisample color buffer - bool srgb = settings.sRgbCapable && GLEXT_texture_sRGB; GLuint color = 0; glCheck(GLEXT_glGenRenderbuffers(1, &color)); m_colorBuffer = static_cast(color); @@ -306,7 +308,7 @@ bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsig return false; } glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_colorBuffer)); - glCheck(GLEXT_glRenderbufferStorageMultisample(GLEXT_GL_RENDERBUFFER, settings.antialiasingLevel, srgb ? GL_SRGB8_ALPHA8_EXT : GL_RGBA, width, height)); + glCheck(GLEXT_glRenderbufferStorageMultisample(GLEXT_GL_RENDERBUFFER, settings.antialiasingLevel, m_sRgb ? GL_SRGB8_ALPHA8_EXT : GL_RGBA, width, height)); // Create the multisample depth/stencil buffer if requested if (settings.stencilBits) @@ -568,6 +570,13 @@ bool RenderTextureImplFBO::activate(bool active) } +//////////////////////////////////////////////////////////// +bool RenderTextureImplFBO::isSrgb() const +{ + return m_sRgb; +} + + //////////////////////////////////////////////////////////// void RenderTextureImplFBO::updateTexture(unsigned int) { diff --git a/src/SFML/Graphics/RenderTextureImplFBO.hpp b/src/SFML/Graphics/RenderTextureImplFBO.hpp index 55a9b7cfe..14ebe8e7b 100644 --- a/src/SFML/Graphics/RenderTextureImplFBO.hpp +++ b/src/SFML/Graphics/RenderTextureImplFBO.hpp @@ -114,6 +114,17 @@ private: //////////////////////////////////////////////////////////// virtual bool activate(bool active); + //////////////////////////////////////////////////////////// + /// \brief Tell if the render-texture will use sRGB encoding when drawing on it + /// + /// You can request sRGB encoding for a render-texture + /// by having the sRgbCapable flag set for the context parameter of create() method + /// + /// \return True if the render-texture use sRGB encoding, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool isSrgb() const; + //////////////////////////////////////////////////////////// /// \brief Update the pixels of the target texture /// @@ -135,6 +146,7 @@ private: unsigned int m_textureId; //!< The ID of the texture to attach to the FBO bool m_multisample; //!< Whether we have to create a multisample frame buffer as well bool m_stencil; //!< Whether we have stencil attachment + bool m_sRgb; //!< Whether we need to encode drawn pixels into sRGB color space }; } // namespace priv diff --git a/src/SFML/Graphics/RenderWindow.cpp b/src/SFML/Graphics/RenderWindow.cpp index 9a98836d4..3dc4b6dd8 100644 --- a/src/SFML/Graphics/RenderWindow.cpp +++ b/src/SFML/Graphics/RenderWindow.cpp @@ -73,6 +73,13 @@ Vector2u RenderWindow::getSize() const } +//////////////////////////////////////////////////////////// +bool RenderWindow::isSrgb() const +{ + return getSettings().sRgbCapable; +} + + //////////////////////////////////////////////////////////// bool RenderWindow::setActive(bool active) {