xref: /aosp_15_r20/external/angle/src/tests/gl_tests/ETCTextureTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2015 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 // ETCTextureTest:
7 //   Tests for ETC lossy decode formats.
8 //
9 
10 #include "test_utils/ANGLETest.h"
11 
12 #include "media/etc2bc_srgb8_alpha8.inc"
13 
14 using namespace angle;
15 
16 namespace
17 {
18 
19 class ETCTextureTest : public ANGLETest<>
20 {
21   protected:
ETCTextureTest()22     ETCTextureTest() : mTexture(0u)
23     {
24         setWindowWidth(128);
25         setWindowHeight(128);
26         setConfigRedBits(8);
27         setConfigGreenBits(8);
28         setConfigBlueBits(8);
29         setConfigAlphaBits(8);
30     }
31 
testSetUp()32     void testSetUp() override
33     {
34         glGenTextures(1, &mTexture);
35         ASSERT_GL_NO_ERROR();
36     }
37 
testTearDown()38     void testTearDown() override { glDeleteTextures(1, &mTexture); }
39 
40     GLuint mTexture;
41 };
42 
43 // Tests a texture with ETC1 lossy decode format
TEST_P(ETCTextureTest,ETC1Validation)44 TEST_P(ETCTextureTest, ETC1Validation)
45 {
46     bool supported = IsGLExtensionEnabled("GL_ANGLE_lossy_etc_decode");
47 
48     glBindTexture(GL_TEXTURE_2D, mTexture);
49 
50     GLubyte pixel[8] = {0x0, 0x0, 0xf8, 0x2, 0x43, 0xff, 0x4, 0x12};
51     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 4, 4, 0,
52                            sizeof(pixel), pixel);
53     if (supported)
54     {
55         EXPECT_GL_NO_ERROR();
56 
57         glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE,
58                                   sizeof(pixel), pixel);
59         EXPECT_GL_NO_ERROR();
60 
61         glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 2, 2, 0,
62                                sizeof(pixel), pixel);
63         EXPECT_GL_NO_ERROR();
64 
65         glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 1, 1, 0,
66                                sizeof(pixel), pixel);
67         EXPECT_GL_NO_ERROR();
68     }
69     else
70     {
71         EXPECT_GL_ERROR(GL_INVALID_ENUM);
72     }
73 }
74 
75 // Tests a texture with ETC2 RGB8 lossy decode format
TEST_P(ETCTextureTest,ETC2RGB8Validation)76 TEST_P(ETCTextureTest, ETC2RGB8Validation)
77 {
78     bool supported = IsGLExtensionEnabled("GL_ANGLE_lossy_etc_decode");
79 
80     glBindTexture(GL_TEXTURE_2D, mTexture);
81 
82     GLubyte pixel[] = {
83         0x00, 0x00, 0xf8, 0x02, 0x43, 0xff, 0x04, 0x12,  // Individual/differential block
84         0x1c, 0x65, 0xc6, 0x62, 0xff, 0xf0, 0xff, 0x00,  // T block
85         0x62, 0xf2, 0xe3, 0x32, 0xff, 0x0f, 0xff, 0x00,  // H block
86         0x71, 0x88, 0xfb, 0xee, 0x87, 0x07, 0x11, 0x1f   // Planar block
87     };
88     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 8, 8, 0,
89                            sizeof(pixel), pixel);
90     if (supported)
91     {
92         EXPECT_GL_NO_ERROR();
93 
94         glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8,
95                                   GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, sizeof(pixel), pixel);
96         EXPECT_GL_NO_ERROR();
97 
98         const GLsizei imageSize = 8;
99 
100         glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 4, 4,
101                                0, imageSize, pixel);
102         EXPECT_GL_NO_ERROR();
103 
104         glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 2, 2,
105                                0, imageSize, pixel);
106         EXPECT_GL_NO_ERROR();
107 
108         glCompressedTexImage2D(GL_TEXTURE_2D, 3, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 1, 1,
109                                0, imageSize, pixel);
110         EXPECT_GL_NO_ERROR();
111     }
112     else
113     {
114         EXPECT_GL_ERROR(GL_INVALID_ENUM);
115     }
116 }
117 
118 // Tests a cube map array texture with compressed ETC2 RGB8 format
TEST_P(ETCTextureTest,ETC2RGB8_CubeMapValidation)119 TEST_P(ETCTextureTest, ETC2RGB8_CubeMapValidation)
120 {
121     ANGLE_SKIP_TEST_IF(!(IsGLExtensionEnabled("GL_EXT_texture_cube_map_array") &&
122                          (getClientMajorVersion() >= 3 && getClientMinorVersion() > 1)));
123 
124     constexpr GLsizei kInvalidTextureWidth  = 8;
125     constexpr GLsizei kInvalidTextureHeight = 8;
126     constexpr GLsizei kCubemapFaceCount     = 6;
127     const std::vector<GLubyte> kInvalidTextureData(
128         kInvalidTextureWidth * kInvalidTextureHeight * kCubemapFaceCount, 0);
129 
130     glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
131     EXPECT_GL_NO_ERROR();
132 
133     glCompressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGB, kInvalidTextureWidth,
134                            kInvalidTextureHeight, kCubemapFaceCount, 0, kInvalidTextureData.size(),
135                            kInvalidTextureData.data());
136     EXPECT_GL_ERROR(GL_INVALID_ENUM);
137 
138     constexpr GLenum kFormat = GL_COMPRESSED_RGB8_ETC2;
139 
140     std::vector<GLubyte> arrayData;
141 
142     constexpr GLuint kWidth       = 4u;
143     constexpr GLuint kHeight      = 4u;
144     constexpr GLuint kDepth       = 6u;
145     constexpr GLuint kPixelBytes  = 8u;
146     constexpr GLuint kBlockWidth  = 4u;
147     constexpr GLuint kBlockHeight = 4u;
148 
149     constexpr GLuint kNumBlocksWide = (kWidth + kBlockWidth - 1u) / kBlockWidth;
150     constexpr GLuint kNumBlocksHigh = (kHeight + kBlockHeight - 1u) / kBlockHeight;
151     constexpr GLuint kBytes         = kNumBlocksWide * kNumBlocksHigh * kPixelBytes * kDepth;
152 
153     arrayData.reserve(kBytes);
154 
155     glCompressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, kFormat, kWidth, kHeight, kDepth, 0,
156                            kBytes, arrayData.data());
157     EXPECT_GL_NO_ERROR();
158 
159     glCompressedTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, kInvalidTextureWidth,
160                               kInvalidTextureHeight, kDepth, GL_RGB, kInvalidTextureData.size(),
161                               kInvalidTextureData.data());
162     glCompressedTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, kInvalidTextureWidth,
163                               kInvalidTextureHeight, kDepth, GL_RGB, kInvalidTextureData.size(),
164                               kInvalidTextureData.data());
165     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
166 }
167 
168 // Tests a texture with ETC2 SRGB8 lossy decode format
TEST_P(ETCTextureTest,ETC2SRGB8Validation)169 TEST_P(ETCTextureTest, ETC2SRGB8Validation)
170 {
171     bool supported = IsGLExtensionEnabled("GL_ANGLE_lossy_etc_decode");
172 
173     glBindTexture(GL_TEXTURE_2D, mTexture);
174 
175     GLubyte pixel[] = {
176         0x00, 0x00, 0xf8, 0x02, 0x43, 0xff, 0x04, 0x12,  // Individual/differential block
177         0x1c, 0x65, 0xc6, 0x62, 0xff, 0xf0, 0xff, 0x00,  // T block
178         0x62, 0xf2, 0xe3, 0x32, 0xff, 0x0f, 0xff, 0x00,  // H block
179         0x71, 0x88, 0xfb, 0xee, 0x87, 0x07, 0x11, 0x1f   // Planar block
180     };
181     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 8, 8, 0,
182                            sizeof(pixel), pixel);
183     if (supported)
184     {
185         EXPECT_GL_NO_ERROR();
186 
187         glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8,
188                                   GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, sizeof(pixel),
189                                   pixel);
190         EXPECT_GL_NO_ERROR();
191 
192         const GLsizei imageSize = 8;
193 
194         glCompressedTexImage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 4, 4,
195                                0, imageSize, pixel);
196         EXPECT_GL_NO_ERROR();
197 
198         glCompressedTexImage2D(GL_TEXTURE_2D, 2, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 2, 2,
199                                0, imageSize, pixel);
200         EXPECT_GL_NO_ERROR();
201 
202         glCompressedTexImage2D(GL_TEXTURE_2D, 3, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 1, 1,
203                                0, imageSize, pixel);
204         EXPECT_GL_NO_ERROR();
205     }
206     else
207     {
208         EXPECT_GL_ERROR(GL_INVALID_ENUM);
209     }
210 }
211 
212 // Tests a texture with ETC2 RGB8 punchthrough A1 lossy decode format
TEST_P(ETCTextureTest,ETC2RGB8A1Validation)213 TEST_P(ETCTextureTest, ETC2RGB8A1Validation)
214 {
215     bool supported = IsGLExtensionEnabled("GL_ANGLE_lossy_etc_decode");
216 
217     glBindTexture(GL_TEXTURE_2D, mTexture);
218 
219     GLubyte pixel[] = {
220         0x80, 0x98, 0x59, 0x02, 0x6e, 0xe7, 0x44, 0x47,  // Individual/differential block
221         0xeb, 0x85, 0x68, 0x30, 0x77, 0x73, 0x44, 0x44,  // T block
222         0xb4, 0x05, 0xab, 0x92, 0xf8, 0x8c, 0x07, 0x73,  // H block
223         0xbb, 0x90, 0x15, 0xba, 0x8a, 0x8c, 0xd5, 0x5f   // Planar block
224     };
225     glCompressedTexImage2D(GL_TEXTURE_2D, 0,
226                            GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 8, 8, 0,
227                            sizeof(pixel), pixel);
228     if (supported)
229     {
230         EXPECT_GL_NO_ERROR();
231 
232         glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8,
233                                   GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
234                                   sizeof(pixel), pixel);
235         EXPECT_GL_NO_ERROR();
236 
237         const GLsizei imageSize = 8;
238 
239         glCompressedTexImage2D(GL_TEXTURE_2D, 1,
240                                GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 4, 4,
241                                0, imageSize, pixel);
242         EXPECT_GL_NO_ERROR();
243 
244         glCompressedTexImage2D(GL_TEXTURE_2D, 2,
245                                GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 2, 2,
246                                0, imageSize, pixel);
247         EXPECT_GL_NO_ERROR();
248 
249         glCompressedTexImage2D(GL_TEXTURE_2D, 3,
250                                GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 1, 1,
251                                0, imageSize, pixel);
252         EXPECT_GL_NO_ERROR();
253     }
254     else
255     {
256         EXPECT_GL_ERROR(GL_INVALID_ENUM);
257     }
258 }
259 
260 // Tests a texture with ETC2 SRGB8 punchthrough A1 lossy decode format
TEST_P(ETCTextureTest,ETC2SRGB8A1Validation)261 TEST_P(ETCTextureTest, ETC2SRGB8A1Validation)
262 {
263     bool supported = IsGLExtensionEnabled("GL_ANGLE_lossy_etc_decode");
264 
265     glBindTexture(GL_TEXTURE_2D, mTexture);
266 
267     GLubyte pixel[] = {
268         0x80, 0x98, 0x59, 0x02, 0x6e, 0xe7, 0x44, 0x47,  // Individual/differential block
269         0xeb, 0x85, 0x68, 0x30, 0x77, 0x73, 0x44, 0x44,  // T block
270         0xb4, 0x05, 0xab, 0x92, 0xf8, 0x8c, 0x07, 0x73,  // H block
271         0xbb, 0x90, 0x15, 0xba, 0x8a, 0x8c, 0xd5, 0x5f   // Planar block
272     };
273     glCompressedTexImage2D(GL_TEXTURE_2D, 0,
274                            GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 8, 8, 0,
275                            sizeof(pixel), pixel);
276     if (supported)
277     {
278         EXPECT_GL_NO_ERROR();
279 
280         glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8,
281                                   GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
282                                   sizeof(pixel), pixel);
283         EXPECT_GL_NO_ERROR();
284 
285         const GLsizei imageSize = 8;
286 
287         glCompressedTexImage2D(GL_TEXTURE_2D, 1,
288                                GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 4,
289                                4, 0, imageSize, pixel);
290         EXPECT_GL_NO_ERROR();
291 
292         glCompressedTexImage2D(GL_TEXTURE_2D, 2,
293                                GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 2,
294                                2, 0, imageSize, pixel);
295         EXPECT_GL_NO_ERROR();
296 
297         glCompressedTexImage2D(GL_TEXTURE_2D, 3,
298                                GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 1,
299                                1, 0, imageSize, pixel);
300         EXPECT_GL_NO_ERROR();
301     }
302     else
303     {
304         EXPECT_GL_ERROR(GL_INVALID_ENUM);
305     }
306 }
307 
308 class ETCToBCTextureTest : public ANGLETest<>
309 {
310   protected:
311     static constexpr int kWidth    = 4;
312     static constexpr int kHeight   = 4;
313     static constexpr int kTexSize  = 4;
314     static constexpr int kAbsError = 6;
315     // the transcoded BC1 data
316     // {0x0000a534, 0x05055555}
317     // then decoded RGBA data are
318     // 0xff000000 0xff000000 0xff000000 0xff000000
319     // 0xff000000 0xff000000 0xff000000 0xff000000
320     // 0xff000000 0xff000000 0xffa5a6a5 0xffa5a6a5
321     // 0xff000000 0xff000000 0xffa5a6a5 0xffa5a6a5
322     static constexpr uint32_t kEtcAllZero[2]        = {0x0, 0x0};
323     static constexpr uint32_t kEtcRGBData[2]        = {0x14050505, 0x00ffff33};
324     static constexpr uint32_t kExpectedRGBColor[16] = {
325         0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
326         0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffa5a6a5, 0xffa5a6a5,
327         0xff000000, 0xff000000, 0xffa5a6a5, 0xffa5a6a5,
328     };
329     // the transcoded RGB data (BC1)
330     // {0x0000a534 0x58585c5f}
331     // the 16 ETC2 decoded alpha value are
332     // 20,  20, 182, 182
333     // 128, 128, 110, 110
334     // 128, 47,   47, 47
335     // 128, 65,   65, 65
336     // max alpha value = 0xb6
337     // min alpha value = 0x14
338     // Result BC4 data are 0xb00914b6, 0xdb3ffb91
339     static constexpr uint32_t kEtcRGBAData[4] = {0xd556975c, 0x088ff048, 0x9e6c6c6c, 0x3f11f1ff};
340     static constexpr uint32_t kExpectedRGBAColor[16] = {
341         0x14373737, 0x14373737, 0xb6000000, 0xb6000000, 0x88a5a6a5, 0x88373737,
342         0x70000000, 0x70000000, 0x88a5a6a5, 0x2b6e6f6e, 0x2b000000, 0x2b000000,
343         0x88a5a6a5, 0x426e6f6e, 0x42000000, 0x42000000,
344     };
345     // Result BC4 data as {0xf6f1836f, 0xc41c5e7c}
346     static constexpr uint32_t kEacR11Signed[2]            = {0xb068efff, 0x00b989e7};
347     static constexpr uint32_t kExpectedR11SignedColor[16] = {
348         0xff000003, 0xff000046, 0xff0000ac, 0xff0000ac, 0xff000025, 0xff000003,
349         0xff000025, 0xff0000ac, 0xff000046, 0xff0000ac, 0xff000003, 0xff000046,
350         0xff000003, 0xff0000ef, 0xff000003, 0xff000046,
351     };
352 
353     // Result BC1 data as {0xa65a7b55, 0xcc3c4f43}
354     static constexpr uint32_t kRgb8a1[2]          = {0x95938c6a, 0x0030e384};
355     static constexpr uint32_t kExpectedRgb8a1[16] = {
356         0x00000000, 0xffab697b, 0xffab697b, 0xffd6cba5, 0x00000000, 0x00000000,
357         0xffab697b, 0xffd6cba5, 0xffab697b, 0x00000000, 0x00000000, 0xffab697b,
358         0xffab697b, 0x00000000, 0xffab697b, 0x00000000,
359     };
360 
361     static constexpr char kVS[] =
362         "#version 300 es\n"
363         "in vec4 position;\n"
364         "void main()\n"
365         "{\n"
366         "    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
367         "}\n";
ETCToBCTextureTest()368     ETCToBCTextureTest() : mEtcTexture(0u)
369     {
370         setWindowWidth(256);
371         setWindowHeight(256);
372         setConfigRedBits(8);
373         setConfigGreenBits(8);
374         setConfigBlueBits(8);
375         setConfigAlphaBits(8);
376     }
377 
testSetUp()378     void testSetUp() override
379     {
380         glGenTextures(1, &mEtcTexture);
381         ASSERT_GL_NO_ERROR();
382     }
383 
testTearDown()384     void testTearDown() override { glDeleteTextures(1, &mEtcTexture); }
385     GLuint mEtcTexture;
386 };
387 
388 // Tests GPU compute transcode ETC2_RGB8 to BC1
TEST_P(ETCToBCTextureTest,ETC2Rgb8UnormToBC1_2D)389 TEST_P(ETCToBCTextureTest, ETC2Rgb8UnormToBC1_2D)
390 {
391     ANGLE_SKIP_TEST_IF(
392         !IsVulkan() || !IsNVIDIA() ||
393         !getEGLWindow()->isFeatureEnabled(Feature::SupportsComputeTranscodeEtcToBc) ||
394         !IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
395     glViewport(0, 0, kWidth, kHeight);
396     glBindTexture(GL_TEXTURE_2D, mEtcTexture);
397     glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_ETC2, kTexSize, kTexSize);
398     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexSize, kTexSize, GL_COMPRESSED_RGB8_ETC2,
399                               sizeof(kEtcRGBData), kEtcRGBData);
400     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
401     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
402     draw2DTexturedQuad(0.5f, 1.0f, false);
403     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(kExpectedRGBColor[0]), kAbsError);
404     EXPECT_PIXEL_COLOR_NEAR(1, 1, GLColor(kExpectedRGBColor[5]), kAbsError);
405     EXPECT_PIXEL_COLOR_NEAR(2, 2, GLColor(kExpectedRGBColor[10]), kAbsError);
406     EXPECT_PIXEL_COLOR_NEAR(3, 3, GLColor(kExpectedRGBColor[15]), kAbsError);
407 }
408 
409 // Tests GPU compute transcode ETC2_RGB8 to BC1 with cube texture type
TEST_P(ETCToBCTextureTest,ETC2Rgb8UnormToBC1_Cube)410 TEST_P(ETCToBCTextureTest, ETC2Rgb8UnormToBC1_Cube)
411 {
412     ANGLE_SKIP_TEST_IF(
413         !IsVulkan() || !IsNVIDIA() ||
414         !getEGLWindow()->isFeatureEnabled(Feature::SupportsComputeTranscodeEtcToBc) ||
415         !IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
416     glViewport(0, 0, kWidth, kHeight);
417     glActiveTexture(GL_TEXTURE0);
418     glBindTexture(GL_TEXTURE_CUBE_MAP, mEtcTexture);
419     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_COMPRESSED_RGB8_ETC2, kTexSize, kTexSize);
420     glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, kTexSize, kTexSize,
421                               GL_COMPRESSED_RGB8_ETC2, sizeof(kEtcAllZero), kEtcAllZero);
422     glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, kTexSize, kTexSize,
423                               GL_COMPRESSED_RGB8_ETC2, sizeof(kEtcAllZero), kEtcAllZero);
424     glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, kTexSize, kTexSize,
425                               GL_COMPRESSED_RGB8_ETC2, sizeof(kEtcRGBData), kEtcRGBData);
426     glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, kTexSize, kTexSize,
427                               GL_COMPRESSED_RGB8_ETC2, sizeof(kEtcAllZero), kEtcAllZero);
428     glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, kTexSize, kTexSize,
429                               GL_COMPRESSED_RGB8_ETC2, sizeof(kEtcAllZero), kEtcAllZero);
430     glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, kTexSize, kTexSize,
431                               GL_COMPRESSED_RGB8_ETC2, sizeof(kEtcAllZero), kEtcAllZero);
432     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
433     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
434     constexpr char kTextureCubeFS[] =
435         "#version 300 es\n"
436         "precision highp float;\n"
437         "uniform highp samplerCube texCube;\n"
438         "uniform vec3 faceCoord;\n"
439         "out vec4 fragColor;\n"
440         "void main()\n"
441         "{\n"
442         "    fragColor = texture(texCube, faceCoord);\n"
443         "}\n";
444     GLuint program = CompileProgram(kVS, kTextureCubeFS);
445     glUseProgram(program);
446     GLint texCubePos = glGetUniformLocation(program, "texCube");
447     glUniform1i(texCubePos, 0);
448     GLint faceCoordpos = glGetUniformLocation(program, "faceCoord");
449     // sample at (2, 2) on y plane.
450     glUniform3f(faceCoordpos, 0.25f, 1.0f, 0.25f);
451     drawQuad(program, "position", 0.5f);
452     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(kExpectedRGBColor[10]), kAbsError);
453 }
454 
455 // Tests GPU compute transcode ETC2_RGB8 to BC1 with 2DArray texture type
TEST_P(ETCToBCTextureTest,ETC2Rgb8UnormToBC1_2DArray)456 TEST_P(ETCToBCTextureTest, ETC2Rgb8UnormToBC1_2DArray)
457 {
458     ANGLE_SKIP_TEST_IF(
459         !IsVulkan() || !IsNVIDIA() ||
460         !getEGLWindow()->isFeatureEnabled(Feature::SupportsComputeTranscodeEtcToBc) ||
461         !IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
462     glViewport(0, 0, kWidth, kHeight);
463     glActiveTexture(GL_TEXTURE0);
464     glBindTexture(GL_TEXTURE_2D_ARRAY, mEtcTexture);
465     static constexpr int kArraySize = 6;
466     uint32_t data[2 * kArraySize]   = {
467         kEtcAllZero[0], kEtcAllZero[1],  // array 0
468         kEtcRGBData[0], kEtcRGBData[1],  // array 1
469         kEtcRGBData[0], kEtcRGBData[1],  // array 2
470         kEtcAllZero[0], kEtcAllZero[1],  // array 3
471         kEtcAllZero[0], kEtcAllZero[1],  // array 4
472         kEtcAllZero[0], kEtcAllZero[1],  // array 5
473     };
474     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_COMPRESSED_RGB8_ETC2, kTexSize, kTexSize, kArraySize);
475     glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kTexSize, kTexSize, kArraySize,
476                               GL_COMPRESSED_RGB8_ETC2, sizeof(data), data);
477     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
478     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
479     constexpr char kTexture2DArrayFS[] =
480         "#version 300 es\n"
481         "precision highp float;\n"
482         "uniform highp sampler2DArray tex2DArray;\n"
483         "uniform vec3 coord;\n"
484         "out vec4 fragColor;\n"
485         "void main()\n"
486         "{\n"
487         "    fragColor = texture(tex2DArray, coord);\n"
488         "}\n";
489     GLuint program = CompileProgram(kVS, kTexture2DArrayFS);
490     glUseProgram(program);
491     GLint texCubePos = glGetUniformLocation(program, "tex2DArray");
492     glUniform1i(texCubePos, 0);
493     GLint faceCoordpos = glGetUniformLocation(program, "coord");
494     // sample at (2, 2) on y plane.
495     glUniform3f(faceCoordpos, 0.625f, 0.625f, 2.0f);
496     drawQuad(program, "position", 0.5f);
497     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(kExpectedRGBColor[10]), kAbsError);
498 }
499 
500 // Tests GPU compute transcode ETC2_RGB8 to BC1 with partial updates
TEST_P(ETCToBCTextureTest,ETC2Rgb8UnormToBC1_partial)501 TEST_P(ETCToBCTextureTest, ETC2Rgb8UnormToBC1_partial)
502 {
503     ANGLE_SKIP_TEST_IF(!IsVulkan() || !IsNVIDIA() ||
504                        getEGLWindow()->isFeatureEnabled(Feature::SupportsComputeTranscodeEtcToBc) ||
505                        !IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
506     glViewport(0, 0, kWidth, kHeight);
507     glBindTexture(GL_TEXTURE_2D, mEtcTexture);
508     glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_ETC2, kTexSize * 3, kTexSize * 3);
509     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexSize, kTexSize, GL_COMPRESSED_RGB8_ETC2,
510                               sizeof(kEtcAllZero), kEtcAllZero);
511     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 2 * kTexSize, 2 * kTexSize, kTexSize, kTexSize,
512                               GL_COMPRESSED_RGB8_ETC2, sizeof(kEtcRGBData), kEtcRGBData);
513     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
514     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
515     constexpr char kFS[] =
516         "#version 300 es\n"
517         "precision highp float;\n"
518         "uniform highp sampler2D tex2D;\n"
519         "uniform vec2 coord;\n"
520         "out vec4 fragColor;\n"
521         "void main()\n"
522         "{\n"
523         "    fragColor = texture(tex2D, coord);\n"
524         "}\n";
525     GLuint program = CompileProgram(kVS, kFS);
526     glUseProgram(program);
527     GLint texCubePos = glGetUniformLocation(program, "tex2D");
528     glUniform1i(texCubePos, 0);
529     GLint faceCoordpos = glGetUniformLocation(program, "coord");
530     // sample at (2, 2) on y plane.
531     glUniform2f(faceCoordpos, 21.0f / 24.0f, 21.0f / 24.0f);
532     drawQuad(program, "position", 0.5f);
533     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(kExpectedRGBColor[10]), kAbsError);
534 }
535 
536 // Tests GPU compute transcode ETC2_RGBA8 to BC3
TEST_P(ETCToBCTextureTest,ETC2Rgba8UnormToBC3)537 TEST_P(ETCToBCTextureTest, ETC2Rgba8UnormToBC3)
538 {
539     ANGLE_SKIP_TEST_IF(
540         !IsVulkan() || !IsNVIDIA() ||
541         !getEGLWindow()->isFeatureEnabled(Feature::SupportsComputeTranscodeEtcToBc) ||
542         !IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc"));
543 
544     glViewport(0, 0, kWidth, kHeight);
545     glBindTexture(GL_TEXTURE_2D, mEtcTexture);
546     glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGBA8_ETC2_EAC, kTexSize, kTexSize);
547 
548     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexSize, kTexSize,
549                               GL_COMPRESSED_RGBA8_ETC2_EAC, sizeof(kEtcRGBAData), kEtcRGBAData);
550     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
551     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
552     draw2DTexturedQuad(0.5f, 1.0f, false);
553     for (int i = 0; i < 4; ++i)
554     {
555         for (int j = 0; j < 4; ++j)
556         {
557             EXPECT_PIXEL_COLOR_NEAR(j, i, GLColor(kExpectedRGBAColor[i * 4 + j]), kAbsError);
558         }
559     }
560 }
561 
562 // Tests GPU compute transcode ETC2_RGBA8 to BC3 texture with lod.
TEST_P(ETCToBCTextureTest,ETC2Rgba8UnormToBC3_Lod)563 TEST_P(ETCToBCTextureTest, ETC2Rgba8UnormToBC3_Lod)
564 {
565     ANGLE_SKIP_TEST_IF(
566         !IsVulkan() || !IsNVIDIA() ||
567         !getEGLWindow()->isFeatureEnabled(Feature::SupportsComputeTranscodeEtcToBc) ||
568         !IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc"));
569 
570     glViewport(0, 0, kWidth, kHeight);
571     glBindTexture(GL_TEXTURE_2D, mEtcTexture);
572     glTexStorage2D(GL_TEXTURE_2D, 3, GL_COMPRESSED_RGBA8_ETC2_EAC, kTexSize, kTexSize);
573 
574     static constexpr uint32_t kAllZero[] = {0, 0, 0, 0};
575     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexSize, kTexSize,
576                               GL_COMPRESSED_RGBA8_ETC2_EAC, sizeof(kAllZero), kAllZero);
577     glCompressedTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kTexSize / 2, kTexSize / 2,
578                               GL_COMPRESSED_RGBA8_ETC2_EAC, sizeof(kAllZero), kAllZero);
579     glCompressedTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, kTexSize / 4, kTexSize / 4,
580                               GL_COMPRESSED_RGBA8_ETC2_EAC, sizeof(kEtcRGBAData), kEtcRGBAData);
581     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
582     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
583     constexpr char kVS[] =
584         "#version 300 es\n"
585         "in vec2 position;\n"
586         "out vec2 texCoord;\n"
587         "void main()\n"
588         "{\n"
589         "    gl_Position = vec4(position, 0, 1);\n"
590         "    texCoord = position * 0.5 + vec2(0.5);\n"
591         "}\n";
592 
593     constexpr char kFS[] =
594         "#version 300 es\n"
595         "precision highp float;\n"
596         "uniform highp sampler2D tex2D;\n"
597         "in vec2 texCoord;\n"
598         "out vec4 fragColor;\n"
599         "void main()\n"
600         "{\n"
601         "    fragColor = textureLod(tex2D, texCoord, 2.0);\n"
602         "}\n";
603     GLuint program = CompileProgram(kVS, kFS);
604     glUseProgram(program);
605     GLint texPos = glGetUniformLocation(program, "tex2D");
606     glUniform1i(texPos, 0);
607     drawQuad(program, "position", 0.5f);
608     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(kExpectedRGBAColor[0]), kAbsError);
609 }
610 
611 // Tests GPU compute transcode ETC2_SRGB8_ALPHA8 to BC3
TEST_P(ETCToBCTextureTest,ETC2SrgbAlpha8UnormToBC3)612 TEST_P(ETCToBCTextureTest, ETC2SrgbAlpha8UnormToBC3)
613 {
614     ANGLE_SKIP_TEST_IF(
615         !IsVulkan() || !IsNVIDIA() ||
616         !getEGLWindow()->isFeatureEnabled(Feature::SupportsComputeTranscodeEtcToBc) ||
617         !IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc_srgb"));
618 
619     glViewport(0, 0, pixel_width, pixel_height);
620     glBindTexture(GL_TEXTURE_2D, mEtcTexture);
621     EXPECT_GL_NO_ERROR();
622     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, pixel_width,
623                            pixel_height, 0, sizeof(etc2bc_srgb8_alpha8), etc2bc_srgb8_alpha8);
624     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
625     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
626     draw2DTexturedQuad(0.5f, 1.0f, false);
627     EXPECT_PIXEL_ALPHA_NEAR(96, 160, 255, kAbsError);
628     EXPECT_PIXEL_ALPHA_NEAR(88, 148, 0, kAbsError);
629 }
630 
631 // Tests GPU compute transcode R11 Signed to BC4
TEST_P(ETCToBCTextureTest,ETC2R11SignedToBC4)632 TEST_P(ETCToBCTextureTest, ETC2R11SignedToBC4)
633 {
634     ANGLE_SKIP_TEST_IF(
635         !IsVulkan() || !IsNVIDIA() ||
636         !getEGLWindow()->isFeatureEnabled(Feature::SupportsComputeTranscodeEtcToBc) ||
637         !IsGLExtensionEnabled("GL_EXT_texture_compression_rgtc"));
638 
639     glViewport(0, 0, kWidth, kHeight);
640     glActiveTexture(GL_TEXTURE0);
641     glBindTexture(GL_TEXTURE_2D, mEtcTexture);
642     glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_SIGNED_R11_EAC, kTexSize, kTexSize);
643 
644     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexSize, kTexSize,
645                               GL_COMPRESSED_SIGNED_R11_EAC, sizeof(kEacR11Signed), kEacR11Signed);
646     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
647     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
648     constexpr char kVS[] =
649         "attribute vec2 position;\n"
650         "varying mediump vec2 texCoord;\n"
651         "void main()\n"
652         "{\n"
653         "    gl_Position = vec4(position, 0, 1);\n"
654         "    texCoord = position * 0.5 + vec2(0.5);\n"
655         "}\n";
656 
657     constexpr char kFS[] =
658         "varying mediump vec2 texCoord;\n"
659         "uniform sampler2D tex;\n"
660         "void main()\n"
661         "{\n"
662         "    gl_FragColor = texture2D(tex, texCoord)/2.0 + vec4(0.5, 0.0, 0.0, 0.5);\n"
663         "}\n";
664     GLuint program = CompileProgram(kVS, kFS);
665     glUseProgram(program);
666     GLint pos = glGetUniformLocation(program, "tex");
667     glUniform1i(pos, 0);
668     drawQuad(program, "position", 0.5f);
669     for (int i = 0; i < 4; ++i)
670     {
671         for (int j = 0; j < 4; ++j)
672         {
673             EXPECT_PIXEL_COLOR_NEAR(j, i, GLColor(kExpectedR11SignedColor[i * 4 + j]), kAbsError);
674         }
675     }
676 }
677 
678 // Tests GPU compute transcode RG11 to BC5
TEST_P(ETCToBCTextureTest,ETC2RG11ToBC5)679 TEST_P(ETCToBCTextureTest, ETC2RG11ToBC5)
680 {
681     ANGLE_SKIP_TEST_IF(
682         !IsVulkan() || !IsNVIDIA() ||
683         !getEGLWindow()->isFeatureEnabled(Feature::SupportsComputeTranscodeEtcToBc) ||
684         !IsGLExtensionEnabled("GL_EXT_texture_compression_rgtc"));
685     glViewport(0, 0, kWidth, kHeight);
686     glBindTexture(GL_TEXTURE_2D, mEtcTexture);
687     uint32_t data[4] = {
688         kEtcRGBAData[0],
689         kEtcRGBAData[1],
690         kEtcRGBAData[0],
691         kEtcRGBAData[1],
692     };
693     glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RG11_EAC, kTexSize, kTexSize);
694 
695     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexSize, kTexSize, GL_COMPRESSED_RG11_EAC,
696                               sizeof(data), data);
697     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
698     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
699     draw2DTexturedQuad(0.5f, 1.0f, false);
700     for (int i = 0; i < 4; ++i)
701     {
702         for (int j = 0; j < 4; ++j)
703         {
704             uint32_t color = (kExpectedRGBAColor[i * 4 + j] & 0xff000000) >> 24;
705             color |= color << 8;
706             color |= 0xff000000;
707             EXPECT_PIXEL_COLOR_NEAR(j, i, GLColor(color), kAbsError);
708         }
709     }
710 }
711 
712 // Tests GPU compute transcode RGB8A1 to BC1_RGBA
TEST_P(ETCToBCTextureTest,ETC2Rgb8a1UnormToBC1)713 TEST_P(ETCToBCTextureTest, ETC2Rgb8a1UnormToBC1)
714 {
715     ANGLE_SKIP_TEST_IF(
716         !IsVulkan() || !IsNVIDIA() ||
717         !getEGLWindow()->isFeatureEnabled(Feature::SupportsComputeTranscodeEtcToBc) ||
718         !IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc"));
719     glViewport(0, 0, kWidth, kHeight);
720     glBindTexture(GL_TEXTURE_2D, mEtcTexture);
721     glTexStorage2D(GL_TEXTURE_2D, 1, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, kTexSize,
722                    kTexSize);
723     glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexSize, kTexSize,
724                               GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, sizeof(kRgb8a1),
725                               kRgb8a1);
726     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
727     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
728     draw2DTexturedQuad(0.5f, 1.0f, false);
729     for (int i = 0; i < 4; ++i)
730     {
731         for (int j = 0; j < 4; ++j)
732         {
733             EXPECT_PIXEL_COLOR_NEAR(j, i, GLColor(kExpectedRgb8a1[i * 4 + j]), kAbsError);
734         }
735     }
736 }
737 
738 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ETCTextureTest);
739 ANGLE_INSTANTIATE_TEST_ES3_AND(ETCToBCTextureTest,
740                                ES3_VULKAN().enable(Feature::SupportsComputeTranscodeEtcToBc));
741 }  // anonymous namespace
742