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.
This commit is contained in:
Guillaume Bertholon 2021-04-21 14:52:18 +02:00 committed by Lukas Dürrenberger
parent ade4a3912a
commit 1f21e5497b
11 changed files with 116 additions and 3 deletions

View File

@ -276,6 +276,14 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual Vector2u getSize() const = 0; 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 /// \brief Activate or deactivate the render target for rendering
/// ///

View File

@ -217,6 +217,18 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual Vector2u getSize() const; 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 /// \brief Get a read-only reference to the target texture
/// ///

View File

@ -112,6 +112,17 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual Vector2u getSize() const; 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 /// \brief Activate or deactivate the window as the current target
/// for OpenGL rendering /// for OpenGL rendering

View File

@ -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) bool RenderTarget::setActive(bool active)
{ {
@ -680,6 +688,16 @@ void RenderTarget::applyShader(const Shader* shader)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void RenderTarget::setupDraw(bool useVertexCache, const RenderStates& states) 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 // First set the persistent OpenGL states if it's the very first call
if (!m_cache.glStatesSet) if (!m_cache.glStatesSet)
resetGLStates(); resetGLStates();

View File

@ -180,6 +180,13 @@ Vector2u RenderTexture::getSize() const
} }
////////////////////////////////////////////////////////////
bool RenderTexture::isSrgb() const
{
return m_impl->isSrgb();
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
const Texture& RenderTexture::getTexture() const const Texture& RenderTexture::getTexture() const
{ {

View File

@ -75,6 +75,17 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual bool activate(bool active) = 0; 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 /// \brief Update the pixels of the target texture
/// ///

View File

@ -85,6 +85,13 @@ bool RenderTextureImplDefault::activate(bool active)
} }
////////////////////////////////////////////////////////////
bool RenderTextureImplDefault::isSrgb() const
{
return m_context->getSettings().sRgbCapable;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void RenderTextureImplDefault::updateTexture(unsigned int textureId) void RenderTextureImplDefault::updateTexture(unsigned int textureId)
{ {

View File

@ -91,6 +91,17 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual bool activate(bool active); 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 /// \brief Update the pixels of the target texture
/// ///

View File

@ -120,7 +120,8 @@ m_height (0),
m_context (NULL), m_context (NULL),
m_textureId (0), m_textureId (0),
m_multisample (false), m_multisample (false),
m_stencil (false) m_stencil (false),
m_sRgb (false)
{ {
Lock lock(mutex); Lock lock(mutex);
@ -228,6 +229,8 @@ bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsig
if (settings.stencilBits && !GLEXT_packed_depth_stencil) if (settings.stencilBits && !GLEXT_packed_depth_stencil)
return false; return false;
m_sRgb = settings.sRgbCapable && GL_EXT_texture_sRGB;
#ifndef SFML_OPENGL_ES #ifndef SFML_OPENGL_ES
// Check if the requested anti-aliasing level is supported // 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 #ifndef SFML_OPENGL_ES
// Create the multisample color buffer // Create the multisample color buffer
bool srgb = settings.sRgbCapable && GLEXT_texture_sRGB;
GLuint color = 0; GLuint color = 0;
glCheck(GLEXT_glGenRenderbuffers(1, &color)); glCheck(GLEXT_glGenRenderbuffers(1, &color));
m_colorBuffer = static_cast<unsigned int>(color); m_colorBuffer = static_cast<unsigned int>(color);
@ -306,7 +308,7 @@ bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsig
return false; return false;
} }
glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_colorBuffer)); 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 // Create the multisample depth/stencil buffer if requested
if (settings.stencilBits) if (settings.stencilBits)
@ -568,6 +570,13 @@ bool RenderTextureImplFBO::activate(bool active)
} }
////////////////////////////////////////////////////////////
bool RenderTextureImplFBO::isSrgb() const
{
return m_sRgb;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void RenderTextureImplFBO::updateTexture(unsigned int) void RenderTextureImplFBO::updateTexture(unsigned int)
{ {

View File

@ -114,6 +114,17 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual bool activate(bool active); 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 /// \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 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_multisample; //!< Whether we have to create a multisample frame buffer as well
bool m_stencil; //!< Whether we have stencil attachment bool m_stencil; //!< Whether we have stencil attachment
bool m_sRgb; //!< Whether we need to encode drawn pixels into sRGB color space
}; };
} // namespace priv } // namespace priv

View File

@ -73,6 +73,13 @@ Vector2u RenderWindow::getSize() const
} }
////////////////////////////////////////////////////////////
bool RenderWindow::isSrgb() const
{
return getSettings().sRgbCapable;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderWindow::setActive(bool active) bool RenderWindow::setActive(bool active)
{ {