Commit 7198ebc4 by Geoff Lang Committed by Commit Bot

GL: Work around Qualcomm sRGB ReadPixels driver bug.

When calling glReadPixels on unsized sRGB textures, the data returned is not linearized. Using sized sRGB formats works around this problem. Fix SRGBTextureTest assuming that unsized SRGB formats work in ES3. BUG=angleproject:2977 Change-Id: I413c888ca0c3564ecdc364f3ea693e75ed4f8d6d Reviewed-on: https://chromium-review.googlesource.com/c/1343138Reviewed-by: 's avatarTobin Ehlis <tobine@google.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent 617103ed
...@@ -3231,6 +3231,12 @@ Extensions Context::generateSupportedExtensions() const ...@@ -3231,6 +3231,12 @@ Extensions Context::generateSupportedExtensions() const
supportedExtensions.maxViews = 1u; supportedExtensions.maxViews = 1u;
supportedExtensions.copyTexture3d = false; supportedExtensions.copyTexture3d = false;
supportedExtensions.textureMultisample = false; supportedExtensions.textureMultisample = false;
// Don't expose GL_EXT_texture_sRGB_decode without sRGB texture support
if (!supportedExtensions.sRGB)
{
supportedExtensions.textureSRGBDecode = false;
}
} }
if (getClientVersion() < ES_3_1) if (getClientVersion() < ES_3_1)
......
...@@ -158,6 +158,11 @@ struct WorkaroundsGL ...@@ -158,6 +158,11 @@ struct WorkaroundsGL
// instead of disabling the functionality entirely. The AMD bug looked like incorrect blending, // instead of disabling the functionality entirely. The AMD bug looked like incorrect blending,
// not sure if a workaround is feasible. http://anglebug.com/1085 // not sure if a workaround is feasible. http://anglebug.com/1085
bool disableBlendFuncExtended = false; bool disableBlendFuncExtended = false;
// Qualcomm drivers returns raw sRGB values instead of linearized values when calling
// glReadPixels on unsized sRGB texture formats. http://crbug.com/550292 and
// http://crbug.com/565179
bool unsizedsRGBReadPixelsDoesntTransform = false;
}; };
inline WorkaroundsGL::WorkaroundsGL() = default; inline WorkaroundsGL::WorkaroundsGL() = default;
......
...@@ -414,6 +414,13 @@ static GLenum GetNativeInternalFormat(const FunctionsGL *functions, ...@@ -414,6 +414,13 @@ static GLenum GetNativeInternalFormat(const FunctionsGL *functions,
// Workaround Adreno driver not supporting unsized EXT_texture_rg formats // Workaround Adreno driver not supporting unsized EXT_texture_rg formats
result = internalFormat.sizedInternalFormat; result = internalFormat.sizedInternalFormat;
} }
else if (workarounds.unsizedsRGBReadPixelsDoesntTransform &&
internalFormat.colorEncoding == GL_SRGB)
{
// Work around some Adreno driver bugs that don't read back SRGB data correctly when
// it's in unsized SRGB texture formats.
result = internalFormat.sizedInternalFormat;
}
} }
return result; return result;
...@@ -454,6 +461,21 @@ static GLenum GetNativeFormat(const FunctionsGL *functions, ...@@ -454,6 +461,21 @@ static GLenum GetNativeFormat(const FunctionsGL *functions,
} }
} }
} }
else if (functions->isAtLeastGLES(gl::Version(3, 0)))
{
if (workarounds.unsizedsRGBReadPixelsDoesntTransform)
{
if (format == GL_SRGB)
{
result = GL_RGB;
}
if (format == GL_SRGB_ALPHA)
{
result = GL_RGBA;
}
}
}
return result; return result;
} }
......
...@@ -1201,6 +1201,14 @@ void GenerateCaps(const FunctionsGL *functions, ...@@ -1201,6 +1201,14 @@ void GenerateCaps(const FunctionsGL *functions,
// ES driver. // ES driver.
extensions->compressedTextureETC = functions->standard == STANDARD_GL_ES && extensions->compressedTextureETC = functions->standard == STANDARD_GL_ES &&
gl::DetermineCompressedTextureETCSupport(*textureCapsMap); gl::DetermineCompressedTextureETCSupport(*textureCapsMap);
// To work around broken unsized sRGB textures, sized sRGB textures are used. Disable EXT_sRGB
// if those formats are not available.
if (workarounds.unsizedsRGBReadPixelsDoesntTransform &&
!functions->isAtLeastGLES(gl::Version(3, 0)))
{
extensions->sRGB = false;
}
} }
void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds) void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds)
...@@ -1295,6 +1303,13 @@ void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workaround ...@@ -1295,6 +1303,13 @@ void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workaround
#endif #endif
workarounds->disableBlendFuncExtended = IsAMD(vendor) || IsIntel(vendor); workarounds->disableBlendFuncExtended = IsAMD(vendor) || IsIntel(vendor);
#if defined(ANGLE_PLATFORM_ANDROID)
if (IsQualcomm(vendor))
{
workarounds->unsizedsRGBReadPixelsDoesntTransform = true;
}
#endif // defined(ANGLE_PLATFORM_ANDROID)
} }
void ApplyWorkarounds(const FunctionsGL *functions, gl::Workarounds *workarounds) void ApplyWorkarounds(const FunctionsGL *functions, gl::Workarounds *workarounds)
......
...@@ -1331,21 +1331,26 @@ TEST_P(CopyTextureTestES3, ES3UnormFormats) ...@@ -1331,21 +1331,26 @@ TEST_P(CopyTextureTestES3, ES3UnormFormats)
GL_UNSIGNED_BYTE, false, true, false, GLColor(0, 0, 0, 128)); GL_UNSIGNED_BYTE, false, true, false, GLColor(0, 0, 0, 128));
// New sRGB dest formats // New sRGB dest formats
testCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128), GL_SRGB, if (extensionEnabled("GL_EXT_sRGB"))
GL_UNSIGNED_BYTE, false, false, false, GLColor(55, 13, 4, 255)); {
testCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128), GL_SRGB, testCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128), GL_SRGB,
GL_UNSIGNED_BYTE, false, true, false, GLColor(13, 4, 1, 255)); GL_UNSIGNED_BYTE, false, false, false, GLColor(55, 13, 4, 255));
testCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128), testCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128), GL_SRGB,
GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, false, false, false, GL_UNSIGNED_BYTE, false, true, false, GLColor(13, 4, 1, 255));
GLColor(55, 13, 4, 128)); testCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128),
GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, false, false, false,
testSubCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128), GL_SRGB, GLColor(55, 13, 4, 128));
GL_SRGB, GL_UNSIGNED_BYTE, false, false, false, GLColor(55, 13, 4, 255));
testSubCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128), GL_SRGB, testSubCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128),
GL_SRGB, GL_UNSIGNED_BYTE, false, true, false, GLColor(13, 4, 1, 255)); GL_SRGB, GL_SRGB, GL_UNSIGNED_BYTE, false, false, false,
testSubCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128), GLColor(55, 13, 4, 255));
GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, false, false, testSubCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128),
false, GLColor(55, 13, 4, 128)); GL_SRGB, GL_SRGB, GL_UNSIGNED_BYTE, false, true, false,
GLColor(13, 4, 1, 255));
testSubCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128),
GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, false, false,
false, GLColor(55, 13, 4, 128));
}
} }
// Test the newly added ES3 float formats // Test the newly added ES3 float formats
......
...@@ -62,6 +62,26 @@ class SRGBTextureTest : public ANGLETest ...@@ -62,6 +62,26 @@ class SRGBTextureTest : public ANGLETest
ANGLETest::TearDown(); ANGLETest::TearDown();
} }
GLenum getSRGBA8TextureInternalFormat() const
{
return getClientMajorVersion() >= 3 ? GL_SRGB8_ALPHA8 : GL_SRGB_ALPHA_EXT;
}
GLenum getSRGBA8TextureFormat() const
{
return getClientMajorVersion() >= 3 ? GL_RGBA : GL_SRGB_ALPHA_EXT;
}
GLenum getSRGB8TextureInternalFormat() const
{
return getClientMajorVersion() >= 3 ? GL_SRGB8 : GL_SRGB_EXT;
}
GLenum getSRGB8TextureFormat() const
{
return getClientMajorVersion() >= 3 ? GL_RGB : GL_SRGB_EXT;
}
GLuint mProgram = 0; GLuint mProgram = 0;
GLint mTextureLocation = -1; GLint mTextureLocation = -1;
}; };
...@@ -80,23 +100,19 @@ TEST_P(SRGBTextureTest, SRGBValidation) ...@@ -80,23 +100,19 @@ TEST_P(SRGBTextureTest, SRGBValidation)
glBindTexture(GL_TEXTURE_2D, tex); glBindTexture(GL_TEXTURE_2D, tex);
GLubyte pixel[3] = { 0 }; GLubyte pixel[3] = { 0 };
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB, 1, 1, 0, GL_SRGB, GL_UNSIGNED_BYTE, pixel); glTexImage2D(GL_TEXTURE_2D, 0, getSRGB8TextureInternalFormat(), 1, 1, 0,
getSRGB8TextureFormat(), GL_UNSIGNED_BYTE, pixel);
if (supported) if (supported)
{ {
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_SRGB, GL_UNSIGNED_BYTE, pixel); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, getSRGB8TextureFormat(), GL_UNSIGNED_BYTE,
pixel);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
// Mipmap generation always generates errors for SRGB unsized in ES2 or SRGB8 sized in ES3.
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
if (getClientMajorVersion() < 3) EXPECT_GL_ERROR(GL_INVALID_OPERATION);
{
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
}
else
{
EXPECT_GL_NO_ERROR();
}
} }
else else
{ {
...@@ -118,12 +134,14 @@ TEST_P(SRGBTextureTest, SRGBAValidation) ...@@ -118,12 +134,14 @@ TEST_P(SRGBTextureTest, SRGBAValidation)
glBindTexture(GL_TEXTURE_2D, tex); glBindTexture(GL_TEXTURE_2D, tex);
GLubyte pixel[4] = { 0 }; GLubyte pixel[4] = { 0 };
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 1, 1, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, pixel); glTexImage2D(GL_TEXTURE_2D, 0, getSRGBA8TextureInternalFormat(), 1, 1, 0,
getSRGBA8TextureFormat(), GL_UNSIGNED_BYTE, pixel);
if (supported) if (supported)
{ {
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, pixel); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, getSRGBA8TextureFormat(), GL_UNSIGNED_BYTE,
pixel);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
...@@ -157,7 +175,8 @@ TEST_P(SRGBTextureTest, SRGBASizedValidation) ...@@ -157,7 +175,8 @@ TEST_P(SRGBTextureTest, SRGBASizedValidation)
glBindTexture(GL_TEXTURE_2D, tex); glBindTexture(GL_TEXTURE_2D, tex);
GLubyte pixel[4] = {0}; GLubyte pixel[4] = {0};
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel); glTexImage2D(GL_TEXTURE_2D, 0, getSRGBA8TextureInternalFormat(), 1, 1, 0,
getSRGBA8TextureFormat(), GL_UNSIGNED_BYTE, pixel);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
...@@ -237,8 +256,8 @@ TEST_P(SRGBTextureTest, SRGBDecodeTextureParameter) ...@@ -237,8 +256,8 @@ TEST_P(SRGBTextureTest, SRGBDecodeTextureParameter)
GLTexture tex; GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex.get()); 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, glTexImage2D(GL_TEXTURE_2D, 0, getSRGBA8TextureInternalFormat(), 1, 1, 0,
&linearColor); getSRGBA8TextureFormat(), GL_UNSIGNED_BYTE, &linearColor);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
...@@ -267,8 +286,8 @@ TEST_P(SRGBTextureTest, SRGBDecodeSamplerParameter) ...@@ -267,8 +286,8 @@ TEST_P(SRGBTextureTest, SRGBDecodeSamplerParameter)
GLTexture tex; GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex.get()); 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, glTexImage2D(GL_TEXTURE_2D, 0, getSRGBA8TextureInternalFormat(), 1, 1, 0,
&linearColor); getSRGBA8TextureFormat(), GL_UNSIGNED_BYTE, &linearColor);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
GLSampler sampler; GLSampler sampler;
......
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