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.copyTexture3d = 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)

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

@ -158,6 +158,11 @@ struct WorkaroundsGL
// instead of disabling the functionality entirely. The AMD bug looked like incorrect blending,
// not sure if a workaround is feasible. http://anglebug.com/1085
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;

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

@ -414,6 +414,13 @@ static GLenum GetNativeInternalFormat(const FunctionsGL *functions,
// Workaround Adreno driver not supporting unsized EXT_texture_rg formats
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;
@ -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;
}

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

@ -1201,6 +1201,14 @@ void GenerateCaps(const FunctionsGL *functions,
// ES driver.
extensions->compressedTextureETC = functions->standard == STANDARD_GL_ES &&
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)
@ -1295,6 +1303,13 @@ void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workaround
#endif
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)

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

@ -1331,21 +1331,26 @@ TEST_P(CopyTextureTestES3, ES3UnormFormats)
GL_UNSIGNED_BYTE, false, true, false, GLColor(0, 0, 0, 128));
// New sRGB dest formats
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));
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));
testCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128),
GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, false, false, false,
GLColor(55, 13, 4, 128));
if (extensionEnabled("GL_EXT_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));
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));
testCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128),
GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, false, false, false,
GLColor(55, 13, 4, 128));
testSubCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128), GL_SRGB,
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,
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));
testSubCopyCombination(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, GLColor(128, 64, 32, 128),
GL_SRGB, 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, 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

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

@ -62,6 +62,26 @@ class SRGBTextureTest : public ANGLETest
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;
GLint mTextureLocation = -1;
};
@ -80,23 +100,19 @@ TEST_P(SRGBTextureTest, SRGBValidation)
glBindTexture(GL_TEXTURE_2D, tex);
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)
{
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();
// Mipmap generation always generates errors for SRGB unsized in ES2 or SRGB8 sized in ES3.
glGenerateMipmap(GL_TEXTURE_2D);
if (getClientMajorVersion() < 3)
{
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
}
else
{
EXPECT_GL_NO_ERROR();
}
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
}
else
{
@ -118,12 +134,14 @@ TEST_P(SRGBTextureTest, SRGBAValidation)
glBindTexture(GL_TEXTURE_2D, tex);
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)
{
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();
glGenerateMipmap(GL_TEXTURE_2D);
@ -157,7 +175,8 @@ TEST_P(SRGBTextureTest, SRGBASizedValidation)
glBindTexture(GL_TEXTURE_2D, tex);
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();
@ -237,8 +256,8 @@ TEST_P(SRGBTextureTest, SRGBDecodeTextureParameter)
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);
glTexImage2D(GL_TEXTURE_2D, 0, getSRGBA8TextureInternalFormat(), 1, 1, 0,
getSRGBA8TextureFormat(), GL_UNSIGNED_BYTE, &linearColor);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
ASSERT_GL_NO_ERROR();
@ -267,8 +286,8 @@ TEST_P(SRGBTextureTest, SRGBDecodeSamplerParameter)
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);
glTexImage2D(GL_TEXTURE_2D, 0, getSRGBA8TextureInternalFormat(), 1, 1, 0,
getSRGBA8TextureFormat(), GL_UNSIGNED_BYTE, &linearColor);
ASSERT_GL_NO_ERROR();
GLSampler sampler;