Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: cherry-pick 1234829 from angle
- Loading branch information
Showing
4 changed files
with
394 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
cherry-pick-d8cb996.patch | ||
cherry-pick-1fb846c.patch |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: Alexey Knyazev <lexa.knyazev@gmail.com> | ||
Date: Tue Aug 3 01:57:49 2021 +0400 | ||
Subject: Validate texStorage dimensions with compressed formats | ||
|
||
Bug: angleproject:6230 | ||
Change-Id: I501ec1e6974bdc7e6731dcb88045edb0aa22b888 | ||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3067329 | ||
Commit-Queue: Alexey Knyazev <lexa.knyazev@gmail.com> | ||
Reviewed-by: Kenneth Russell <kbr@chromium.org> | ||
Reviewed-by: Jamie Madill <jmadill@chromium.org> | ||
|
||
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp | ||
index 53e1afd6e..5c69d568e 100644 | ||
--- a/src/libANGLE/validationES3.cpp | ||
+++ b/src/libANGLE/validationES3.cpp | ||
@@ -1339,17 +1339,26 @@ bool ValidateES3TexStorageParametersBase(const Context *context, | ||
return false; | ||
} | ||
|
||
- if (formatInfo.compressed && target == TextureType::Rectangle) | ||
+ if (formatInfo.compressed) | ||
{ | ||
- context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed); | ||
- return false; | ||
- } | ||
+ if (target == TextureType::Rectangle) | ||
+ { | ||
+ context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed); | ||
+ return false; | ||
+ } | ||
|
||
- if (formatInfo.compressed && target == TextureType::_3D) | ||
- { | ||
- if (!ValidateES3CompressedFormatForTexture3D(context, formatInfo.internalFormat)) | ||
+ if (target == TextureType::_3D) | ||
{ | ||
- // Error already generated. | ||
+ if (!ValidateES3CompressedFormatForTexture3D(context, formatInfo.internalFormat)) | ||
+ { | ||
+ // Error already generated. | ||
+ return false; | ||
+ } | ||
+ } | ||
+ | ||
+ if (!ValidCompressedImageSize(context, formatInfo.internalFormat, 0, width, height, depth)) | ||
+ { | ||
+ context->validationError(GL_INVALID_OPERATION, kInvalidCompressedImageSize); | ||
return false; | ||
} | ||
} | ||
diff --git a/src/tests/gl_tests/SRGBTextureTest.cpp b/src/tests/gl_tests/SRGBTextureTest.cpp | ||
index 271fe6dba..a0eab1af9 100644 | ||
--- a/src/tests/gl_tests/SRGBTextureTest.cpp | ||
+++ b/src/tests/gl_tests/SRGBTextureTest.cpp | ||
@@ -340,7 +340,7 @@ TEST_P(SRGBTextureTestES3, SRGBOverrideFormats) | ||
{ | ||
GLTexture tex; | ||
glBindTexture(GL_TEXTURE_2D, tex.get()); | ||
- glTexStorage2D(GL_TEXTURE_2D, 1, format, 1, 1); | ||
+ glTexStorage2D(GL_TEXTURE_2D, 1, format, 4, 4); | ||
GLenum error = glGetError(); | ||
if (error == GL_INVALID_ENUM) | ||
{ | ||
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp | ||
index fabaefbe3..efbd9ebdb 100644 | ||
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp | ||
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp | ||
@@ -5073,6 +5073,21 @@ void WebGLCompatibilityTest::testCompressedTexLevelDimension(GLenum format, | ||
{ | ||
EXPECT_GL_ERROR(expectedError) << explanation; | ||
} | ||
+ | ||
+ if (level == 0 && width > 0 && getClientMajorVersion() >= 3) | ||
+ { | ||
+ GLTexture sourceTextureStorage; | ||
+ glBindTexture(GL_TEXTURE_2D, sourceTextureStorage); | ||
+ glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height); | ||
+ if (expectedError == 0) | ||
+ { | ||
+ EXPECT_GL_NO_ERROR() << explanation << " (texStorage)"; | ||
+ } | ||
+ else | ||
+ { | ||
+ EXPECT_GL_ERROR(expectedError) << explanation << " (texStorage)"; | ||
+ } | ||
+ } | ||
} | ||
|
||
void WebGLCompatibilityTest::testCompressedTexImage(GLenum format) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,300 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: Kenneth Russell <kbr@chromium.org> | ||
Date: Wed Aug 4 18:15:51 2021 -0700 | ||
Subject: In WebGL, constrain base level of compressed textures. | ||
|
||
Enforce that if a mipmap level > 0 is specified for a compressed | ||
texture, that it implies that the size of the base level of the | ||
texture is a multiple of the format's block size. | ||
|
||
Makes the test changes in | ||
https://github.com/KhronosGroup/WebGL/pull/3304 largely pass. There | ||
are some needed follow-on fixes to that PR, and this CL changes a | ||
sub-test result in the existing S3TC and S3TC-sRGB tests which will | ||
need to be suppressed Chromium-side first. | ||
|
||
Bug: angleproject:6245 | ||
Change-Id: I7723d7882091b78a353d8d273e80b819dd384021 | ||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3072568 | ||
Commit-Queue: Kenneth Russell <kbr@chromium.org> | ||
Reviewed-by: Jamie Madill <jmadill@chromium.org> | ||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> | ||
|
||
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp | ||
index 656e51f17..412b9aa0f 100644 | ||
--- a/src/libANGLE/validationES.cpp | ||
+++ b/src/libANGLE/validationES.cpp | ||
@@ -1006,6 +1006,15 @@ bool ValidCompressedDimension(GLsizei size, GLuint blockSize, GLint level) | ||
return (level > 0) || (size % blockSize == 0); | ||
} | ||
|
||
+bool ValidCompressedBaseLevelForWebGL(GLsizei size, GLuint blockSize, GLint level) | ||
+{ | ||
+ // Avoid C++ undefined behavior. | ||
+ constexpr int maxValidShifts = 31; | ||
+ if (level > maxValidShifts) | ||
+ return false; | ||
+ return ((size << level) % blockSize) == 0; | ||
+} | ||
+ | ||
bool ValidCompressedImageSize(const Context *context, | ||
GLenum internalFormat, | ||
GLint level, | ||
@@ -1043,11 +1052,27 @@ bool ValidCompressedImageSize(const Context *context, | ||
|
||
if (CompressedTextureFormatRequiresExactSize(internalFormat)) | ||
{ | ||
- if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth, level) || | ||
- !ValidCompressedDimension(height, formatInfo.compressedBlockHeight, level) || | ||
- !ValidCompressedDimension(depth, formatInfo.compressedBlockDepth, level)) | ||
+ // In WebGL compatibility mode, enforce that the base level implied | ||
+ // by the compressed texture's mip level would conform to the block | ||
+ // size. This is more strict than the non-WebGL check. | ||
+ if (context->getExtensions().webglCompatibility) | ||
{ | ||
- return false; | ||
+ if (!ValidCompressedBaseLevelForWebGL(width, formatInfo.compressedBlockWidth, level) || | ||
+ !ValidCompressedBaseLevelForWebGL(height, formatInfo.compressedBlockHeight, | ||
+ level) || | ||
+ !ValidCompressedBaseLevelForWebGL(depth, formatInfo.compressedBlockDepth, level)) | ||
+ { | ||
+ return false; | ||
+ } | ||
+ } | ||
+ else | ||
+ { | ||
+ if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth, level) || | ||
+ !ValidCompressedDimension(height, formatInfo.compressedBlockHeight, level) || | ||
+ !ValidCompressedDimension(depth, formatInfo.compressedBlockDepth, level)) | ||
+ { | ||
+ return false; | ||
+ } | ||
} | ||
} | ||
|
||
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp | ||
index 40c9a02e3..fabaefbe3 100644 | ||
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp | ||
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp | ||
@@ -296,6 +296,16 @@ void main() | ||
GLsizei blockSize, | ||
const std::string &extName, | ||
bool subImageAllowed); | ||
+ | ||
+ GLint expectedByteLength(GLenum format, GLsizei width, GLsizei height); | ||
+ void testCompressedTexLevelDimension(GLenum format, | ||
+ GLint level, | ||
+ GLsizei width, | ||
+ GLsizei height, | ||
+ GLsizei expectedByteLength, | ||
+ GLenum expectedError, | ||
+ const char *explanation); | ||
+ void testCompressedTexImage(GLenum format); | ||
}; | ||
|
||
class WebGL2CompatibilityTest : public WebGLCompatibilityTest | ||
@@ -3040,6 +3050,84 @@ TEST_P(WebGLCompatibilityTest, CompressedTextureS3TC) | ||
ASSERT_GL_ERROR(GL_INVALID_OPERATION); | ||
} | ||
|
||
+// Test WebGL-specific constraints on sizes of S3TC textures' mipmap levels. | ||
+TEST_P(WebGLCompatibilityTest, CompressedTexImageS3TC) | ||
+{ | ||
+ const char *extensions[] = { | ||
+ "GL_EXT_texture_compression_dxt1", | ||
+ "GL_ANGLE_texture_compression_dxt3", | ||
+ "GL_ANGLE_texture_compression_dxt5", | ||
+ }; | ||
+ | ||
+ for (const char *extension : extensions) | ||
+ { | ||
+ if (IsGLExtensionRequestable(extension)) | ||
+ { | ||
+ glRequestExtensionANGLE(extension); | ||
+ } | ||
+ | ||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(extension)); | ||
+ } | ||
+ | ||
+ // Ported from WebGL conformance suite: | ||
+ // sdk/tests/conformance/extensions/s3tc-and-srgb.html | ||
+ constexpr GLenum formats[] = { | ||
+ GL_COMPRESSED_RGB_S3TC_DXT1_EXT, | ||
+ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, | ||
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, | ||
+ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, | ||
+ }; | ||
+ | ||
+ for (GLenum format : formats) | ||
+ { | ||
+ testCompressedTexImage(format); | ||
+ } | ||
+} | ||
+ | ||
+// Test WebGL-specific constraints on sizes of RGTC textures' mipmap levels. | ||
+TEST_P(WebGLCompatibilityTest, CompressedTexImageRGTC) | ||
+{ | ||
+ if (IsGLExtensionRequestable("GL_EXT_texture_compression_rgtc")) | ||
+ { | ||
+ glRequestExtensionANGLE("GL_EXT_texture_compression_rgtc"); | ||
+ } | ||
+ | ||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_rgtc")); | ||
+ | ||
+ // Ported from WebGL conformance suite: | ||
+ // sdk/tests/conformance/extensions/ext-texture-compression-rgtc.html | ||
+ constexpr GLenum formats[] = {GL_COMPRESSED_RED_RGTC1_EXT, GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, | ||
+ GL_COMPRESSED_RED_GREEN_RGTC2_EXT, | ||
+ GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT}; | ||
+ | ||
+ for (GLenum format : formats) | ||
+ { | ||
+ testCompressedTexImage(format); | ||
+ } | ||
+} | ||
+ | ||
+// Test WebGL-specific constraints on sizes of BPTC textures' mipmap levels. | ||
+TEST_P(WebGLCompatibilityTest, CompressedTexImageBPTC) | ||
+{ | ||
+ if (IsGLExtensionRequestable("GL_EXT_texture_compression_bptc")) | ||
+ { | ||
+ glRequestExtensionANGLE("GL_EXT_texture_compression_bptc"); | ||
+ } | ||
+ | ||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc")); | ||
+ | ||
+ // Ported from WebGL conformance suite: | ||
+ // sdk/tests/conformance/extensions/ext-texture-compression-bptc.html | ||
+ constexpr GLenum formats[] = { | ||
+ GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, | ||
+ GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT}; | ||
+ | ||
+ for (GLenum format : formats) | ||
+ { | ||
+ testCompressedTexImage(format); | ||
+ } | ||
+} | ||
+ | ||
TEST_P(WebGLCompatibilityTest, L32FTextures) | ||
{ | ||
constexpr float textureData[] = {15.1f, 0.0f, 0.0f, 0.0f}; | ||
@@ -4937,6 +5025,119 @@ void WebGLCompatibilityTest::validateCompressedTexImageExtensionFormat(GLenum fo | ||
} | ||
} | ||
|
||
+GLint WebGLCompatibilityTest::expectedByteLength(GLenum format, GLsizei width, GLsizei height) | ||
+{ | ||
+ switch (format) | ||
+ { | ||
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | ||
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: | ||
+ case GL_COMPRESSED_RED_RGTC1_EXT: | ||
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT: | ||
+ return ((width + 3) / 4) * ((height + 3) / 4) * 8; | ||
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: | ||
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | ||
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: | ||
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: | ||
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT: | ||
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT: | ||
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT: | ||
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT: | ||
+ return ((width + 3) / 4) * ((height + 3) / 4) * 16; | ||
+ } | ||
+ | ||
+ UNREACHABLE(); | ||
+ return 0; | ||
+} | ||
+ | ||
+void WebGLCompatibilityTest::testCompressedTexLevelDimension(GLenum format, | ||
+ GLint level, | ||
+ GLsizei width, | ||
+ GLsizei height, | ||
+ GLsizei expectedByteLength, | ||
+ GLenum expectedError, | ||
+ const char *explanation) | ||
+{ | ||
+ std::vector<uint8_t> tempVector(expectedByteLength, 0); | ||
+ | ||
+ EXPECT_GL_NO_ERROR(); | ||
+ | ||
+ GLTexture sourceTexture; | ||
+ glBindTexture(GL_TEXTURE_2D, sourceTexture); | ||
+ glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height, 0, expectedByteLength, | ||
+ tempVector.data()); | ||
+ if (expectedError == 0) | ||
+ { | ||
+ EXPECT_GL_NO_ERROR() << explanation; | ||
+ } | ||
+ else | ||
+ { | ||
+ EXPECT_GL_ERROR(expectedError) << explanation; | ||
+ } | ||
+} | ||
+ | ||
+void WebGLCompatibilityTest::testCompressedTexImage(GLenum format) | ||
+{ | ||
+ struct TestCase | ||
+ { | ||
+ GLint level; | ||
+ GLsizei width; | ||
+ GLsizei height; | ||
+ GLenum expectedError; | ||
+ const char *explanation; | ||
+ }; | ||
+ | ||
+ constexpr TestCase testCases[] = { | ||
+ {0, 4, 3, GL_INVALID_OPERATION, "level is 0, height is not a multiple of 4"}, | ||
+ {0, 3, 4, GL_INVALID_OPERATION, "level is 0, width is not a multiple of 4"}, | ||
+ {0, 2, 2, GL_INVALID_OPERATION, "level is 0, width is not a multiple of 4"}, | ||
+ {0, 4, 4, GL_NO_ERROR, "is valid"}, | ||
+ {1, 1, 1, GL_INVALID_OPERATION, "implied base mip 2x2 is invalid"}, | ||
+ {1, 1, 2, GL_INVALID_OPERATION, "implied base mip 2x4 is invalid"}, | ||
+ {1, 2, 1, GL_INVALID_OPERATION, "implied base mip 4x2 is invalid"}, | ||
+ {1, 2, 2, GL_NO_ERROR, "implied base mip 4x4 is valid"}, | ||
+ }; | ||
+ | ||
+ constexpr TestCase webgl2TestCases[] = { | ||
+ {0, 0, 0, GL_NO_ERROR, "0: 0x0 is valid"}, | ||
+ {0, 1, 1, GL_INVALID_OPERATION, "0: 1x1 is invalid"}, | ||
+ {0, 2, 2, GL_INVALID_OPERATION, "0: 2x2 is invalid"}, | ||
+ {0, 3, 3, GL_INVALID_OPERATION, "0: 3x3 is invalid"}, | ||
+ {0, 10, 10, GL_INVALID_OPERATION, "0: 10x10 is invalid"}, | ||
+ {0, 11, 11, GL_INVALID_OPERATION, "0: 11x11 is invalid"}, | ||
+ {0, 11, 12, GL_INVALID_OPERATION, "0: 11x12 is invalid"}, | ||
+ {0, 12, 11, GL_INVALID_OPERATION, "0: 12x11 is invalid"}, | ||
+ {0, 12, 12, GL_NO_ERROR, "0: 12x12 is valid"}, | ||
+ {1, 0, 0, GL_NO_ERROR, "1: 0x0 is valid"}, | ||
+ {1, 3, 3, GL_INVALID_OPERATION, "1: 3x3 is invalid"}, | ||
+ {1, 5, 5, GL_INVALID_OPERATION, "1: 5x5 is invalid"}, | ||
+ {1, 5, 6, GL_INVALID_OPERATION, "1: 5x6 is invalid"}, | ||
+ {1, 6, 5, GL_INVALID_OPERATION, "1: 6x5 is invalid"}, | ||
+ {1, 6, 6, GL_NO_ERROR, "1: 6x6 is valid"}, | ||
+ {2, 0, 0, GL_NO_ERROR, "2: 0x0 is valid"}, | ||
+ {2, 3, 3, GL_NO_ERROR, "2: 3x3 is valid"}, | ||
+ {3, 1, 3, GL_NO_ERROR, "3: 1x3 is valid"}, | ||
+ {3, 1, 1, GL_NO_ERROR, "3: 1x1 is valid"}, | ||
+ {2, 1, 3, GL_NO_ERROR, "implied base mip 4x12 is valid"}, | ||
+ }; | ||
+ | ||
+ for (const TestCase &test : testCases) | ||
+ { | ||
+ testCompressedTexLevelDimension(format, test.level, test.width, test.height, | ||
+ expectedByteLength(format, test.width, test.height), | ||
+ test.expectedError, test.explanation); | ||
+ } | ||
+ | ||
+ if (getClientMajorVersion() >= 3) | ||
+ { | ||
+ for (const TestCase &test : webgl2TestCases) | ||
+ { | ||
+ testCompressedTexLevelDimension(format, test.level, test.width, test.height, | ||
+ expectedByteLength(format, test.width, test.height), | ||
+ test.expectedError, test.explanation); | ||
+ } | ||
+ } | ||
+} | ||
+ | ||
// Test enabling GL_EXT_texture_compression_dxt1 for GL_COMPRESSED_RGB_S3TC_DXT1_EXT | ||
TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1RGB) | ||
{ |
Oops, something went wrong.