Commit 81c6b577 by Geoff Lang Committed by Commit Bot

Implement GL_EXT_texture_sRGB_decode for GL.

BUG=angleproject:1383 BUG=655247 Change-Id: I409b12e1ae418530576de5ec9ce26b7be5d91650 Reviewed-on: https://chromium-review.googlesource.com/400807Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent de318b26
......@@ -170,6 +170,7 @@ Extensions::Extensions()
webglCompatibility(false),
bindGeneratesResource(false),
robustClientMemory(false),
textureSRGBDecode(false),
colorBufferFloat(false),
multisampleCompatibility(false),
framebufferMixedSamples(false),
......@@ -585,6 +586,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility);
map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource);
map["GL_ANGLE_robust_client_memory"] = esOnlyExtension(&Extensions::robustClientMemory);
map["GL_EXT_texture_sRGB_decode"] = esOnlyExtension(&Extensions::textureSRGBDecode);
map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility);
map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples);
map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16);
......
......@@ -305,6 +305,9 @@ struct Extensions
// GL_ANGLE_robust_client_memory
bool robustClientMemory;
// GL_EXT_texture_sRGB_decode
bool textureSRGBDecode;
// ES3 Extension support
// GL_EXT_color_buffer_float
......
......@@ -135,6 +135,16 @@ GLenum Sampler::getCompareFunc() const
return mSamplerState.compareFunc;
}
void Sampler::setSRGBDecode(GLenum sRGBDecode)
{
mSamplerState.sRGBDecode = sRGBDecode;
}
GLenum Sampler::getSRGBDecode() const
{
return mSamplerState.sRGBDecode;
}
const SamplerState &Sampler::getSamplerState() const
{
return mSamplerState;
......
......@@ -62,6 +62,9 @@ class Sampler final : public RefCountObject, public LabeledObject
void setCompareFunc(GLenum compareFunc);
GLenum getCompareFunc() const;
void setSRGBDecode(GLenum sRGBDecode);
GLenum getSRGBDecode() const;
const SamplerState &getSamplerState() const;
rx::SamplerImpl *getImplementation() const;
......
......@@ -683,6 +683,17 @@ GLenum Texture::getCompareFunc() const
return mState.mSamplerState.compareFunc;
}
void Texture::setSRGBDecode(GLenum sRGBDecode)
{
mState.mSamplerState.sRGBDecode = sRGBDecode;
mDirtyBits.set(DIRTY_BIT_SRGB_DECODE);
}
GLenum Texture::getSRGBDecode() const
{
return mState.mSamplerState.sRGBDecode;
}
const SamplerState &Texture::getSamplerState() const
{
return mState.mSamplerState;
......
......@@ -217,6 +217,9 @@ class Texture final : public egl::ImageSibling,
void setCompareFunc(GLenum compareFunc);
GLenum getCompareFunc() const;
void setSRGBDecode(GLenum sRGBDecode);
GLenum getSRGBDecode() const;
const SamplerState &getSamplerState() const;
void setBaseLevel(GLuint baseLevel);
......@@ -330,6 +333,7 @@ class Texture final : public egl::ImageSibling,
DIRTY_BIT_MAX_LOD,
DIRTY_BIT_COMPARE_MODE,
DIRTY_BIT_COMPARE_FUNC,
DIRTY_BIT_SRGB_DECODE,
// Texture state
DIRTY_BIT_SWIZZLE_RED,
......
......@@ -49,7 +49,8 @@ SamplerState::SamplerState()
minLod(-1000.0f),
maxLod(1000.0f),
compareMode(GL_NONE),
compareFunc(GL_LEQUAL)
compareFunc(GL_LEQUAL),
sRGBDecode(GL_DECODE_EXT)
{
}
......
......@@ -192,6 +192,8 @@ struct SamplerState
GLenum compareMode;
GLenum compareFunc;
GLenum sRGBDecode;
};
bool operator==(const SamplerState &a, const SamplerState &b);
......
......@@ -89,6 +89,9 @@ void QueryTexParameterBase(const Texture *texture, GLenum pname, ParamType *para
case GL_TEXTURE_COMPARE_FUNC:
*params = ConvertFromGLenum<ParamType>(texture->getCompareFunc());
break;
case GL_TEXTURE_SRGB_DECODE_EXT:
*params = ConvertFromGLenum<ParamType>(texture->getSRGBDecode());
break;
default:
UNREACHABLE();
break;
......@@ -153,6 +156,9 @@ void SetTexParameterBase(Texture *texture, GLenum pname, const ParamType *params
case GL_TEXTURE_MAX_LOD:
texture->setMaxLod(ConvertToGLfloat(params[0]));
break;
case GL_TEXTURE_SRGB_DECODE_EXT:
texture->setSRGBDecode(ConvertToGLenum(params[0]));
break;
default:
UNREACHABLE();
break;
......@@ -194,6 +200,9 @@ void QuerySamplerParameterBase(const Sampler *sampler, GLenum pname, ParamType *
case GL_TEXTURE_COMPARE_FUNC:
*params = ConvertFromGLenum<ParamType>(sampler->getCompareFunc());
break;
case GL_TEXTURE_SRGB_DECODE_EXT:
*params = ConvertFromGLenum<ParamType>(sampler->getSRGBDecode());
break;
default:
UNREACHABLE();
break;
......@@ -235,6 +244,9 @@ void SetSamplerParameterBase(Sampler *sampler, GLenum pname, const ParamType *pa
case GL_TEXTURE_MAX_LOD:
sampler->setMaxLod(ConvertToGLfloat(params[0]));
break;
case GL_TEXTURE_SRGB_DECODE_EXT:
sampler->setSRGBDecode(ConvertToGLenum(params[0]));
break;
default:
UNREACHABLE();
break;
......
......@@ -62,6 +62,7 @@ void SamplerGL::syncState(const gl::SamplerState &samplerState) const
SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_MAX_LOD, &gl::SamplerState::maxLod);
SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode);
SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc);
SyncSamplerStateMember(mFunctions, mSamplerID, samplerState, mAppliedSamplerState, GL_TEXTURE_SRGB_DECODE_EXT, &gl::SamplerState::sRGBDecode);
// clang-format on
}
......
......@@ -858,6 +858,10 @@ void TextureGL::syncState(const gl::Texture::DirtyBits &dirtyBits)
mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_COMPARE_FUNC,
mState.getSamplerState().compareFunc);
break;
case gl::Texture::DIRTY_BIT_SRGB_DECODE:
mFunctions->texParameteri(mState.mTarget, GL_TEXTURE_SRGB_DECODE_EXT,
mState.getSamplerState().sRGBDecode);
break;
// Texture state
case gl::Texture::DIRTY_BIT_SWIZZLE_RED:
......
......@@ -871,6 +871,20 @@ void GenerateCaps(const FunctionsGL *functions, gl::Caps *caps, gl::TextureCapsM
functions->isAtLeastGLES(gl::Version(3, 1));
extensions->pathRendering = canEnableGLPathRendering || canEnableESPathRendering;
extensions->textureSRGBDecode = functions->hasGLExtension("GL_EXT_texture_sRGB_decode") ||
functions->hasGLESExtension("GL_EXT_texture_sRGB_decode");
#if defined(ANGLE_PLATFORM_APPLE)
VendorID vendor = GetVendorID(functions);
if ((vendor == VENDOR_ID_AMD || vendor == VENDOR_ID_INTEL) &&
*maxSupportedESVersion >= gl::Version(3, 0))
{
// Apple Intel/AMD drivers do not correctly use the TEXTURE_SRGB_DECODE property of sampler
// states. Disable this extension when we would advertise any ES version that has samplers.
extensions->textureSRGBDecode = false;
}
#endif
}
void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds)
......
......@@ -471,6 +471,15 @@ bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname,
}
break;
case GL_TEXTURE_SRGB_DECODE_EXT:
if (!context->getExtensions().textureSRGBDecode)
{
context->handleError(
Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
return false;
}
break;
default:
context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
return false;
......@@ -603,6 +612,29 @@ bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
}
template <typename ParamType>
bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
{
if (!context->getExtensions().textureSRGBDecode)
{
context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
return false;
}
switch (ConvertToGLenum(params[0]))
{
case GL_DECODE_EXT:
case GL_SKIP_DECODE_EXT:
break;
default:
context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
return false;
}
return true;
}
template <typename ParamType>
bool ValidateTexParameterBase(Context *context,
GLenum target,
GLenum pname,
......@@ -777,6 +809,13 @@ bool ValidateTexParameterBase(Context *context,
}
break;
case GL_TEXTURE_SRGB_DECODE_EXT:
if (!ValidateTextureSRGBDecodeValue(context, params))
{
return false;
}
break;
default:
context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
return false;
......@@ -857,6 +896,13 @@ bool ValidateSamplerParameterBase(Context *context,
}
break;
case GL_TEXTURE_SRGB_DECODE_EXT:
if (!ValidateTextureSRGBDecodeValue(context, params))
{
return false;
}
break;
default:
context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
return false;
......@@ -901,6 +947,15 @@ bool ValidateGetSamplerParameterBase(Context *context,
case GL_TEXTURE_COMPARE_FUNC:
break;
case GL_TEXTURE_SRGB_DECODE_EXT:
if (!context->getExtensions().textureSRGBDecode)
{
context->handleError(
Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
return false;
}
break;
default:
context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
return false;
......
......@@ -5,10 +5,9 @@
//
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
using namespace angle;
namespace
namespace angle
{
class SRGBTextureTest : public ANGLETest
......@@ -27,12 +26,44 @@ class SRGBTextureTest : public ANGLETest
void SetUp() override
{
ANGLETest::SetUp();
const std::string vs =
"precision highp float;\n"
"attribute vec4 position;\n"
"varying vec2 texcoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position.xy, 0.0, 1.0);\n"
" texcoord = (position.xy * 0.5) + 0.5;\n"
"}\n";
const std::string fs =
"precision highp float;\n"
"uniform sampler2D tex;\n"
"varying vec2 texcoord;\n"
"\n"
"void main()\n"
"{\n"
" gl_FragColor = texture2D(tex, texcoord);\n"
"}\n";
mProgram = CompileProgram(vs, fs);
ASSERT_NE(0u, mProgram);
mTextureLocation = glGetUniformLocation(mProgram, "tex");
ASSERT_NE(-1, mTextureLocation);
}
void TearDown() override
{
glDeleteProgram(mProgram);
ANGLETest::TearDown();
}
GLuint mProgram = 0;
GLint mTextureLocation = -1;
};
TEST_P(SRGBTextureTest, SRGBValidation)
......@@ -143,12 +174,95 @@ TEST_P(SRGBTextureTest, SRGBARenderbuffer)
glDeleteRenderbuffers(1, &rbo);
}
// Verify that if the srgb decode extension is available, srgb textures are too
TEST_P(SRGBTextureTest, SRGBDecodeExtensionAvailability)
{
bool hasSRGBDecode = extensionEnabled("GL_EXT_texture_sRGB_decode");
if (hasSRGBDecode)
{
bool hasSRGBTextures = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() >= 3;
EXPECT_TRUE(hasSRGBTextures);
}
}
// Test basic functionality of SRGB decode using the texture parameter
TEST_P(SRGBTextureTest, SRGBDecodeTextureParameter)
{
if (!extensionEnabled("GL_EXT_texture_sRGB_decode"))
{
std::cout << "Test skipped because GL_EXT_texture_sRGB_decode is not available."
<< std::endl;
return;
}
GLColor linearColor(64, 127, 191, 255);
GLColor srgbColor(13, 54, 133, 255);
GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex.get());
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
&linearColor);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
ASSERT_GL_NO_ERROR();
glUseProgram(mProgram);
glUniform1i(mTextureLocation, 0);
glDisable(GL_DEPTH_TEST);
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 1.0);
}
// Test basic functionality of SRGB decode using the sampler parameter
TEST_P(SRGBTextureTest, SRGBDecodeSamplerParameter)
{
if (!extensionEnabled("GL_EXT_texture_sRGB_decode") || getClientMajorVersion() < 3)
{
std::cout << "Test skipped because GL_EXT_texture_sRGB_decode or ES3 is not available."
<< std::endl;
return;
}
GLColor linearColor(64, 127, 191, 255);
GLColor srgbColor(13, 54, 133, 255);
GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex.get());
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE,
&linearColor);
ASSERT_GL_NO_ERROR();
GLSampler sampler;
glBindSampler(0, sampler.get());
glSamplerParameteri(sampler.get(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
glUseProgram(mProgram);
glUniform1i(mTextureLocation, 0);
glDisable(GL_DEPTH_TEST);
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, srgbColor, 1.0);
glSamplerParameteri(sampler.get(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_NEAR(0, 0, linearColor, 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(SRGBTextureTest,
ES2_D3D9(),
ES2_D3D11(),
ES3_D3D11(),
ES2_OPENGL(),
ES2_OPENGLES());
ES3_OPENGL(),
ES2_OPENGLES(),
ES3_OPENGLES());
} // namespace
......@@ -46,6 +46,7 @@ using GLBuffer = GLWrapper<glGenBuffers, glDeleteBuffers>;
using GLTexture = GLWrapper<glGenTextures, glDeleteTextures>;
using GLFramebuffer = GLWrapper<glGenFramebuffers, glDeleteFramebuffers>;
using GLRenderbuffer = GLWrapper<glGenRenderbuffers, glDeleteRenderbuffers>;
using GLSampler = GLWrapper<glGenSamplers, glDeleteSamplers>;
class GLProgram
{
......
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