1 //
2 // Copyright 2020 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // Tests of DXT texture mipmap sizes required by WebGL.
7 
8 #include "test_utils/ANGLETest.h"
9 #include "test_utils/gl_raii.h"
10 
11 #include "media/pixel.inc"
12 
13 using namespace angle;
14 
15 std::array<uint8_t, 72> k12x12DXT1Data = {
16     0xe0, 0x03, 0x00, 0x78, 0x13, 0x10, 0x15, 0x00, 0x0f, 0x00, 0xe0, 0x7b, 0x11, 0x10, 0x15,
17     0x00, 0xe0, 0x03, 0x0f, 0x78, 0x44, 0x45, 0x40, 0x55, 0x0f, 0x00, 0xef, 0x03, 0x44, 0x45,
18     0x40, 0x55, 0xe0, 0x03, 0x00, 0x78, 0x13, 0x10, 0x15, 0x00, 0x0f, 0x00, 0xe0, 0x7b, 0x11,
19     0x10, 0x15, 0x00, 0xe0, 0x03, 0x0f, 0x78, 0x44, 0x45, 0x40, 0x55, 0x0f, 0x00, 0xef, 0x03,
20     0x44, 0x45, 0x40, 0x55, 0x0f, 0x00, 0xef, 0x03, 0x44, 0x45, 0x40, 0x55,
21 };
22 
23 class S3TCTextureSizesTest : public ANGLETest
24 {
25   protected:
S3TCTextureSizesTest()26     S3TCTextureSizesTest()
27     {
28         setWindowWidth(512);
29         setWindowHeight(512);
30         setConfigRedBits(8);
31         setConfigGreenBits(8);
32         setConfigBlueBits(8);
33         setConfigAlphaBits(8);
34     }
35 
testSetUp()36     void testSetUp() override
37     {
38         constexpr char kVS[] = R"(precision highp float;
39 attribute vec4 position;
40 varying vec2 texcoord;
41 
42 void main()
43 {
44     gl_Position = position;
45     texcoord = (position.xy * 0.5) + 0.5;
46     texcoord.y = 1.0 - texcoord.y;
47 })";
48 
49         constexpr char kFS[] = R"(precision highp float;
50 uniform sampler2D tex;
51 varying vec2 texcoord;
52 
53 void main()
54 {
55     gl_FragColor = texture2D(tex, texcoord);
56 })";
57 
58         mTextureProgram = CompileProgram(kVS, kFS);
59         if (mTextureProgram == 0)
60         {
61             FAIL() << "shader compilation failed.";
62         }
63 
64         mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
65 
66         ASSERT_GL_NO_ERROR();
67     }
68 
testTearDown()69     void testTearDown() override { glDeleteProgram(mTextureProgram); }
70 
71     GLuint mTextureProgram;
72     GLint mTextureUniformLocation;
73 };
74 
75 // Test DXT1 formats with POT sizes on all mips
TEST_P(S3TCTextureSizesTest,POT)76 TEST_P(S3TCTextureSizesTest, POT)
77 {
78     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
79 
80     GLTexture texture;
81     glBindTexture(GL_TEXTURE_2D, texture);
82     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
83     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
84     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
85     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
86 
87     glUseProgram(mTextureProgram);
88     glUniform1i(mTextureUniformLocation, 0);
89 
90     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, 8, 0, 32,
91                            k12x12DXT1Data.data());
92     drawQuad(mTextureProgram, "position", 0.5f);
93     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor(0, 0, 123, 255));
94 
95     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, 4, 0, 16,
96                            k12x12DXT1Data.data());
97     drawQuad(mTextureProgram, "position", 0.5f);
98     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor(0, 0, 123, 255));
99 
100     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, 4, 0, 16,
101                            k12x12DXT1Data.data());
102     drawQuad(mTextureProgram, "position", 0.5f);
103     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor(0, 0, 123, 255));
104 
105     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, 8,
106                            k12x12DXT1Data.data());
107     drawQuad(mTextureProgram, "position", 0.5f);
108     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor(123, 0, 0, 255));
109 
110     EXPECT_GL_NO_ERROR();
111 }
112 
113 // Test DXT1 formats with NPOT sizes with glTexStorage
TEST_P(S3TCTextureSizesTest,NPOTTexStorage)114 TEST_P(S3TCTextureSizesTest, NPOTTexStorage)
115 {
116     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
117 
118     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
119                        (!IsGLExtensionEnabled("GL_EXT_texture_storage") ||
120                         !IsGLExtensionEnabled("GL_OES_rgb8_rgba8")));
121 
122     GLTexture texture;
123     glBindTexture(GL_TEXTURE_2D, texture);
124     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
125     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
126     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
127     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
128 
129     glUseProgram(mTextureProgram);
130     glUniform1i(mTextureUniformLocation, 0);
131 
132     if (getClientMajorVersion() < 3)
133     {
134         glTexStorage2DEXT(GL_TEXTURE_2D, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 12, 12);
135     }
136     else
137     {
138         glTexStorage2D(GL_TEXTURE_2D, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 12, 12);
139     }
140 
141     struct levelInfo
142     {
143         size_t width;
144         size_t height;
145         size_t size;
146         GLColor expectedColor;
147     };
148     std::array<levelInfo, 4> levels{{
149         {12, 12, 72, GLColor(123, 0, 123, 255)},
150         {6, 6, 32, GLColor(123, 0, 123, 255)},
151         {3, 3, 8, GLColor(123, 0, 0, 255)},
152         {1, 1, 8, GLColor(0, 0, 0, 0)},
153     }};
154 
155     for (size_t i = 0; i < levels.size(); i++)
156     {
157         const levelInfo &level = levels[i];
158         glCompressedTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, level.width, level.height,
159                                   GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, level.size,
160                                   k12x12DXT1Data.data());
161     }
162     EXPECT_GL_NO_ERROR();
163 
164     for (size_t i = 0; i < levels.size(); i++)
165     {
166         const levelInfo &level = levels[i];
167         glViewport(0, 0, level.width, level.height);
168         drawQuad(mTextureProgram, "position", 0.5f);
169         EXPECT_PIXEL_COLOR_EQ(0, 0, level.expectedColor) << " failed on level " << i;
170     }
171 
172     EXPECT_GL_NO_ERROR();
173 }
174 
175 // Test DXT1 formats with NPOT sizes with glTex[Sub]Image
TEST_P(S3TCTextureSizesTest,NPOTTexImage)176 TEST_P(S3TCTextureSizesTest, NPOTTexImage)
177 {
178     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
179 
180     GLTexture texture;
181     glBindTexture(GL_TEXTURE_2D, texture);
182     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
183     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
184     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
185     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
186 
187     glUseProgram(mTextureProgram);
188     glUniform1i(mTextureUniformLocation, 0);
189 
190     struct levelInfo
191     {
192         size_t width;
193         size_t height;
194         size_t size;
195         GLColor expectedColor;
196     };
197     std::array<levelInfo, 4> levels{{
198         {12, 12, 72, GLColor(123, 0, 123, 255)},
199         {6, 6, 32, GLColor(123, 0, 123, 255)},
200         {3, 3, 8, GLColor(123, 0, 0, 255)},
201         {1, 1, 8, GLColor(0, 0, 0, 0)},
202     }};
203 
204     for (size_t i = 0; i < levels.size(); i++)
205     {
206         const levelInfo &level = levels[i];
207         glCompressedTexImage2D(GL_TEXTURE_2D, i, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, level.width,
208                                level.height, 0, level.size, k12x12DXT1Data.data());
209     }
210     EXPECT_GL_NO_ERROR();
211 
212     for (size_t i = 0; i < levels.size(); i++)
213     {
214         const levelInfo &level = levels[i];
215         glViewport(0, 0, level.width, level.height);
216         drawQuad(mTextureProgram, "position", 0.5f);
217         EXPECT_PIXEL_COLOR_EQ(0, 0, level.expectedColor) << " failed on level " << i;
218     }
219 
220     EXPECT_GL_NO_ERROR();
221 }
222 
223 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
224 // tests should be run against.
225 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(S3TCTextureSizesTest);
226