// // Copyright 2021 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // CompressedTextureFormatsTest: // Tests that only the appropriate entry points are affected after // enabling compressed texture extensions. // #include "common/gl_enum_utils.h" #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" using namespace angle; namespace { struct FormatDesc { GLenum format; GLsizei blockX; GLsizei blockY; GLsizei size; bool isPVRTC1() const { return ((format & ~3) == GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG) || ((format & ~3) == GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT); } bool mayBeEmulated() const { return format == GL_COMPRESSED_R11_EAC || format == GL_COMPRESSED_RG11_EAC || format == GL_COMPRESSED_SIGNED_R11_EAC || format == GL_COMPRESSED_SIGNED_RG11_EAC || format == GL_ETC1_RGB8_OES || format == GL_COMPRESSED_RGB8_ETC2 || format == GL_COMPRESSED_SRGB8_ETC2 || format == GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 || format == GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 || format == GL_COMPRESSED_RGBA8_ETC2_EAC || format == GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC; } }; using CompressedTextureTestParams = std::tuple; class CompressedTextureFormatsTest : public ANGLETest { public: CompressedTextureFormatsTest(const std::string ext1, const std::string ext2, const bool supportsUpdates, const bool supportsPartialUpdates, const bool supports2DArray, const bool supports3D, const bool alwaysOnES3) : mExtNames({ext1, ext2}), mSupportsUpdates(supportsUpdates), mSupportsPartialUpdates(supportsPartialUpdates), mSupports2DArray(supports2DArray), mSupports3D(supports3D), mAlwaysOnES3(alwaysOnES3) { setExtensionsEnabled(false); } void testSetUp() override { // Apple platforms require PVRTC1 textures to be squares. mSquarePvrtc1 = IsAppleGPU(); } void checkSubImage2D(FormatDesc desc, int numX) { GLubyte data[64] = {}; // The semantic of this call is to take uncompressed data, compress it on-the-fly, // and perform a partial update of an existing GPU-compressed texture. This // operation is not supported in OpenGL ES. glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.blockX, desc.blockY, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_ERROR(GL_INVALID_OPERATION); // Compressed texture extensions never extend TexSubImage2D. glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.blockX, desc.blockY, desc.format, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_ERROR(GL_INVALID_ENUM); // The semantic of this call is to take pixel data from the current framebuffer, compress it // on-the-fly, and perform a partial update of an existing GPU-compressed texture. This // operation is not supported in OpenGL ES. glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, desc.blockX, desc.blockY); EXPECT_GL_ERROR(GL_INVALID_OPERATION); // Try whole image update. It is always valid when API supports updates. glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.blockX * numX, desc.blockY * 2, desc.format, desc.size * 4, data); if (!mSupportsUpdates) { EXPECT_GL_ERROR(GL_INVALID_OPERATION); return; } EXPECT_GL_NO_ERROR(); if (!mSupportsPartialUpdates) { glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.blockX, desc.blockY, desc.format, desc.size, data); EXPECT_GL_ERROR(GL_INVALID_OPERATION); return; } // All compressed formats that support partial updates require the offsets to be // multiples of block dimensions. glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 1, 0, desc.blockX, desc.blockY, desc.format, desc.size, data); EXPECT_GL_ERROR(GL_INVALID_OPERATION); glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 1, desc.blockX, desc.blockY, desc.format, desc.size, data); EXPECT_GL_ERROR(GL_INVALID_OPERATION); // All compressed formats that support partial updates require the dimensions to be // multiples of block dimensions or reach the image boundaries. glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.blockX - 1, desc.blockY, desc.format, desc.size, data); EXPECT_GL_ERROR(GL_INVALID_OPERATION); glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.blockX, desc.blockY - 1, desc.format, desc.size, data); EXPECT_GL_ERROR(GL_INVALID_OPERATION); // Test should pass when replaced region dimensions are multiples the of block // dimensions // clang-format off glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.blockX, desc.blockY, desc.format, desc.size, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, desc.blockX, 0, desc.blockX, desc.blockY, desc.format, desc.size, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, desc.blockY, desc.blockX, desc.blockY, desc.format, desc.size, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, desc.blockX, desc.blockY, desc.blockX, desc.blockY, desc.format, desc.size, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.blockX * 2, desc.blockY, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.blockX, desc.blockY * 2, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, desc.blockY, desc.blockX * 2, desc.blockY, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, desc.blockX, 0, desc.blockX, desc.blockY * 2, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); // clang-format on // Test should pass when replaced region dimensions are not multiples of block dimensions // but reach the image boundaries. For example, it is valid to replace right-bottom 2x2 // region of a 6x6 texture made of 4x4 blocks. To check this on all platforms with the same // code, level 1 should be used to avoid hitting a D3D11 limitation. if (getClientMajorVersion() >= 3 || EnsureGLExtensionEnabled("GL_OES_texture_npot")) { GLTexture texture; glBindTexture(GL_TEXTURE_2D, texture); const int newW = desc.blockX * 3; const int newH = desc.blockY * 3; glCompressedTexImage2D(GL_TEXTURE_2D, 0, desc.format, newW, newH, 0, desc.size * 9, nullptr); EXPECT_GL_NO_ERROR(); glCompressedTexImage2D(GL_TEXTURE_2D, 1, desc.format, newW / 2, newH / 2, 0, desc.size * 4, nullptr); EXPECT_GL_NO_ERROR(); // clang-format off glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, desc.blockX, 0, desc.blockX / 2, desc.blockY, desc.format, desc.size * 1, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, desc.blockX, 0, desc.blockX / 2, desc.blockY * 3 / 2, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, desc.blockY, desc.blockX, desc.blockY / 2, desc.format, desc.size * 1, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, desc.blockY, desc.blockX * 3 / 2, desc.blockY / 2, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, desc.blockX, desc.blockY, desc.blockX / 2, desc.blockY / 2, desc.format, desc.size * 1, data); EXPECT_GL_NO_ERROR(); // clang-format on } } void checkSubImage3D(GLenum target, FormatDesc desc) { GLubyte data[128] = {}; // The semantic of this call is to take uncompressed data, compress it on-the-fly, // and perform a partial update of an existing GPU-compressed texture. This // operation is not supported in OpenGL ES. glTexSubImage3D(target, 0, 0, 0, 0, desc.blockX, desc.blockY, 2, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_ERROR(GL_INVALID_OPERATION); // Compressed texture extensions never extend TexSubImage3D. glTexSubImage3D(target, 0, 0, 0, 0, desc.blockX, desc.blockY, 2, desc.format, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_ERROR(GL_INVALID_ENUM); // The semantic of this call is to take pixel data from the current framebuffer, compress it // on-the-fly, and perform a partial update of an existing GPU-compressed texture. This // operation is not supported in OpenGL ES. glCopyTexSubImage3D(target, 0, 0, 0, 0, 0, 0, desc.blockX, desc.blockY); EXPECT_GL_ERROR(GL_INVALID_OPERATION); // All formats that are accepted for 3D entry points support updates. ASSERT(mSupportsUpdates); // Try whole image update. It is always valid for formats that support updates. glCompressedTexSubImage3D(target, 0, 0, 0, 0, desc.blockX * 2, desc.blockY * 2, 2, desc.format, desc.size * 8, data); EXPECT_GL_NO_ERROR(); // Try a whole image update from a pixel unpack buffer. // Don't test non-emulated formats on Desktop GL. // TODO(anglebug.com/42264819): implement emulation on Desktop GL, then remove this check. if (!(IsDesktopOpenGL() && desc.mayBeEmulated())) { GLBuffer buffer; glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer); glBufferData(GL_PIXEL_UNPACK_BUFFER, 128, data, GL_STREAM_DRAW); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, 0, 0, 0, desc.blockX * 2, desc.blockY * 2, 2, desc.format, desc.size * 8, nullptr); EXPECT_GL_NO_ERROR(); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); } // All formats that are accepted for 3D entry points support partial updates. ASSERT(mSupportsPartialUpdates); // All compressed formats that support partial updates require the offsets to be // multiples of block dimensions. glCompressedTexSubImage3D(target, 0, 1, 0, 0, desc.blockX, desc.blockY, 1, desc.format, desc.size, data); EXPECT_GL_ERROR(GL_INVALID_OPERATION); glCompressedTexSubImage3D(target, 0, 0, 1, 0, desc.blockX, desc.blockY, 1, desc.format, desc.size, data); EXPECT_GL_ERROR(GL_INVALID_OPERATION); // All compressed formats that support partial updates require the dimensions to be // multiples of block dimensions or reach the image boundaries. glCompressedTexSubImage3D(target, 0, 0, 0, 0, desc.blockX - 1, desc.blockY, 1, desc.format, desc.size, data); EXPECT_GL_ERROR(GL_INVALID_OPERATION); glCompressedTexSubImage3D(target, 0, 0, 0, 0, desc.blockX, desc.blockY - 1, 1, desc.format, desc.size, data); EXPECT_GL_ERROR(GL_INVALID_OPERATION); // Valid partial updates // clang-format off glCompressedTexSubImage3D(target, 0, 0, 0, 0, desc.blockX, desc.blockY, 1, desc.format, desc.size, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, desc.blockX, 0, 0, desc.blockX, desc.blockY, 1, desc.format, desc.size, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, 0, desc.blockY, 0, desc.blockX, desc.blockY, 1, desc.format, desc.size, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, desc.blockX, desc.blockY, 0, desc.blockX, desc.blockY, 1, desc.format, desc.size, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, 0, 0, 1, desc.blockX, desc.blockY, 1, desc.format, desc.size, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, desc.blockX, 0, 1, desc.blockX, desc.blockY, 1, desc.format, desc.size, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, 0, desc.blockY, 1, desc.blockX, desc.blockY, 1, desc.format, desc.size, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, desc.blockX, desc.blockY, 1, desc.blockX, desc.blockY, 1, desc.format, desc.size, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, 0, 0, 0, desc.blockX * 2, desc.blockY, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, 0, 0, 0, desc.blockX, desc.blockY * 2, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, 0, desc.blockY, 0, desc.blockX * 2, desc.blockY, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, desc.blockX, 0, 0, desc.blockX, desc.blockY * 2, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, 0, 0, 1, desc.blockX * 2, desc.blockY, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, 0, 0, 1, desc.blockX, desc.blockY * 2, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, 0, desc.blockY, 1, desc.blockX * 2, desc.blockY, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, desc.blockX, 0, 1, desc.blockX, desc.blockY * 2, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, 0, 0, 0, desc.blockX, desc.blockY, 2, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, desc.blockX, 0, 0, desc.blockX, desc.blockY, 2, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, 0, desc.blockY, 0, desc.blockX, desc.blockY, 2, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 0, desc.blockX, desc.blockY, 0, desc.blockX, desc.blockY, 2, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); // clang-format on // Test should pass when replaced region dimensions are not multiples of block dimensions // but reach the image boundaries. For example, it is valid to replace right-bottom 2x2 // region of a 6x6 texture made of 4x4 blocks. To check this on all platforms with the same // code, level 1 should be used to avoid hitting a D3D11 limitation. { GLTexture texture; glBindTexture(target, texture); const int newW = desc.blockX * 3; const int newH = desc.blockY * 3; glCompressedTexImage3D(target, 0, desc.format, newW, newH, 2, 0, desc.size * 18, nullptr); EXPECT_GL_NO_ERROR(); if (target == GL_TEXTURE_2D_ARRAY) { glCompressedTexImage3D(target, 1, desc.format, newW / 2, newH / 2, 2, 0, desc.size * 8, nullptr); EXPECT_GL_NO_ERROR(); // clang-format off glCompressedTexSubImage3D(target, 1, desc.blockX, 0, 0, desc.blockX / 2, desc.blockY, 1, desc.format, desc.size * 1, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, desc.blockX, 0, 0, desc.blockX / 2, desc.blockY * 3 / 2, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, 0, desc.blockY, 0, desc.blockX, desc.blockY / 2, 1, desc.format, desc.size * 1, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, 0, desc.blockY, 0, desc.blockX * 3 / 2, desc.blockY / 2, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, desc.blockX, desc.blockY, 0, desc.blockX / 2, desc.blockY / 2, 1, desc.format, desc.size * 1, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, desc.blockX, 0, 1, desc.blockX / 2, desc.blockY, 1, desc.format, desc.size * 1, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, desc.blockX, 0, 1, desc.blockX / 2, desc.blockY * 3 / 2, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, 0, desc.blockY, 1, desc.blockX, desc.blockY / 2, 1, desc.format, desc.size * 1, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, 0, desc.blockY, 1, desc.blockX * 3 / 2, desc.blockY / 2, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, desc.blockX, desc.blockY, 1, desc.blockX / 2, desc.blockY / 2, 1, desc.format, desc.size * 1, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, desc.blockX, 0, 0, desc.blockX / 2, desc.blockY, 2, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, desc.blockX, 0, 0, desc.blockX / 2, desc.blockY * 3 / 2, 2, desc.format, desc.size * 4, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, 0, desc.blockY, 0, desc.blockX, desc.blockY / 2, 2, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, 0, desc.blockY, 0, desc.blockX * 3 / 2, desc.blockY / 2, 2, desc.format, desc.size * 4, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, desc.blockX, desc.blockY, 0, desc.blockX / 2, desc.blockY / 2, 2, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); // clang-format on } else { glCompressedTexImage3D(target, 1, desc.format, newW / 2, newH / 2, 1, 0, desc.size * 4, nullptr); EXPECT_GL_NO_ERROR(); // clang-format off glCompressedTexSubImage3D(target, 1, desc.blockX, 0, 0, desc.blockX / 2, desc.blockY, 1, desc.format, desc.size * 1, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, desc.blockX, 0, 0, desc.blockX / 2, desc.blockY * 3 / 2, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, 0, desc.blockY, 0, desc.blockX, desc.blockY / 2, 1, desc.format, desc.size * 1, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, 0, desc.blockY, 0, desc.blockX * 3 / 2, desc.blockY / 2, 1, desc.format, desc.size * 2, data); EXPECT_GL_NO_ERROR(); glCompressedTexSubImage3D(target, 1, desc.blockX, desc.blockY, 0, desc.blockX / 2, desc.blockY / 2, 1, desc.format, desc.size * 1, data); EXPECT_GL_NO_ERROR(); // clang-format on } } } void check2D(const bool compressedFormatEnabled) { const FormatDesc desc = ::testing::get<1>(GetParam()); { GLTexture texture; glBindTexture(GL_TEXTURE_2D, texture); // The semantic of this call is to take uncompressed data and compress it on-the-fly. // This operation is not supported in OpenGL ES. glTexImage2D(GL_TEXTURE_2D, 0, desc.format, desc.blockX, desc.blockY, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_ERROR(GL_INVALID_VALUE); // Try compressed enum as format. Compressed texture extensions never allow this. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, desc.blockX, desc.blockY, 0, desc.format, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_ERROR(GL_INVALID_ENUM); // The semantic of this call is to take pixel data from the current framebuffer // and create a compressed texture from it on-the-fly. This operation is not supported // in OpenGL ES. glCopyTexImage2D(GL_TEXTURE_2D, 0, desc.format, 0, 0, desc.blockX, desc.blockY, 0); EXPECT_GL_ERROR(GL_INVALID_OPERATION); glCompressedTexImage2D(GL_TEXTURE_2D, 0, desc.format, desc.blockX, desc.blockY, 0, desc.size, nullptr); if (compressedFormatEnabled) { int numX = 2; if (desc.isPVRTC1()) { if (mSquarePvrtc1 && desc.blockX == 8) { EXPECT_GL_ERROR(GL_INVALID_OPERATION); numX = 1; } else { // PVRTC1 formats require data size for at least 2x2 blocks. EXPECT_GL_ERROR(GL_INVALID_VALUE); } } else { EXPECT_GL_NO_ERROR(); } // Create a texture with more than one block to test partial updates glCompressedTexImage2D(GL_TEXTURE_2D, 0, desc.format, desc.blockX * numX, desc.blockY * 2, 0, desc.size * 4, nullptr); EXPECT_GL_NO_ERROR(); checkSubImage2D(desc, numX); } else { EXPECT_GL_ERROR(GL_INVALID_ENUM); } } if (getClientMajorVersion() >= 3) { GLTexture texture; glBindTexture(GL_TEXTURE_2D, texture); glTexStorage2D(GL_TEXTURE_2D, 1, desc.format, desc.blockX * 2, desc.blockY * 2); if (compressedFormatEnabled) { int numX = 2; if (desc.isPVRTC1() && mSquarePvrtc1 && desc.blockX == 8) { EXPECT_GL_ERROR(GL_INVALID_OPERATION); numX = 1; glTexStorage2D(GL_TEXTURE_2D, 1, desc.format, desc.blockX, desc.blockY * 2); } EXPECT_GL_NO_ERROR(); checkSubImage2D(desc, numX); } else { EXPECT_GL_ERROR(GL_INVALID_ENUM); } } if (EnsureGLExtensionEnabled("GL_EXT_texture_storage")) { GLTexture texture; glBindTexture(GL_TEXTURE_2D, texture); glTexStorage2DEXT(GL_TEXTURE_2D, 1, desc.format, desc.blockX * 2, desc.blockY * 2); if (compressedFormatEnabled) { int numX = 2; if (desc.isPVRTC1() && mSquarePvrtc1 && desc.blockX == 8) { EXPECT_GL_ERROR(GL_INVALID_OPERATION); numX = 1; glTexStorage2DEXT(GL_TEXTURE_2D, 1, desc.format, desc.blockX, desc.blockY * 2); } EXPECT_GL_NO_ERROR(); checkSubImage2D(desc, numX); } else { EXPECT_GL_ERROR(GL_INVALID_ENUM); } } } void check3D(GLenum target, const bool compressedFormatEnabled, const bool supportsTarget) { const FormatDesc desc = ::testing::get<1>(GetParam()); { GLTexture texture; glBindTexture(target, texture); // Try compressed enum as internalformat. The semantic of this call is to take // uncompressed data and compress it on-the-fly. This operation is not supported in // OpenGL ES. glTexImage3D(target, 0, desc.format, desc.blockX, desc.blockX, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_ERROR(GL_INVALID_VALUE); // Try compressed enum as format. Compressed texture extensions never allow this. glTexImage3D(target, 0, GL_RGB, desc.blockX, desc.blockX, 1, 0, desc.format, GL_UNSIGNED_BYTE, nullptr); EXPECT_GL_ERROR(GL_INVALID_ENUM); glCompressedTexImage3D(target, 0, desc.format, desc.blockX * 2, desc.blockY * 2, 2, 0, desc.size * 8, nullptr); if (compressedFormatEnabled) { if (supportsTarget) { EXPECT_GL_NO_ERROR(); checkSubImage3D(target, desc); } else { EXPECT_GL_ERROR(GL_INVALID_OPERATION); } } else { EXPECT_GL_ERROR(GL_INVALID_ENUM); } } { GLTexture texture; glBindTexture(target, texture); glTexStorage3D(target, 1, desc.format, desc.blockX * 2, desc.blockY * 2, 2); if (compressedFormatEnabled) { if (supportsTarget) { EXPECT_GL_NO_ERROR(); checkSubImage3D(target, desc); } else { EXPECT_GL_ERROR(GL_INVALID_OPERATION); } } else { EXPECT_GL_ERROR(GL_INVALID_ENUM); } } } void testSamplerSliced3D(GLenum target) { ASSERT(target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_3D); const FormatDesc desc = ::testing::get<1>(GetParam()); { int width = desc.blockX; int height = desc.blockY; int depth = 9; static GLubyte red_RGBA_ASTC_block_data[144] = { 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 252, 253, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255}; GLTexture texID; glActiveTexture(GL_TEXTURE0); glBindTexture(target, texID); EXPECT_GL_NO_ERROR(); glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glCompressedTexImage3D(target, 0, desc.format, width, height, depth, 0, desc.size * depth, red_RGBA_ASTC_block_data); EXPECT_GL_NO_ERROR(); float layer = 0.0f; for (int i = 0; i < depth; i++) { GLFramebuffer fb; glBindFramebuffer(GL_FRAMEBUFFER, fb); GLRenderbuffer rb; glBindRenderbuffer(GL_RENDERBUFFER, rb); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb); EXPECT_GL_NO_ERROR(); glViewport(0, 0, width, height); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); if (target == GL_TEXTURE_2D_ARRAY) { layer = i * 1.0f; draw2DArrayTexturedQuad(0.0f, 1.0f, false, layer); } else { layer = ((float)i + 0.5f) / (float)depth; draw3DTexturedQuad(0.0f, 1.0f, false, layer); } std::vector pixels(width * height); glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { const int curPos = y * width + x; EXPECT_COLOR_NEAR(GLColor::red, pixels[curPos], 2); } } } } } void test() { // ETC2/EAC formats always pass validation on ES3 contexts but in some cases fail in drivers // because their emulation is not implemented for OpenGL renderer. // https://crbug.com/angleproject/6300 if (mAlwaysOnES3) { ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3 && !IsGLExtensionRequestable(mExtNames[0])); } // It's not possible to disable ETC2/EAC support on ES 3.0. const bool compressedFormatEnabled = mAlwaysOnES3 && getClientMajorVersion() >= 3; check2D(compressedFormatEnabled); if (getClientMajorVersion() >= 3) { check3D(GL_TEXTURE_2D_ARRAY, compressedFormatEnabled, mSupports2DArray); check3D(GL_TEXTURE_3D, compressedFormatEnabled, mSupports3D && !mDisableTexture3D); } for (const std::string &extName : mExtNames) { if (!extName.empty()) { if (IsGLExtensionRequestable(extName)) { glRequestExtensionANGLE(extName.c_str()); } ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(extName)); } } // Repeat all checks after enabling the extensions. check2D(true); if (getClientMajorVersion() >= 3) { check3D(GL_TEXTURE_2D_ARRAY, true, mSupports2DArray); check3D(GL_TEXTURE_3D, true, mSupports3D && !mDisableTexture3D); } } void testSamplerASTCSliced3D() { for (const std::string &extName : mExtNames) { if (!extName.empty()) { if (IsGLExtensionRequestable(extName)) { glRequestExtensionANGLE(extName.c_str()); } ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(extName)); } } if (getClientMajorVersion() >= 3) { testSamplerSliced3D(GL_TEXTURE_2D_ARRAY); testSamplerSliced3D(GL_TEXTURE_3D); } } private: bool mSquarePvrtc1 = false; bool mDisableTexture3D = false; const std::vector mExtNames; const bool mSupportsUpdates; const bool mSupportsPartialUpdates; const bool mSupports2DArray; const bool mSupports3D; const bool mAlwaysOnES3; }; template class _Test : public CompressedTextureFormatsTest { public: _Test() : CompressedTextureFormatsTest(ext1, ext2, supports_updates, supports_partial_updates, supports_2d_array, supports_3d, always_on_es3) {} }; const char kDXT1[] = "GL_EXT_texture_compression_dxt1"; const char kDXT3[] = "GL_ANGLE_texture_compression_dxt3"; const char kDXT5[] = "GL_ANGLE_texture_compression_dxt5"; const char kS3TCSRGB[] = "GL_EXT_texture_compression_s3tc_srgb"; const char kRGTC[] = "GL_EXT_texture_compression_rgtc"; const char kBPTC[] = "GL_EXT_texture_compression_bptc"; const char kETC1[] = "GL_OES_compressed_ETC1_RGB8_texture"; const char kETC1Sub[] = "GL_EXT_compressed_ETC1_RGB8_sub_texture"; const char kEACR11U[] = "GL_OES_compressed_EAC_R11_unsigned_texture"; const char kEACR11S[] = "GL_OES_compressed_EAC_R11_signed_texture"; const char kEACRG11U[] = "GL_OES_compressed_EAC_RG11_unsigned_texture"; const char kEACRG11S[] = "GL_OES_compressed_EAC_RG11_signed_texture"; const char kETC2RGB8[] = "GL_OES_compressed_ETC2_RGB8_texture"; const char kETC2RGB8SRGB[] = "GL_OES_compressed_ETC2_sRGB8_texture"; const char kETC2RGB8A1[] = "GL_OES_compressed_ETC2_punchthroughA_RGBA8_texture"; const char kETC2RGB8A1SRGB[] = "GL_OES_compressed_ETC2_punchthroughA_sRGB8_alpha_texture"; const char kETC2RGBA8[] = "GL_OES_compressed_ETC2_RGBA8_texture"; const char kETC2RGBA8SRGB[] = "GL_OES_compressed_ETC2_sRGB8_alpha8_texture"; const char kASTC[] = "GL_KHR_texture_compression_astc_ldr"; const char kASTCSliced3D[] = "GL_KHR_texture_compression_astc_sliced_3d"; const char kPVRTC1[] = "GL_IMG_texture_compression_pvrtc"; const char kPVRTCSRGB[] = "GL_EXT_pvrtc_sRGB"; const char kEmpty[] = ""; // clang-format off using CompressedTextureDXT1Test = _Test; using CompressedTextureDXT3Test = _Test; using CompressedTextureDXT5Test = _Test; using CompressedTextureS3TCSRGBTest = _Test; using CompressedTextureRGTCTest = _Test; using CompressedTextureBPTCTest = _Test; using CompressedTextureETC1Test = _Test; using CompressedTextureETC1SubTest = _Test; using CompressedTextureEACR11UTest = _Test; using CompressedTextureEACR11STest = _Test; using CompressedTextureEACRG11UTest = _Test; using CompressedTextureEACRG11STest = _Test; using CompressedTextureETC2RGB8Test = _Test; using CompressedTextureETC2RGB8SRGBTest = _Test; using CompressedTextureETC2RGB8A1Test = _Test; using CompressedTextureETC2RGB8A1SRGBTest = _Test; using CompressedTextureETC2RGBA8Test = _Test; using CompressedTextureETC2RGBA8SRGBTest = _Test; using CompressedTextureASTCTest = _Test; using CompressedTextureASTCSliced3DTest = _Test; using CompressedTextureSamplerASTCSliced3DTest = _Test; using CompressedTexturePVRTC1Test = _Test; using CompressedTexturePVRTC1SRGBTest = _Test; // clang-format on std::string PrintToStringParamName( const ::testing::TestParamInfo &info) { std::string name = gl::GLinternalFormatToString(std::get<1>(info.param).format); if (name.find("GL_") == 0) name.erase(0, 3); if (name.find("COMPRESSED_") == 0) name.erase(0, 11); for (std::string str : {"_EXT", "_IMG", "_KHR", "_OES"}) { if (name.find(str) != std::string::npos) { name.erase(name.length() - 4, 4); break; } } std::stringstream nameStr; nameStr << std::get<0>(info.param) << "__" << name; return nameStr.str(); } static const FormatDesc kDXT1Formats[] = {{GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 8}, {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 8}}; static const FormatDesc kDXT3Formats[] = {{GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 16}}; static const FormatDesc kDXT5Formats[] = {{GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 4, 4, 16}}; static const FormatDesc kS3TCSRGBFormats[] = {{GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 4, 4, 8}, {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 4, 4, 8}, {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 4, 4, 16}, {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 4, 4, 16}}; static const FormatDesc kRGTCFormats[] = {{GL_COMPRESSED_RED_RGTC1_EXT, 4, 4, 8}, {GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, 4, 4, 8}, {GL_COMPRESSED_RED_GREEN_RGTC2_EXT, 4, 4, 16}, {GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, 4, 4, 16}}; static const FormatDesc kBPTCFormats[] = {{GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 16}, {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, 4, 4, 16}, {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, 4, 4, 16}, {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, 4, 4, 16}}; static const FormatDesc kETC1Formats[] = {{GL_ETC1_RGB8_OES, 4, 4, 8}}; // clang-format off static const FormatDesc kEACR11UFormats[] = {{GL_COMPRESSED_R11_EAC, 4, 4, 8}}; static const FormatDesc kEACR11SFormats[] = {{GL_COMPRESSED_SIGNED_R11_EAC, 4, 4, 8}}; static const FormatDesc kEACRG11UFormats[] = {{GL_COMPRESSED_RG11_EAC, 4, 4, 16}}; static const FormatDesc kEACRG11SFormats[] = {{GL_COMPRESSED_SIGNED_RG11_EAC, 4, 4, 16}}; static const FormatDesc kETC2RGB8Formats[] = {{GL_COMPRESSED_RGB8_ETC2, 4, 4, 8}}; static const FormatDesc kETC2RGB8SRGBFormats[] = {{GL_COMPRESSED_SRGB8_ETC2, 4, 4, 8}}; static const FormatDesc kETC2RGB8A1Formats[] = {{GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 8}}; static const FormatDesc kETC2RGB8A1SRGBFormats[] = {{GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 8}}; static const FormatDesc kETC2RGBA8Formats[] = {{GL_COMPRESSED_RGBA8_ETC2_EAC, 4, 4, 16}}; static const FormatDesc kETC2RGBA8SRGBFormats[] = {{GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 4, 4, 16}}; // clang-format on static const FormatDesc kASTCFormats[] = {{GL_COMPRESSED_RGBA_ASTC_4x4_KHR, 4, 4, 16}, {GL_COMPRESSED_RGBA_ASTC_5x4_KHR, 5, 4, 16}, {GL_COMPRESSED_RGBA_ASTC_5x5_KHR, 5, 5, 16}, {GL_COMPRESSED_RGBA_ASTC_6x5_KHR, 6, 5, 16}, {GL_COMPRESSED_RGBA_ASTC_6x6_KHR, 6, 6, 16}, {GL_COMPRESSED_RGBA_ASTC_8x5_KHR, 8, 5, 16}, {GL_COMPRESSED_RGBA_ASTC_8x6_KHR, 8, 6, 16}, {GL_COMPRESSED_RGBA_ASTC_8x8_KHR, 8, 8, 16}, {GL_COMPRESSED_RGBA_ASTC_10x5_KHR, 10, 5, 16}, {GL_COMPRESSED_RGBA_ASTC_10x6_KHR, 10, 6, 16}, {GL_COMPRESSED_RGBA_ASTC_10x8_KHR, 10, 8, 16}, {GL_COMPRESSED_RGBA_ASTC_10x10_KHR, 10, 10, 16}, {GL_COMPRESSED_RGBA_ASTC_12x10_KHR, 12, 10, 16}, {GL_COMPRESSED_RGBA_ASTC_12x12_KHR, 12, 12, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, 4, 4, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, 5, 4, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, 5, 5, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, 6, 5, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, 6, 6, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, 8, 5, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, 8, 6, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, 8, 8, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, 10, 5, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, 10, 6, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, 10, 8, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, 10, 10, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, 12, 10, 16}, {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, 12, 12, 16}}; static const FormatDesc kPVRTC1Formats[] = {{GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 4, 4, 8}, {GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, 8, 4, 8}, {GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 4, 4, 8}, {GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, 8, 4, 8}}; static const FormatDesc kPVRTC1SRGBFormats[] = { {GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT, 8, 4, 8}, {GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT, 4, 4, 8}, {GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT, 8, 4, 8}, {GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT, 4, 4, 8}}; ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureDXT1Test, PrintToStringParamName, testing::ValuesIn(kDXT1Formats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureDXT3Test, PrintToStringParamName, testing::ValuesIn(kDXT3Formats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureDXT5Test, PrintToStringParamName, testing::ValuesIn(kDXT5Formats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureS3TCSRGBTest, PrintToStringParamName, testing::ValuesIn(kS3TCSRGBFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureRGTCTest, PrintToStringParamName, testing::ValuesIn(kRGTCFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureBPTCTest, PrintToStringParamName, testing::ValuesIn(kBPTCFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureETC1Test, PrintToStringParamName, testing::ValuesIn(kETC1Formats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureETC1SubTest, PrintToStringParamName, testing::ValuesIn(kETC1Formats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureEACR11UTest, PrintToStringParamName, testing::ValuesIn(kEACR11UFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureEACR11STest, PrintToStringParamName, testing::ValuesIn(kEACR11SFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureEACRG11UTest, PrintToStringParamName, testing::ValuesIn(kEACRG11UFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureEACRG11STest, PrintToStringParamName, testing::ValuesIn(kEACRG11SFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureETC2RGB8Test, PrintToStringParamName, testing::ValuesIn(kETC2RGB8Formats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureETC2RGB8SRGBTest, PrintToStringParamName, testing::ValuesIn(kETC2RGB8SRGBFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureETC2RGB8A1Test, PrintToStringParamName, testing::ValuesIn(kETC2RGB8A1Formats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureETC2RGB8A1SRGBTest, PrintToStringParamName, testing::ValuesIn(kETC2RGB8A1SRGBFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureETC2RGBA8Test, PrintToStringParamName, testing::ValuesIn(kETC2RGBA8Formats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureETC2RGBA8SRGBTest, PrintToStringParamName, testing::ValuesIn(kETC2RGBA8SRGBFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureASTCTest, PrintToStringParamName, testing::ValuesIn(kASTCFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureASTCSliced3DTest, PrintToStringParamName, testing::ValuesIn(kASTCFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTextureSamplerASTCSliced3DTest, PrintToStringParamName, testing::ValuesIn(kASTCFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTexturePVRTC1Test, PrintToStringParamName, testing::ValuesIn(kPVRTC1Formats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); ANGLE_INSTANTIATE_TEST_COMBINE_1(CompressedTexturePVRTC1SRGBTest, PrintToStringParamName, testing::ValuesIn(kPVRTC1SRGBFormats), ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3); // clang-format off TEST_P(CompressedTextureDXT1Test, Test) { test(); } TEST_P(CompressedTextureDXT3Test, Test) { test(); } TEST_P(CompressedTextureDXT5Test, Test) { test(); } TEST_P(CompressedTextureS3TCSRGBTest, Test) { test(); } TEST_P(CompressedTextureRGTCTest, Test) { test(); } TEST_P(CompressedTextureBPTCTest, Test) { test(); } TEST_P(CompressedTextureETC1Test, Test) { test(); } TEST_P(CompressedTextureETC1SubTest, Test) { test(); } TEST_P(CompressedTextureEACR11UTest, Test) { test(); } TEST_P(CompressedTextureEACR11STest, Test) { test(); } TEST_P(CompressedTextureEACRG11UTest, Test) { test(); } TEST_P(CompressedTextureEACRG11STest, Test) { test(); } TEST_P(CompressedTextureETC2RGB8Test, Test) { test(); } TEST_P(CompressedTextureETC2RGB8SRGBTest, Test) { test(); } TEST_P(CompressedTextureETC2RGB8A1Test, Test) { test(); } TEST_P(CompressedTextureETC2RGB8A1SRGBTest, Test) { test(); } TEST_P(CompressedTextureETC2RGBA8Test, Test) { test(); } TEST_P(CompressedTextureETC2RGBA8SRGBTest, Test) { test(); } TEST_P(CompressedTextureASTCTest, Test) { test(); } TEST_P(CompressedTextureASTCSliced3DTest, Test) { test(); } // Check that texture sampling works correctly TEST_P(CompressedTextureSamplerASTCSliced3DTest, Test) { testSamplerASTCSliced3D(); } TEST_P(CompressedTexturePVRTC1Test, Test) { test(); } TEST_P(CompressedTexturePVRTC1SRGBTest, Test) { test(); } // clang-format on } // namespace