xref: /aosp_15_r20/external/angle/src/tests/gl_tests/SwizzleTest.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 
7 #include "test_utils/ANGLETest.h"
8 
9 #include <vector>
10 
11 using namespace angle;
12 
13 namespace
14 {
15 
16 class SwizzleTest : public ANGLETest<>
17 {
18   protected:
SwizzleTest()19     SwizzleTest()
20     {
21         setWindowWidth(128);
22         setWindowHeight(128);
23         setConfigRedBits(8);
24         setConfigGreenBits(8);
25         setConfigBlueBits(8);
26         setConfigAlphaBits(8);
27 
28         constexpr GLenum swizzles[] = {
29             GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_ZERO, GL_ONE,
30         };
31 
32         // Only use every 13th swizzle permutation, use a prime number to make sure the permuations
33         // are somewhat evenly distributed.  Reduces the permuations from 1296 to 100.
34         constexpr size_t swizzleReductionFactor = 13;
35 
36         size_t swizzleCount = 0;
37         for (GLenum r : swizzles)
38         {
39             for (GLenum g : swizzles)
40             {
41                 for (GLenum b : swizzles)
42                 {
43                     for (GLenum a : swizzles)
44                     {
45                         swizzleCount++;
46                         if (swizzleCount % swizzleReductionFactor != 0)
47                         {
48                             continue;
49                         }
50 
51                         swizzlePermutation permutation;
52                         permutation.swizzleRed   = r;
53                         permutation.swizzleGreen = g;
54                         permutation.swizzleBlue  = b;
55                         permutation.swizzleAlpha = a;
56                         mPermutations.push_back(permutation);
57                     }
58                 }
59             }
60         }
61     }
62 
testSetUp()63     void testSetUp() override
64     {
65         constexpr char kVS[] = R"(precision highp float;
66 attribute vec4 position;
67 varying vec2 texcoord;
68 
69 void main()
70 {
71     gl_Position = position;
72     texcoord = (position.xy * 0.5) + 0.5;
73 })";
74 
75         constexpr char kFS[] = R"(precision highp float;
76 uniform sampler2D tex;
77 varying vec2 texcoord;
78 
79 void main()
80 {
81     gl_FragColor = texture2D(tex, texcoord);
82 })";
83 
84         mProgram = CompileProgram(kVS, kFS);
85         ASSERT_NE(0u, mProgram);
86 
87         mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
88         ASSERT_NE(-1, mTextureUniformLocation);
89 
90         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
91         ASSERT_GL_NO_ERROR();
92     }
93 
testTearDown()94     void testTearDown() override
95     {
96         glDeleteProgram(mProgram);
97         glDeleteTextures(1, &mTexture);
98     }
99 
isTextureSwizzleAvailable() const100     bool isTextureSwizzleAvailable() const
101     {
102         // On Metal back-end, texture swizzle is not always supported.
103         return !IsMetal() || IsMetalTextureSwizzleAvailable();
104     }
105 
106     template <typename T>
init2DTexture(GLenum internalFormat,GLenum dataFormat,GLenum dataType,const T * data)107     void init2DTexture(GLenum internalFormat, GLenum dataFormat, GLenum dataType, const T *data)
108     {
109         glGenTextures(1, &mTexture);
110         glBindTexture(GL_TEXTURE_2D, mTexture);
111         glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, dataFormat, dataType, data);
112 
113         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
114         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
115     }
116 
init2DCompressedTexture(GLenum internalFormat,GLsizei width,GLsizei height,GLsizei dataSize,const GLubyte * data)117     void init2DCompressedTexture(GLenum internalFormat,
118                                  GLsizei width,
119                                  GLsizei height,
120                                  GLsizei dataSize,
121                                  const GLubyte *data)
122     {
123         glGenTextures(1, &mTexture);
124         glBindTexture(GL_TEXTURE_2D, mTexture);
125         glCompressedTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, dataSize, data);
126 
127         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
128         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
129     }
130 
getExpectedValue(GLenum swizzle,GLubyte unswizzled[4])131     GLubyte getExpectedValue(GLenum swizzle, GLubyte unswizzled[4])
132     {
133         switch (swizzle)
134         {
135             case GL_RED:
136                 return unswizzled[0];
137             case GL_GREEN:
138                 return unswizzled[1];
139             case GL_BLUE:
140                 return unswizzled[2];
141             case GL_ALPHA:
142                 return unswizzled[3];
143             case GL_ZERO:
144                 return 0;
145             case GL_ONE:
146                 return 255;
147             default:
148                 return 0;
149         }
150     }
151 
runTest2D()152     void runTest2D()
153     {
154         glUseProgram(mProgram);
155         glBindTexture(GL_TEXTURE_2D, mTexture);
156         glUniform1i(mTextureUniformLocation, 0);
157 
158         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
159         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
160         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
161         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
162 
163         glClear(GL_COLOR_BUFFER_BIT);
164         drawQuad(mProgram, "position", 0.5f);
165 
166         GLubyte unswizzled[4];
167         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &unswizzled);
168 
169         ASSERT_GL_NO_ERROR();
170 
171         for (const auto &permutation : mPermutations)
172         {
173             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, permutation.swizzleRed);
174             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, permutation.swizzleGreen);
175             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, permutation.swizzleBlue);
176             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, permutation.swizzleAlpha);
177 
178             glClear(GL_COLOR_BUFFER_BIT);
179             drawQuad(mProgram, "position", 0.5f);
180 
181             EXPECT_PIXEL_EQ(0, 0, getExpectedValue(permutation.swizzleRed, unswizzled),
182                             getExpectedValue(permutation.swizzleGreen, unswizzled),
183                             getExpectedValue(permutation.swizzleBlue, unswizzled),
184                             getExpectedValue(permutation.swizzleAlpha, unswizzled));
185 
186             ASSERT_GL_NO_ERROR();
187         }
188     }
189 
190     GLuint mProgram               = 0;
191     GLint mTextureUniformLocation = 0;
192 
193     GLuint mTexture = 0;
194 
195     struct swizzlePermutation
196     {
197         GLenum swizzleRed;
198         GLenum swizzleGreen;
199         GLenum swizzleBlue;
200         GLenum swizzleAlpha;
201     };
202     std::vector<swizzlePermutation> mPermutations;
203 };
204 
205 class SwizzleIntegerTest : public SwizzleTest
206 {
207   protected:
testSetUp()208     void testSetUp() override
209     {
210         constexpr char kVS[] =
211             "#version 300 es\n"
212             "precision highp float;\n"
213             "in vec4 position;\n"
214             "out vec2 texcoord;\n"
215             "\n"
216             "void main()\n"
217             "{\n"
218             "    gl_Position = position;\n"
219             "    texcoord = (position.xy * 0.5) + 0.5;\n"
220             "}\n";
221 
222         constexpr char kFS[] =
223             "#version 300 es\n"
224             "precision highp float;\n"
225             "precision highp usampler2D;\n"
226             "uniform usampler2D tex;\n"
227             "in vec2 texcoord;\n"
228             "out vec4 my_FragColor;\n"
229             "\n"
230             "void main()\n"
231             "{\n"
232             "    uvec4 s = texture(tex, texcoord);\n"
233             "    if (s[0] == 1u) s[0] = 255u;\n"
234             "    if (s[1] == 1u) s[1] = 255u;\n"
235             "    if (s[2] == 1u) s[2] = 255u;\n"
236             "    if (s[3] == 1u) s[3] = 255u;\n"
237             "    my_FragColor = vec4(s) / 255.0;\n"
238             "}\n";
239 
240         mProgram = CompileProgram(kVS, kFS);
241         ASSERT_NE(0u, mProgram);
242 
243         mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
244         ASSERT_NE(-1, mTextureUniformLocation);
245 
246         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
247         ASSERT_GL_NO_ERROR();
248     }
249 };
250 
TEST_P(SwizzleTest,RGBA8_2D)251 TEST_P(SwizzleTest, RGBA8_2D)
252 {
253     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
254 
255     GLubyte data[] = {1, 64, 128, 200};
256     init2DTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
257     runTest2D();
258 }
259 
TEST_P(SwizzleTest,RGB8_2D)260 TEST_P(SwizzleTest, RGB8_2D)
261 {
262     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
263 
264     GLubyte data[] = {77, 66, 55};
265     init2DTexture(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, data);
266     runTest2D();
267 }
268 
TEST_P(SwizzleTest,RG8_2D)269 TEST_P(SwizzleTest, RG8_2D)
270 {
271     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
272 
273     GLubyte data[] = {11, 99};
274     init2DTexture(GL_RG8, GL_RG, GL_UNSIGNED_BYTE, data);
275     runTest2D();
276 }
277 
TEST_P(SwizzleTest,R8_2D)278 TEST_P(SwizzleTest, R8_2D)
279 {
280     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
281 
282     GLubyte data[] = {2};
283     init2DTexture(GL_R8, GL_RED, GL_UNSIGNED_BYTE, data);
284     runTest2D();
285 }
286 
TEST_P(SwizzleTest,RGB10_A2_2D)287 TEST_P(SwizzleTest, RGB10_A2_2D)
288 {
289     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
290 
291     GLuint data[] = {20u | (40u << 10) | (60u << 20) | (2u << 30)};
292     init2DTexture(GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, data);
293     runTest2D();
294 }
295 
TEST_P(SwizzleTest,RGB10_2D)296 TEST_P(SwizzleTest, RGB10_2D)
297 {
298     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
299     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_texture_type_2_10_10_10_REV"));
300 
301     GLuint data[] = {20u | (40u << 10) | (60u << 20) | (2u << 30)};
302     init2DTexture(GL_RGB, GL_RGB, GL_UNSIGNED_INT_2_10_10_10_REV, data);
303     runTest2D();
304 }
305 
TEST_P(SwizzleTest,RGBA32F_2D)306 TEST_P(SwizzleTest, RGBA32F_2D)
307 {
308     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
309 
310     GLfloat data[] = {0.25f, 0.5f, 0.75f, 0.8f};
311     init2DTexture(GL_RGBA32F, GL_RGBA, GL_FLOAT, data);
312     runTest2D();
313 }
314 
TEST_P(SwizzleTest,RGB32F_2D)315 TEST_P(SwizzleTest, RGB32F_2D)
316 {
317     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
318 
319     GLfloat data[] = {0.1f, 0.2f, 0.3f};
320     init2DTexture(GL_RGB32F, GL_RGB, GL_FLOAT, data);
321     runTest2D();
322 }
323 
TEST_P(SwizzleTest,RG32F_2D)324 TEST_P(SwizzleTest, RG32F_2D)
325 {
326     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
327 
328     GLfloat data[] = {0.9f, 0.1f};
329     init2DTexture(GL_RG32F, GL_RG, GL_FLOAT, data);
330     runTest2D();
331 }
332 
TEST_P(SwizzleTest,R32F_2D)333 TEST_P(SwizzleTest, R32F_2D)
334 {
335     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
336 
337     GLfloat data[] = {0.5f};
338     init2DTexture(GL_R32F, GL_RED, GL_FLOAT, data);
339     runTest2D();
340 }
341 
TEST_P(SwizzleTest,D32F_2D)342 TEST_P(SwizzleTest, D32F_2D)
343 {
344     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
345 
346     GLfloat data[] = {0.5f};
347     init2DTexture(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, data);
348     runTest2D();
349 }
350 
TEST_P(SwizzleTest,D16_2D)351 TEST_P(SwizzleTest, D16_2D)
352 {
353     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
354 
355     GLushort data[] = {0xFF};
356     init2DTexture(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, data);
357     runTest2D();
358 }
359 
TEST_P(SwizzleTest,D24_2D)360 TEST_P(SwizzleTest, D24_2D)
361 {
362     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
363 
364     ANGLE_SKIP_TEST_IF(IsVulkan() && IsAMD() && IsWindows());  // anglebug.com/42262208
365     GLuint data[] = {0xFFFF};
366     init2DTexture(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, data);
367     runTest2D();
368 }
369 
TEST_P(SwizzleTest,L8_2D)370 TEST_P(SwizzleTest, L8_2D)
371 {
372     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
373 
374     GLubyte data[] = {0x77};
375     init2DTexture(GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
376     runTest2D();
377 }
378 
TEST_P(SwizzleTest,A8_2D)379 TEST_P(SwizzleTest, A8_2D)
380 {
381     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
382 
383     GLubyte data[] = {0x55};
384     init2DTexture(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, data);
385     runTest2D();
386 }
387 
TEST_P(SwizzleTest,LA8_2D)388 TEST_P(SwizzleTest, LA8_2D)
389 {
390     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
391 
392     GLubyte data[] = {0x77, 0x66};
393     init2DTexture(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data);
394     runTest2D();
395 }
396 
TEST_P(SwizzleTest,L32F_2D)397 TEST_P(SwizzleTest, L32F_2D)
398 {
399     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
400 
401     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
402 
403     GLfloat data[] = {0.7f};
404     init2DTexture(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT, data);
405     runTest2D();
406 }
407 
TEST_P(SwizzleTest,A32F_2D)408 TEST_P(SwizzleTest, A32F_2D)
409 {
410     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
411 
412     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
413 
414     GLfloat data[] = {
415         0.4f,
416     };
417     init2DTexture(GL_ALPHA, GL_ALPHA, GL_FLOAT, data);
418     runTest2D();
419 }
420 
TEST_P(SwizzleTest,LA32F_2D)421 TEST_P(SwizzleTest, LA32F_2D)
422 {
423     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
424 
425     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
426 
427     GLfloat data[] = {
428         0.5f,
429         0.6f,
430     };
431     init2DTexture(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT, data);
432     runTest2D();
433 }
434 
435 #include "media/pixel.inc"
436 
TEST_P(SwizzleTest,CompressedDXT_2D)437 TEST_P(SwizzleTest, CompressedDXT_2D)
438 {
439     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
440 
441     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
442 
443     init2DCompressedTexture(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width, pixel_0_height,
444                             pixel_0_size, pixel_0_data);
445     runTest2D();
446 }
447 
TEST_P(SwizzleTest,CompressedDXT1_RGB_2D)448 TEST_P(SwizzleTest, CompressedDXT1_RGB_2D)
449 {
450     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
451 
452     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
453 
454     init2DCompressedTexture(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixel_0_width, pixel_0_height,
455                             pixel_0_size, pixel_0_data);
456     runTest2D();
457 }
458 
TEST_P(SwizzleIntegerTest,RGB8UI_2D)459 TEST_P(SwizzleIntegerTest, RGB8UI_2D)
460 {
461     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
462 
463     ANGLE_SKIP_TEST_IF(IsVulkan());  // anglebug.com/42261870 - integer textures
464     GLubyte data[] = {77, 66, 55};
465     init2DTexture(GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, data);
466     runTest2D();
467 }
468 
469 // Test that updating the texture data still generates the correct swizzles
TEST_P(SwizzleTest,SubUpdate)470 TEST_P(SwizzleTest, SubUpdate)
471 {
472     ANGLE_SKIP_TEST_IF(!isTextureSwizzleAvailable());
473 
474     GLColor data(1, 64, 128, 200);
475     init2DTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &data);
476 
477     glUseProgram(mProgram);
478     glBindTexture(GL_TEXTURE_2D, mTexture);
479     glUniform1i(mTextureUniformLocation, 0);
480 
481     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
482     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
483     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
484     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
485 
486     glClear(GL_COLOR_BUFFER_BIT);
487     drawQuad(mProgram, "position", 0.5f);
488 
489     GLColor expectedData(data.R, data.R, data.R, data.R);
490     EXPECT_PIXEL_COLOR_EQ(0, 0, expectedData);
491 
492     GLColor updateData(32, 234, 28, 232);
493     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &updateData);
494 
495     glClear(GL_COLOR_BUFFER_BIT);
496     drawQuad(mProgram, "position", 0.5f);
497 
498     GLColor expectedUpdateData(updateData.R, updateData.R, updateData.R, updateData.R);
499     EXPECT_PIXEL_COLOR_EQ(0, 0, expectedUpdateData);
500 }
501 
502 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SwizzleTest);
503 ANGLE_INSTANTIATE_TEST_ES3_AND(SwizzleTest);
504 
505 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SwizzleIntegerTest);
506 ANGLE_INSTANTIATE_TEST_ES3_AND(SwizzleIntegerTest);
507 
508 }  // namespace
509