diff --git a/patches/angle/.patches b/patches/angle/.patches new file mode 100644 index 0000000000000..89ec7cba41053 --- /dev/null +++ b/patches/angle/.patches @@ -0,0 +1,2 @@ +cherry-pick-d8cb996.patch +cherry-pick-1fb846c.patch diff --git a/patches/angle/cherry-pick-1fb846c.patch b/patches/angle/cherry-pick-1fb846c.patch new file mode 100644 index 0000000000000..733a3794f6dad --- /dev/null +++ b/patches/angle/cherry-pick-1fb846c.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alexey Knyazev +Date: Tue, 3 Aug 2021 01:57:49 +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 +Reviewed-by: Kenneth Russell +Reviewed-by: Jamie Madill + +diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp +index 53e1afd6e26ef8cc099e51c66457a968ca82b1c8..5c69d568ee45b9e8bf1d4d0da7b9a48b123a47c0 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 271fe6dbaa1d5684f7c2e16bdef18bce30943e8b..a0eab1af9e34a5de75e226efef9c0af4a50c63ff 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 fabaefbe33c94a048ec7c974951ac9ef886826ef..efbd9ebdb2bb29cf9673750e1e3e7b492bfbf87e 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) diff --git a/patches/angle/cherry-pick-d8cb996.patch b/patches/angle/cherry-pick-d8cb996.patch new file mode 100644 index 0000000000000..26f998699f7da --- /dev/null +++ b/patches/angle/cherry-pick-d8cb996.patch @@ -0,0 +1,300 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kenneth Russell +Date: Wed, 4 Aug 2021 18:15:51 -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 +Reviewed-by: Jamie Madill +Reviewed-by: Shahbaz Youssefi + +diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp +index 656e51f17724af9e0959fcd741ceeebf25ee0f24..412b9aa0f1d75c40ce02522589c53e943d049228 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 40c9a02e3eafe9d437e20e72a391bad73c783516..fabaefbe33c94a048ec7c974951ac9ef886826ef 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 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) + { diff --git a/patches/config.json b/patches/config.json index 758169dd989f8..56ea6c0f83eff 100644 --- a/patches/config.json +++ b/patches/config.json @@ -17,5 +17,7 @@ "src/electron/patches/nan": "src/third_party/nan", + "src/electron/patches/angle": "src/third_party/angle", + "src/electron/patches/sqlite": "src/third_party/sqlite/src" }