mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
* chore: cherry-pick 1234829 from angle * chore: update patches Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
301 lines
12 KiB
Diff
301 lines
12 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Kenneth Russell <kbr@chromium.org>
|
|
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 <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 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<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)
|
|
{
|