blob: d6d9ada8dd564965f1c63f00b4cb31cd9a4e865f [file] [log] [blame]
//
// 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<angle::PlatformParameters, FormatDesc>;
class CompressedTextureFormatsTest : public ANGLETest<CompressedTextureTestParams>
{
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<GLColor> 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<std::string> mExtNames;
const bool mSupportsUpdates;
const bool mSupportsPartialUpdates;
const bool mSupports2DArray;
const bool mSupports3D;
const bool mAlwaysOnES3;
};
template <char const *ext1,
char const *ext2,
bool supports_updates,
bool supports_partial_updates,
bool supports_2d_array,
bool supports_3d,
bool always_on_es3>
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<kDXT1, kEmpty, true, true, true, false, false>;
using CompressedTextureDXT3Test = _Test<kDXT3, kEmpty, true, true, true, false, false>;
using CompressedTextureDXT5Test = _Test<kDXT5, kEmpty, true, true, true, false, false>;
using CompressedTextureS3TCSRGBTest = _Test<kS3TCSRGB, kEmpty, true, true, true, false, false>;
using CompressedTextureRGTCTest = _Test<kRGTC, kEmpty, true, true, true, false, false>;
using CompressedTextureBPTCTest = _Test<kBPTC, kEmpty, true, true, true, true, false>;
using CompressedTextureETC1Test = _Test<kETC1, kEmpty, false, false, false, false, false>;
using CompressedTextureETC1SubTest = _Test<kETC1, kETC1Sub, true, true, true, false, false>;
using CompressedTextureEACR11UTest = _Test<kEACR11U, kEmpty, true, true, true, false, true>;
using CompressedTextureEACR11STest = _Test<kEACR11S, kEmpty, true, true, true, false, true>;
using CompressedTextureEACRG11UTest = _Test<kEACRG11U, kEmpty, true, true, true, false, true>;
using CompressedTextureEACRG11STest = _Test<kEACRG11S, kEmpty, true, true, true, false, true>;
using CompressedTextureETC2RGB8Test = _Test<kETC2RGB8, kEmpty, true, true, true, false, true>;
using CompressedTextureETC2RGB8SRGBTest = _Test<kETC2RGB8SRGB, kEmpty, true, true, true, false, true>;
using CompressedTextureETC2RGB8A1Test = _Test<kETC2RGB8A1, kEmpty, true, true, true, false, true>;
using CompressedTextureETC2RGB8A1SRGBTest = _Test<kETC2RGB8A1SRGB, kEmpty, true, true, true, false, true>;
using CompressedTextureETC2RGBA8Test = _Test<kETC2RGBA8, kEmpty, true, true, true, false, true>;
using CompressedTextureETC2RGBA8SRGBTest = _Test<kETC2RGBA8SRGB, kEmpty, true, true, true, false, true>;
using CompressedTextureASTCTest = _Test<kASTC, kEmpty, true, true, true, false, false>;
using CompressedTextureASTCSliced3DTest = _Test<kASTC, kASTCSliced3D, true, true, true, true, false>;
using CompressedTextureSamplerASTCSliced3DTest = _Test<kASTC, kASTCSliced3D, true, true, true, true, false>;
using CompressedTexturePVRTC1Test = _Test<kPVRTC1, kEmpty, true, false, false, false, false>;
using CompressedTexturePVRTC1SRGBTest = _Test<kPVRTC1, kPVRTCSRGB, true, false, false, false, false>;
// clang-format on
std::string PrintToStringParamName(
const ::testing::TestParamInfo<CompressedTextureTestParams> &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