Explicitly enable framebuffer SRGB blending in StateManagerGL.
In DesktopGL, SRGB blending must be enabled or linear blending will be
used.
reland: Work around issues on AMD drivers where SRGB blending would be
used on clears of linear attachments.
Passes all dEQP-GLES3.functional.fragment_ops.blend.fbo_srgb.* tests (1106
new passing tests).
BUG=angleproject:883
BUG=angleproject:885
Change-Id: I974a55fe3acc77ac77e93f19c83ee3b76f784df2
Reviewed-on: https://chromium-review.googlesource.com/302336
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/libANGLE/renderer/gl/FramebufferGL.cpp
index 35712dc..92e08cc 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -18,14 +18,20 @@
#include "libANGLE/renderer/gl/RenderbufferGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
namespace rx
{
-FramebufferGL::FramebufferGL(const gl::Framebuffer::Data &data, const FunctionsGL *functions, StateManagerGL *stateManager, bool isDefault)
+FramebufferGL::FramebufferGL(const gl::Framebuffer::Data &data,
+ const FunctionsGL *functions,
+ StateManagerGL *stateManager,
+ const WorkaroundsGL &workarounds,
+ bool isDefault)
: FramebufferImpl(data),
mFunctions(functions),
mStateManager(stateManager),
+ mWorkarounds(workarounds),
mFramebufferID(0),
mIsDefault(isDefault)
{
@@ -38,10 +44,12 @@
FramebufferGL::FramebufferGL(GLuint id,
const gl::Framebuffer::Data &data,
const FunctionsGL *functions,
+ const WorkaroundsGL &workarounds,
StateManagerGL *stateManager)
: FramebufferImpl(data),
mFunctions(functions),
mStateManager(stateManager),
+ mWorkarounds(workarounds),
mFramebufferID(id),
mIsDefault(true)
{
@@ -197,6 +205,7 @@
gl::Error FramebufferGL::clear(const gl::Data &data, GLbitfield mask)
{
+ syncClearState(mask);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
mFunctions->clear(mask);
@@ -205,6 +214,7 @@
gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
{
+ syncClearBufferState(buffer, drawbuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
mFunctions->clearBufferfv(buffer, drawbuffer, values);
@@ -213,6 +223,7 @@
gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
{
+ syncClearBufferState(buffer, drawbuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
mFunctions->clearBufferuiv(buffer, drawbuffer, values);
@@ -221,6 +232,7 @@
gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
{
+ syncClearBufferState(buffer, drawbuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
mFunctions->clearBufferiv(buffer, drawbuffer, values);
@@ -229,6 +241,7 @@
gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
{
+ syncClearBufferState(buffer, drawbuffer);
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
@@ -290,4 +303,72 @@
return mFramebufferID;
}
+void FramebufferGL::syncDrawState() const
+{
+ if (mFunctions->standard == STANDARD_GL_DESKTOP)
+ {
+ // Enable SRGB blending for all framebuffers except the default framebuffer on Desktop
+ // OpenGL.
+ // When SRGB blending is enabled, only SRGB capable formats will use it but the default
+ // framebuffer will always use it if it is enabled.
+ // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
+ mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
+ }
+}
+
+void FramebufferGL::syncClearState(GLbitfield mask)
+{
+ if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
+ (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
+ {
+ bool hasSRBAttachment = false;
+ for (const auto &attachment : mData.getColorAttachments())
+ {
+ if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
+ {
+ hasSRBAttachment = true;
+ break;
+ }
+ }
+
+ mStateManager->setFramebufferSRGBEnabled(hasSRBAttachment);
+ }
+ else
+ {
+ mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
+ }
+}
+
+void FramebufferGL::syncClearBufferState(GLenum buffer, GLint drawBuffer)
+{
+ if (mFunctions->standard == STANDARD_GL_DESKTOP)
+ {
+ if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
+ !mIsDefault)
+ {
+ // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
+ // is an SRGB format.
+ const auto &drawbufferState = mData.getDrawBufferStates();
+ const auto &colorAttachments = mData.getColorAttachments();
+
+ const gl::FramebufferAttachment *attachment = nullptr;
+ if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
+ drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
+ {
+ size_t attachmentIdx =
+ static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
+ attachment = &colorAttachments[attachmentIdx];
+ }
+
+ if (attachment != nullptr)
+ {
+ mStateManager->setFramebufferSRGBEnabled(attachment->getColorEncoding() == GL_SRGB);
+ }
+ }
+ else
+ {
+ mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
+ }
+ }
+}
}