blob: 72c3097b92293c78ad3696fad31743956cfcf5d0 [file] [log] [blame] [edit]
//
// Copyright 2024 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.
//
// TextureFixedRateCompressionTest: Tests for GL_EXT_texture_storage_compression
#ifdef UNSAFE_BUFFERS_BUILD
# pragma allow_unsafe_buffers
#endif
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
namespace angle
{
static constexpr GLint kDefaultAttribList[3][3] = {
{GL_NONE, GL_NONE, GL_NONE},
{GL_SURFACE_COMPRESSION_EXT, GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT, GL_NONE},
{GL_SURFACE_COMPRESSION_EXT, GL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT, GL_NONE},
};
// Return its name by value for easy printing
static const char *Name(int value)
{
#define NAME(ERR) \
case ERR: \
return #ERR;
switch (value)
{
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT)
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT)
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_1BPC_EXT)
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_2BPC_EXT)
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_3BPC_EXT)
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_4BPC_EXT)
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_5BPC_EXT)
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_6BPC_EXT)
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_7BPC_EXT)
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_8BPC_EXT)
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_9BPC_EXT)
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_10BPC_EXT)
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_11BPC_EXT)
NAME(GL_SURFACE_COMPRESSION_FIXED_RATE_12BPC_EXT)
}
return "UNKNOW";
#undef NAME
}
class TextureFixedRateCompressionTest : public ANGLETest<>
{
protected:
void invalidTestHelper(const GLint *attribs);
void basicTestHelper(const GLint *attribs);
void RenderToTexture(const GLenum internalFormat, const GLint *attribs);
};
void TextureFixedRateCompressionTest::invalidTestHelper(const GLint *attribs)
{
GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex);
ASSERT_GL_NO_ERROR();
glTexStorageAttribs2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16, attribs);
ASSERT_GL_NO_ERROR();
/* Query compression rate */
GLint compressRate = GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT;
glGetTexParameteriv(GL_TEXTURE_2D, GL_SURFACE_COMPRESSION_EXT, &compressRate);
ASSERT_GL_NO_ERROR();
glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
if (nullptr == attribs)
{
/* Default attrib which is non-compressed formats will return GL_NO_ERROR. */
ASSERT_GL_NO_ERROR();
}
else if (compressRate == GL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT ||
(compressRate >= GL_SURFACE_COMPRESSION_FIXED_RATE_1BPC_EXT &&
compressRate <= GL_SURFACE_COMPRESSION_FIXED_RATE_12BPC_EXT))
{
/* Compressed texture is not supported in glBindImageTexture. */
ASSERT_GL_ERROR(GL_INVALID_VALUE);
}
else if (attribs[1] == GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT || attribs[0] == GL_NONE)
{
/* Default attrib which is non-compressed formats will return GL_NO_ERROR. */
ASSERT_GL_NO_ERROR();
}
}
void TextureFixedRateCompressionTest::basicTestHelper(const GLint *attribs)
{
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
ASSERT_GL_NO_ERROR();
glTexStorageAttribs2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16, attribs);
ASSERT_GL_NO_ERROR();
/* Query and check the compression rate */
GLint compressRate;
glGetTexParameteriv(GL_TEXTURE_2D, GL_SURFACE_COMPRESSION_EXT, &compressRate);
ASSERT_GL_NO_ERROR();
if (nullptr != attribs && compressRate != GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT &&
attribs[1] != GL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT)
{
EXPECT_EQ(compressRate, attribs[1]);
}
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
ASSERT_GL_NO_ERROR();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
ASSERT_GL_NO_ERROR();
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0);
EXPECT_PIXEL_RECT_EQ(0, 0, 16, 16, GLColor::red);
ASSERT_GL_NO_ERROR();
}
// Invalid attrib list, GL_INVALID_VALUE is generated.
TEST_P(TextureFixedRateCompressionTest, Invalidate)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage_compression"));
constexpr GLint kAttribListInvalid[3] = {GL_SURFACE_COMPRESSION_EXT, GL_SURFACE_COMPRESSION_EXT,
GL_NONE};
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
ASSERT_GL_NO_ERROR();
glTexStorageAttribs2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16, kAttribListInvalid);
ASSERT_GL_ERROR(GL_INVALID_VALUE);
for (const GLint *attribs : kDefaultAttribList)
{
invalidTestHelper(attribs);
}
invalidTestHelper(nullptr);
}
// Test basic usage of glTexStorageAttribs2DEXT
TEST_P(TextureFixedRateCompressionTest, TexStorageAttribs2DEXT)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage_compression"));
for (const GLint *attribs : kDefaultAttribList)
{
basicTestHelper(attribs);
}
}
void TextureFixedRateCompressionTest::RenderToTexture(const GLenum internalFormat,
const GLint *attribs)
{
GLint compressRate = 0;
ASSERT(attribs != nullptr);
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
ASSERT_GL_NO_ERROR();
glTexStorageAttribs2DEXT(GL_TEXTURE_2D, 1, internalFormat, 16, 16, attribs);
ASSERT_GL_NO_ERROR();
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
ASSERT_GL_NO_ERROR();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
ASSERT_GL_NO_ERROR();
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
// Query and check the compression rate
glGetTexParameteriv(GL_TEXTURE_2D, GL_SURFACE_COMPRESSION_EXT, &compressRate);
ASSERT_GL_NO_ERROR();
ASSERT_EQ(compressRate, attribs[1])
<< "Compression rate of original texture: " << Name(compressRate);
ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0);
EXPECT_PIXEL_RECT_EQ(0, 0, 16, 16, GLColor::red);
ASSERT_GL_NO_ERROR();
// Query and check the compression rate after render
glGetTexParameteriv(GL_TEXTURE_2D, GL_SURFACE_COMPRESSION_EXT, &compressRate);
ASSERT_GL_NO_ERROR();
ASSERT_EQ(compressRate, attribs[1])
<< "Compression rate of texture after render: " << Name(compressRate);
}
// Test render to texture with fixed compression
TEST_P(TextureFixedRateCompressionTest, RenderToTexture)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage_compression"));
static GLint attribList[] = {GL_SURFACE_COMPRESSION_EXT,
GL_SURFACE_COMPRESSION_FIXED_RATE_1BPC_EXT, GL_NONE};
GLint numRates = 0;
constexpr GLenum internalFormats[] = {GL_RGBA4, GL_R8, GL_RG8, GL_RGB8, GL_RGBA8};
for (GLenum internalFormat : internalFormats)
{
// Test attrib list generated from internal format query.
glGetInternalformativ(GL_TEXTURE_2D, internalFormat,
GL_NUM_SURFACE_COMPRESSION_FIXED_RATES_EXT, 1, &numRates);
ASSERT_GL_NO_ERROR();
if (numRates > 0)
{
std::vector<GLint> rates(numRates);
glGetInternalformativ(GL_TEXTURE_2D, internalFormat, GL_SURFACE_COMPRESSION_EXT,
numRates, rates.data());
ASSERT_GL_NO_ERROR();
for (int i = 0; i < numRates; ++i)
{
attribList[1] = rates[i];
RenderToTexture(internalFormat, attribList);
}
}
}
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TextureFixedRateCompressionTest);
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST_ES31_AND(TextureFixedRateCompressionTest);
} // namespace angle