Commit 1d2c41d6 by Geoff Lang Committed by Commit Bot

Implement GL_EXT_sRGB_write_control for GL.

BUG=angleproject:1547 BUG=655247 Change-Id: I3f04ddc7032e4a47eb21ff3b8586c5b47415bb64 Reviewed-on: https://chromium-review.googlesource.com/400958 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 0e3aee3f
...@@ -171,6 +171,7 @@ Extensions::Extensions() ...@@ -171,6 +171,7 @@ Extensions::Extensions()
bindGeneratesResource(false), bindGeneratesResource(false),
robustClientMemory(false), robustClientMemory(false),
textureSRGBDecode(false), textureSRGBDecode(false),
sRGBWriteControl(false),
colorBufferFloat(false), colorBufferFloat(false),
multisampleCompatibility(false), multisampleCompatibility(false),
framebufferMixedSamples(false), framebufferMixedSamples(false),
...@@ -587,6 +588,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() ...@@ -587,6 +588,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource); map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource);
map["GL_ANGLE_robust_client_memory"] = esOnlyExtension(&Extensions::robustClientMemory); map["GL_ANGLE_robust_client_memory"] = esOnlyExtension(&Extensions::robustClientMemory);
map["GL_EXT_texture_sRGB_decode"] = esOnlyExtension(&Extensions::textureSRGBDecode); map["GL_EXT_texture_sRGB_decode"] = esOnlyExtension(&Extensions::textureSRGBDecode);
map["GL_EXT_sRGB_write_control"] = esOnlyExtension(&Extensions::sRGBWriteControl);
map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility); map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility);
map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples); map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples);
map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16); map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16);
......
...@@ -308,6 +308,9 @@ struct Extensions ...@@ -308,6 +308,9 @@ struct Extensions
// GL_EXT_texture_sRGB_decode // GL_EXT_texture_sRGB_decode
bool textureSRGBDecode; bool textureSRGBDecode;
// GL_EXT_sRGB_write_control
bool sRGBWriteControl;
// ES3 Extension support // ES3 Extension support
// GL_EXT_color_buffer_float // GL_EXT_color_buffer_float
......
...@@ -370,6 +370,7 @@ Context::Context(rx::EGLImplFactory *implFactory, ...@@ -370,6 +370,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
mBlitDirtyBits.set(State::DIRTY_BIT_SCISSOR_TEST_ENABLED); mBlitDirtyBits.set(State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
mBlitDirtyBits.set(State::DIRTY_BIT_SCISSOR); mBlitDirtyBits.set(State::DIRTY_BIT_SCISSOR);
mBlitDirtyBits.set(State::DIRTY_BIT_FRAMEBUFFER_SRGB);
mBlitDirtyObjects.set(State::DIRTY_OBJECT_READ_FRAMEBUFFER); mBlitDirtyObjects.set(State::DIRTY_OBJECT_READ_FRAMEBUFFER);
mBlitDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER); mBlitDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
......
...@@ -346,6 +346,17 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign ...@@ -346,6 +346,17 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign
} }
} }
if (getExtensions().sRGBWriteControl)
{
switch (pname)
{
case GL_FRAMEBUFFER_SRGB_EXT:
*type = GL_BOOL;
*numParams = 1;
return true;
}
}
// Check for ES3.0+ parameter names which are also exposed as ES2 extensions // Check for ES3.0+ parameter names which are also exposed as ES2 extensions
switch (pname) switch (pname)
{ {
......
...@@ -60,7 +60,8 @@ State::State() ...@@ -60,7 +60,8 @@ State::State()
mActiveSampler(0), mActiveSampler(0),
mPrimitiveRestart(false), mPrimitiveRestart(false),
mMultiSampling(false), mMultiSampling(false),
mSampleAlphaToOne(false) mSampleAlphaToOne(false),
mFramebufferSRGB(true)
{ {
} }
...@@ -637,6 +638,9 @@ void State::setEnableFeature(GLenum feature, bool enabled) ...@@ -637,6 +638,9 @@ void State::setEnableFeature(GLenum feature, bool enabled)
case GL_DEBUG_OUTPUT: case GL_DEBUG_OUTPUT:
mDebug.setOutputEnabled(enabled); mDebug.setOutputEnabled(enabled);
break; break;
case GL_FRAMEBUFFER_SRGB_EXT:
setFramebufferSRGB(enabled);
break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
} }
...@@ -664,6 +668,8 @@ bool State::getEnableFeature(GLenum feature) const ...@@ -664,6 +668,8 @@ bool State::getEnableFeature(GLenum feature) const
return mDebug.isOutputEnabled(); return mDebug.isOutputEnabled();
case GL_BIND_GENERATES_RESOURCE_CHROMIUM: case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
return isBindGeneratesResourceEnabled(); return isBindGeneratesResourceEnabled();
case GL_FRAMEBUFFER_SRGB_EXT:
return getFramebufferSRGB();
default: UNREACHABLE(); return false; default: UNREACHABLE(); return false;
} }
} }
...@@ -1456,6 +1462,17 @@ GLuint State::getPathStencilMask() const ...@@ -1456,6 +1462,17 @@ GLuint State::getPathStencilMask() const
return mPathStencilMask; return mPathStencilMask;
} }
void State::setFramebufferSRGB(bool sRGB)
{
mFramebufferSRGB = sRGB;
mDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_SRGB);
}
bool State::getFramebufferSRGB() const
{
return mFramebufferSRGB;
}
void State::getBooleanv(GLenum pname, GLboolean *params) void State::getBooleanv(GLenum pname, GLboolean *params)
{ {
switch (pname) switch (pname)
...@@ -1500,6 +1517,9 @@ void State::getBooleanv(GLenum pname, GLboolean *params) ...@@ -1500,6 +1517,9 @@ void State::getBooleanv(GLenum pname, GLboolean *params)
case GL_BIND_GENERATES_RESOURCE_CHROMIUM: case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
*params = isBindGeneratesResourceEnabled() ? GL_TRUE : GL_FALSE; *params = isBindGeneratesResourceEnabled() ? GL_TRUE : GL_FALSE;
break; break;
case GL_FRAMEBUFFER_SRGB_EXT:
*params = getFramebufferSRGB() ? GL_TRUE : GL_FALSE;
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
......
...@@ -290,6 +290,10 @@ class State : angle::NonCopyable ...@@ -290,6 +290,10 @@ class State : angle::NonCopyable
GLint getPathStencilRef() const; GLint getPathStencilRef() const;
GLuint getPathStencilMask() const; GLuint getPathStencilMask() const;
// GL_EXT_sRGB_write_control
void setFramebufferSRGB(bool sRGB);
bool getFramebufferSRGB() const;
// State query functions // State query functions
void getBooleanv(GLenum pname, GLboolean *params); void getBooleanv(GLenum pname, GLboolean *params);
void getFloatv(GLenum pname, GLfloat *params); void getFloatv(GLenum pname, GLfloat *params);
...@@ -363,6 +367,7 @@ class State : angle::NonCopyable ...@@ -363,6 +367,7 @@ class State : angle::NonCopyable
DIRTY_BIT_PATH_RENDERING_MATRIX_MV, // CHROMIUM_path_rendering path model view matrix DIRTY_BIT_PATH_RENDERING_MATRIX_MV, // CHROMIUM_path_rendering path model view matrix
DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ, // CHROMIUM_path_rendering path projection matrix DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ, // CHROMIUM_path_rendering path projection matrix
DIRTY_BIT_PATH_RENDERING_STENCIL_STATE, DIRTY_BIT_PATH_RENDERING_STENCIL_STATE,
DIRTY_BIT_FRAMEBUFFER_SRGB, // GL_EXT_sRGB_write_control
DIRTY_BIT_CURRENT_VALUE_0, DIRTY_BIT_CURRENT_VALUE_0,
DIRTY_BIT_CURRENT_VALUE_MAX = DIRTY_BIT_CURRENT_VALUE_0 + MAX_VERTEX_ATTRIBS, DIRTY_BIT_CURRENT_VALUE_MAX = DIRTY_BIT_CURRENT_VALUE_0 + MAX_VERTEX_ATTRIBS,
DIRTY_BIT_INVALID = DIRTY_BIT_CURRENT_VALUE_MAX, DIRTY_BIT_INVALID = DIRTY_BIT_CURRENT_VALUE_MAX,
...@@ -479,6 +484,9 @@ class State : angle::NonCopyable ...@@ -479,6 +484,9 @@ class State : angle::NonCopyable
GLint mPathStencilRef; GLint mPathStencilRef;
GLuint mPathStencilMask; GLuint mPathStencilMask;
// GL_EXT_sRGB_write_control
bool mFramebufferSRGB;
DirtyBits mDirtyBits; DirtyBits mDirtyBits;
DirtyObjects mDirtyObjects; DirtyObjects mDirtyObjects;
}; };
......
...@@ -332,7 +332,7 @@ Error FramebufferGL::blit(ContextImpl *context, ...@@ -332,7 +332,7 @@ Error FramebufferGL::blit(ContextImpl *context,
} }
// Enable FRAMEBUFFER_SRGB if needed // Enable FRAMEBUFFER_SRGB if needed
syncDrawState(); mStateManager->setFramebufferSRGBEnabledForFramebuffer(true, this);
GLenum blitMask = mask; GLenum blitMask = mask;
if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT)) if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT))
...@@ -421,17 +421,9 @@ GLuint FramebufferGL::getFramebufferID() const ...@@ -421,17 +421,9 @@ GLuint FramebufferGL::getFramebufferID() const
return mFramebufferID; return mFramebufferID;
} }
void FramebufferGL::syncDrawState() const bool FramebufferGL::isDefault() const
{ {
if (mFunctions->standard == STANDARD_GL_DESKTOP) return mIsDefault;
{
// 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) void FramebufferGL::syncClearState(GLbitfield mask)
......
...@@ -80,9 +80,8 @@ class FramebufferGL : public FramebufferImpl ...@@ -80,9 +80,8 @@ class FramebufferGL : public FramebufferImpl
void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override; void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override;
void syncDrawState() const;
GLuint getFramebufferID() const; GLuint getFramebufferID() const;
bool isDefault() const;
private: private:
void syncClearState(GLbitfield mask); void syncClearState(GLbitfield mask);
......
...@@ -785,7 +785,6 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::ContextState &data) ...@@ -785,7 +785,6 @@ gl::Error StateManagerGL::setGenericDrawState(const gl::ContextState &data)
const gl::Framebuffer *framebuffer = state.getDrawFramebuffer(); const gl::Framebuffer *framebuffer = state.getDrawFramebuffer();
const FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer); const FramebufferGL *framebufferGL = GetImplAs<FramebufferGL>(framebuffer);
bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferGL->getFramebufferID()); bindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferGL->getFramebufferID());
framebufferGL->syncDrawState();
// Seamless cubemaps are required for ES3 and higher contexts. // Seamless cubemaps are required for ES3 and higher contexts.
setTextureCubemapSeamlessEnabled(data.getClientMajorVersion() >= 3); setTextureCubemapSeamlessEnabled(data.getClientMajorVersion() >= 3);
...@@ -1320,6 +1319,13 @@ void StateManagerGL::setClearStencil(GLint clearStencil) ...@@ -1320,6 +1319,13 @@ void StateManagerGL::setClearStencil(GLint clearStencil)
void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBits &glDirtyBits) void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBits &glDirtyBits)
{ {
// The the current framebuffer binding sometimes requires resetting the srgb blending
if (glDirtyBits[gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING] &&
mFunctions->standard == STANDARD_GL_DESKTOP)
{
mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
}
const auto &glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits); const auto &glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits);
if (!glAndLocalDirtyBits.any()) if (!glAndLocalDirtyBits.any())
...@@ -1560,6 +1566,11 @@ void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBit ...@@ -1560,6 +1566,11 @@ void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBit
setPathRenderingStencilState(state.getPathStencilFunc(), state.getPathStencilRef(), setPathRenderingStencilState(state.getPathStencilFunc(), state.getPathStencilRef(),
state.getPathStencilMask()); state.getPathStencilMask());
break; break;
case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB:
setFramebufferSRGBEnabledForFramebuffer(
state.getFramebufferSRGB(),
GetImplAs<FramebufferGL>(state.getDrawFramebuffer()));
break;
default: default:
{ {
ASSERT(dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 && ASSERT(dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 &&
...@@ -1589,6 +1600,25 @@ void StateManagerGL::setFramebufferSRGBEnabled(bool enabled) ...@@ -1589,6 +1600,25 @@ void StateManagerGL::setFramebufferSRGBEnabled(bool enabled)
{ {
mFunctions->disable(GL_FRAMEBUFFER_SRGB); mFunctions->disable(GL_FRAMEBUFFER_SRGB);
} }
mLocalDirtyBits.set(gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB);
}
}
void StateManagerGL::setFramebufferSRGBEnabledForFramebuffer(bool enabled,
const FramebufferGL *framebuffer)
{
if (mFunctions->standard == STANDARD_GL_DESKTOP && framebuffer->isDefault())
{
// Obey the framebuffer sRGB state for blending on 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.
setFramebufferSRGBEnabled(false);
}
else
{
setFramebufferSRGBEnabled(enabled);
} }
} }
......
...@@ -27,6 +27,7 @@ class State; ...@@ -27,6 +27,7 @@ class State;
namespace rx namespace rx
{ {
class FramebufferGL;
class FunctionsGL; class FunctionsGL;
class TransformFeedbackGL; class TransformFeedbackGL;
class QueryGL; class QueryGL;
...@@ -123,6 +124,7 @@ class StateManagerGL final : angle::NonCopyable ...@@ -123,6 +124,7 @@ class StateManagerGL final : angle::NonCopyable
GLuint packBuffer); GLuint packBuffer);
void setFramebufferSRGBEnabled(bool enabled); void setFramebufferSRGBEnabled(bool enabled);
void setFramebufferSRGBEnabledForFramebuffer(bool enabled, const FramebufferGL *framebuffer);
void setDitherEnabled(bool enabled); void setDitherEnabled(bool enabled);
......
...@@ -884,6 +884,18 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM ...@@ -884,6 +884,18 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
extensions->textureSRGBDecode = false; extensions->textureSRGBDecode = false;
} }
#endif #endif
extensions->sRGBWriteControl = functions->isAtLeastGL(gl::Version(3, 0)) ||
functions->hasGLExtension("GL_EXT_framebuffer_sRGB") ||
functions->hasGLExtension("GL_ARB_framebuffer_sRGB") ||
functions->hasGLESExtension("GL_EXT_sRGB_write_control");
#if defined(ANGLE_PLATFORM_ANDROID)
// SRGB blending does not appear to work correctly on the Nexus 5. Writing to an SRGB
// framebuffer with GL_FRAMEBUFFER_SRGB enabled and then reading back returns the same value.
// Disabling GL_FRAMEBUFFER_SRGB will then convert in the wrong direction.
extensions->sRGBWriteControl = false;
#endif
} }
void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds) void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds)
......
...@@ -162,6 +162,9 @@ bool ValidCap(const Context *context, GLenum cap, bool queryOnly) ...@@ -162,6 +162,9 @@ bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
case GL_BIND_GENERATES_RESOURCE_CHROMIUM: case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
return queryOnly && context->getExtensions().bindGeneratesResource; return queryOnly && context->getExtensions().bindGeneratesResource;
case GL_FRAMEBUFFER_SRGB_EXT:
return context->getExtensions().sRGBWriteControl;
default: default:
return false; return false;
} }
......
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
'<(angle_path)/src/tests/gl_tests/RobustClientMemoryTest.cpp', '<(angle_path)/src/tests/gl_tests/RobustClientMemoryTest.cpp',
'<(angle_path)/src/tests/gl_tests/SimpleOperationTest.cpp', '<(angle_path)/src/tests/gl_tests/SimpleOperationTest.cpp',
'<(angle_path)/src/tests/gl_tests/SixteenBppTextureTest.cpp', '<(angle_path)/src/tests/gl_tests/SixteenBppTextureTest.cpp',
'<(angle_path)/src/tests/gl_tests/SRGBFramebufferTest.cpp',
'<(angle_path)/src/tests/gl_tests/SRGBTextureTest.cpp', '<(angle_path)/src/tests/gl_tests/SRGBTextureTest.cpp',
'<(angle_path)/src/tests/gl_tests/StateChangeTest.cpp', '<(angle_path)/src/tests/gl_tests/StateChangeTest.cpp',
'<(angle_path)/src/tests/gl_tests/SwizzleTest.cpp', '<(angle_path)/src/tests/gl_tests/SwizzleTest.cpp',
......
...@@ -217,9 +217,11 @@ ...@@ -217,9 +217,11 @@
1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.color0.rgba_half_float_oes = FAIL 1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.color0.rgba_half_float_oes = FAIL
1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.color0.srgb8 = FAIL 1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.color0.srgb8 = FAIL
1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.stencil.srgb8 = FAIL 1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.stencil.srgb8 = FAIL
1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.stencil.srgb8_alpha8 = FAIL
1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.depth_component_unsigned_short = FAIL 1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.depth_component_unsigned_short = FAIL
1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.depth_component_unsigned_int = FAIL 1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.depth_component_unsigned_int = FAIL
1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.srgb8 = FAIL 1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.srgb8 = FAIL
1028 WIN LINUX MAC : dEQP-GLES2.functional.fbo.completeness.renderable.texture.depth.srgb8_alpha8 = FAIL
1128 WIN LINUX MAC : dEQP-GLES2.functional.negative_api.texture.compressedtexsubimage2d_invalid_size = FAIL 1128 WIN LINUX MAC : dEQP-GLES2.functional.negative_api.texture.compressedtexsubimage2d_invalid_size = FAIL
1029 WIN LINUX MAC : dEQP-GLES2.functional.negative_api.texture.teximage2d_invalid_format = FAIL 1029 WIN LINUX MAC : dEQP-GLES2.functional.negative_api.texture.teximage2d_invalid_format = FAIL
1029 WIN LINUX MAC : dEQP-GLES2.functional.negative_api.texture.teximage2d_invalid_internalformat = FAIL 1029 WIN LINUX MAC : dEQP-GLES2.functional.negative_api.texture.teximage2d_invalid_internalformat = FAIL
......
//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SRGBFramebufferTest.cpp: Tests of sRGB framebuffer functionality.
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
namespace angle
{
class SRGBFramebufferTest : public ANGLETest
{
protected:
SRGBFramebufferTest()
{
setWindowWidth(128);
setWindowHeight(128);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
}
void SetUp() override
{
ANGLETest::SetUp();
const std::string vs =
"precision highp float;\n"
"attribute vec4 position;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position.xy, 0.0, 1.0);\n"
"}\n";
const std::string fs =
"precision highp float;\n"
"uniform vec4 color;\n"
"void main()\n"
"{\n"
" gl_FragColor = color;\n"
"}\n";
mProgram = CompileProgram(vs, fs);
ASSERT_NE(0u, mProgram);
mColorLocation = glGetUniformLocation(mProgram, "color");
ASSERT_NE(-1, mColorLocation);
}
void TearDown() override
{
glDeleteProgram(mProgram);
ANGLETest::TearDown();
}
GLuint mProgram = 0;
GLint mColorLocation = -1;
};
// Test basic validation of GL_EXT_sRGB_write_control
TEST_P(SRGBFramebufferTest, Validation)
{
GLenum expectedError =
extensionEnabled("GL_EXT_sRGB_write_control") ? GL_NO_ERROR : GL_INVALID_ENUM;
GLboolean value = GL_FALSE;
glEnable(GL_FRAMEBUFFER_SRGB_EXT);
EXPECT_GL_ERROR(expectedError);
glGetBooleanv(GL_FRAMEBUFFER_SRGB_EXT, &value);
EXPECT_GL_ERROR(expectedError);
if (expectedError == GL_NO_ERROR)
{
EXPECT_EQ(GL_TRUE, value);
}
glDisable(GL_FRAMEBUFFER_SRGB_EXT);
EXPECT_GL_ERROR(expectedError);
glGetBooleanv(GL_FRAMEBUFFER_SRGB_EXT, &value);
EXPECT_GL_ERROR(expectedError);
if (expectedError == GL_NO_ERROR)
{
EXPECT_EQ(GL_FALSE, value);
}
}
// Test basic functionality of GL_EXT_sRGB_write_control
TEST_P(SRGBFramebufferTest, BasicUsage)
{
if (!extensionEnabled("GL_EXT_sRGB_write_control") ||
(!extensionEnabled("GL_EXT_sRGB") && getClientMajorVersion() < 3))
{
std::cout
<< "Test skipped because GL_EXT_sRGB_write_control and GL_EXT_sRGB are not available."
<< std::endl;
return;
}
GLColor linearColor(64, 127, 191, 255);
GLColor srgbColor(13, 54, 133, 255);
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture.get());
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
nullptr);
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
glUseProgram(mProgram);
glUniform4fv(mColorLocation, 1, srgbColor.toNormalizedVector().data());
glEnable(GL_FRAMEBUFFER_SRGB_EXT);
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
glDisable(GL_FRAMEBUFFER_SRGB_EXT);
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST(SRGBFramebufferTest,
ES2_D3D9(),
ES2_D3D11(),
ES3_D3D11(),
ES2_OPENGL(),
ES3_OPENGL(),
ES2_OPENGLES(),
ES3_OPENGLES());
} // namespace angle
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment