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