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/1343138
Reviewed-by: Tobin Ehlis <tobine@google.com>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
This commit is contained in:
Geoff Lang 2018-11-22 14:36:06 -05:00 коммит произвёл Commit Bot
Родитель 617103ed0e
Коммит 7198ebc48c
6 изменённых файлов: 103 добавлений и 31 удалений

Просмотреть файл

@ -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
// 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,
// 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,
} }
} }
} }
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,
// 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
#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,6 +1331,8 @@ 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
if (extensionEnabled("GL_EXT_sRGB"))
{
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, false, false, GLColor(55, 13, 4, 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), GL_SRGB, testCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128), GL_SRGB,
@ -1339,14 +1341,17 @@ TEST_P(CopyTextureTestES3, ES3UnormFormats)
GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, false, false, false, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, false, false, false,
GLColor(55, 13, 4, 128)); GLColor(55, 13, 4, 128));
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, false, false, GLColor(55, 13, 4, 255)); GL_SRGB, GL_SRGB, 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, 255));
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, 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), 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, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, false, false,
false, GLColor(55, 13, 4, 128)); false, GLColor(55, 13, 4, 128));
} }
}
// Test the newly added ES3 float formats // Test the newly added ES3 float formats
TEST_P(CopyTextureTestES3, ES3FloatFormats) TEST_P(CopyTextureTestES3, ES3FloatFormats)

Просмотреть файл

@ -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,25 +100,21 @@ 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 else
{
EXPECT_GL_NO_ERROR();
}
}
else
{ {
EXPECT_GL_ERROR(GL_INVALID_ENUM); EXPECT_GL_ERROR(GL_INVALID_ENUM);
} }
@ -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)
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)
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)
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;