blob: e5de2b4e399b42eef3b07a7840ddf06cb0062d54 [file] [log] [blame]
//
// Copyright 2020 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.
//
// Tests of DXT texture mipmap sizes required by WebGL.
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
#include "media/pixel.inc"
using namespace angle;
std::array<uint8_t, 72> k12x12DXT1Data = {
0xe0, 0x03, 0x00, 0x78, 0x13, 0x10, 0x15, 0x00, 0x0f, 0x00, 0xe0, 0x7b, 0x11, 0x10, 0x15,
0x00, 0xe0, 0x03, 0x0f, 0x78, 0x44, 0x45, 0x40, 0x55, 0x0f, 0x00, 0xef, 0x03, 0x44, 0x45,
0x40, 0x55, 0xe0, 0x03, 0x00, 0x78, 0x13, 0x10, 0x15, 0x00, 0x0f, 0x00, 0xe0, 0x7b, 0x11,
0x10, 0x15, 0x00, 0xe0, 0x03, 0x0f, 0x78, 0x44, 0x45, 0x40, 0x55, 0x0f, 0x00, 0xef, 0x03,
0x44, 0x45, 0x40, 0x55, 0x0f, 0x00, 0xef, 0x03, 0x44, 0x45, 0x40, 0x55,
};
class S3TCTextureSizesTest : public ANGLETest
{
protected:
S3TCTextureSizesTest()
{
setWindowWidth(512);
setWindowHeight(512);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
}
void testSetUp() override
{
constexpr char kVS[] = R"(precision highp float;
attribute vec4 position;
varying vec2 texcoord;
void main()
{
gl_Position = position;
texcoord = (position.xy * 0.5) + 0.5;
texcoord.y = 1.0 - texcoord.y;
})";
constexpr char kFS[] = R"(precision highp float;
uniform sampler2D tex;
varying vec2 texcoord;
void main()
{
gl_FragColor = texture2D(tex, texcoord);
})";
mTextureProgram = CompileProgram(kVS, kFS);
if (mTextureProgram == 0)
{
FAIL() << "shader compilation failed.";
}
mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
ASSERT_GL_NO_ERROR();
}
void testTearDown() override { glDeleteProgram(mTextureProgram); }
GLuint mTextureProgram;
GLint mTextureUniformLocation;
};
// Test DXT1 formats with POT sizes on all mips
TEST_P(S3TCTextureSizesTest, POT)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glUseProgram(mTextureProgram);
glUniform1i(mTextureUniformLocation, 0);
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, 8, 0, 32,
k12x12DXT1Data.data());
drawQuad(mTextureProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor(0, 0, 123, 255));
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, 4, 0, 16,
k12x12DXT1Data.data());
drawQuad(mTextureProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor(0, 0, 123, 255));
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, 4, 0, 16,
k12x12DXT1Data.data());
drawQuad(mTextureProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor(0, 0, 123, 255));
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, 8,
k12x12DXT1Data.data());
drawQuad(mTextureProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor(123, 0, 0, 255));
EXPECT_GL_NO_ERROR();
}
// Test DXT1 formats with NPOT sizes with glTexStorage
TEST_P(S3TCTextureSizesTest, NPOTTexStorage)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
(!IsGLExtensionEnabled("GL_EXT_texture_storage") ||
!IsGLExtensionEnabled("GL_OES_rgb8_rgba8")));
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glUseProgram(mTextureProgram);
glUniform1i(mTextureUniformLocation, 0);
if (getClientMajorVersion() < 3)
{
glTexStorage2DEXT(GL_TEXTURE_2D, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 12, 12);
}
else
{
glTexStorage2D(GL_TEXTURE_2D, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 12, 12);
}
struct levelInfo
{
size_t width;
size_t height;
size_t size;
GLColor expectedColor;
};
std::array<levelInfo, 4> levels{{
{12, 12, 72, GLColor(123, 0, 123, 255)},
{6, 6, 32, GLColor(123, 0, 123, 255)},
{3, 3, 8, GLColor(123, 0, 0, 255)},
{1, 1, 8, GLColor(0, 0, 0, 0)},
}};
for (size_t i = 0; i < levels.size(); i++)
{
const levelInfo &level = levels[i];
glCompressedTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, level.width, level.height,
GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, level.size,
k12x12DXT1Data.data());
}
EXPECT_GL_NO_ERROR();
for (size_t i = 0; i < levels.size(); i++)
{
const levelInfo &level = levels[i];
glViewport(0, 0, level.width, level.height);
drawQuad(mTextureProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, level.expectedColor) << " failed on level " << i;
}
EXPECT_GL_NO_ERROR();
}
// Test DXT1 formats with NPOT sizes with glTex[Sub]Image
TEST_P(S3TCTextureSizesTest, NPOTTexImage)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glUseProgram(mTextureProgram);
glUniform1i(mTextureUniformLocation, 0);
struct levelInfo
{
size_t width;
size_t height;
size_t size;
GLColor expectedColor;
};
std::array<levelInfo, 4> levels{{
{12, 12, 72, GLColor(123, 0, 123, 255)},
{6, 6, 32, GLColor(123, 0, 123, 255)},
{3, 3, 8, GLColor(123, 0, 0, 255)},
{1, 1, 8, GLColor(0, 0, 0, 0)},
}};
for (size_t i = 0; i < levels.size(); i++)
{
const levelInfo &level = levels[i];
glCompressedTexImage2D(GL_TEXTURE_2D, i, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, level.width,
level.height, 0, level.size, k12x12DXT1Data.data());
}
EXPECT_GL_NO_ERROR();
for (size_t i = 0; i < levels.size(); i++)
{
const levelInfo &level = levels[i];
glViewport(0, 0, level.width, level.height);
drawQuad(mTextureProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, level.expectedColor) << " failed on level " << i;
}
EXPECT_GL_NO_ERROR();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(S3TCTextureSizesTest);