• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
100     template <typename T>
init2DTexture(GLenum internalFormat,GLenum dataFormat,GLenum dataType,const T * data)101     void init2DTexture(GLenum internalFormat, GLenum dataFormat, GLenum dataType, const T *data)
102     {
103         glGenTextures(1, &mTexture);
104         glBindTexture(GL_TEXTURE_2D, mTexture);
105         glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, dataFormat, dataType, data);
106 
107         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
108         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
109     }
110 
init2DCompressedTexture(GLenum internalFormat,GLsizei width,GLsizei height,GLsizei dataSize,const GLubyte * data)111     void init2DCompressedTexture(GLenum internalFormat,
112                                  GLsizei width,
113                                  GLsizei height,
114                                  GLsizei dataSize,
115                                  const GLubyte *data)
116     {
117         glGenTextures(1, &mTexture);
118         glBindTexture(GL_TEXTURE_2D, mTexture);
119         glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, width, height, 0,
120                                dataSize, data);
121 
122         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
123         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
124     }
125 
getExpectedValue(GLenum swizzle,GLubyte unswizzled[4])126     GLubyte getExpectedValue(GLenum swizzle, GLubyte unswizzled[4])
127     {
128         switch (swizzle)
129         {
130             case GL_RED:
131                 return unswizzled[0];
132             case GL_GREEN:
133                 return unswizzled[1];
134             case GL_BLUE:
135                 return unswizzled[2];
136             case GL_ALPHA:
137                 return unswizzled[3];
138             case GL_ZERO:
139                 return 0;
140             case GL_ONE:
141                 return 255;
142             default:
143                 return 0;
144         }
145     }
146 
runTest2D()147     void runTest2D()
148     {
149         glUseProgram(mProgram);
150         glBindTexture(GL_TEXTURE_2D, mTexture);
151         glUniform1i(mTextureUniformLocation, 0);
152 
153         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
154         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
155         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
156         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
157 
158         glClear(GL_COLOR_BUFFER_BIT);
159         drawQuad(mProgram, "position", 0.5f);
160 
161         GLubyte unswizzled[4];
162         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &unswizzled);
163 
164         ASSERT_GL_NO_ERROR();
165 
166         for (const auto &permutation : mPermutations)
167         {
168             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, permutation.swizzleRed);
169             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, permutation.swizzleGreen);
170             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, permutation.swizzleBlue);
171             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, permutation.swizzleAlpha);
172 
173             glClear(GL_COLOR_BUFFER_BIT);
174             drawQuad(mProgram, "position", 0.5f);
175 
176             EXPECT_PIXEL_EQ(0, 0, getExpectedValue(permutation.swizzleRed, unswizzled),
177                             getExpectedValue(permutation.swizzleGreen, unswizzled),
178                             getExpectedValue(permutation.swizzleBlue, unswizzled),
179                             getExpectedValue(permutation.swizzleAlpha, unswizzled));
180 
181             ASSERT_GL_NO_ERROR();
182         }
183     }
184 
185     GLuint mProgram;
186     GLint mTextureUniformLocation;
187 
188     GLuint mTexture;
189 
190     struct swizzlePermutation
191     {
192         GLenum swizzleRed;
193         GLenum swizzleGreen;
194         GLenum swizzleBlue;
195         GLenum swizzleAlpha;
196     };
197     std::vector<swizzlePermutation> mPermutations;
198 };
199 
200 class SwizzleIntegerTest : public SwizzleTest
201 {
202   protected:
testSetUp()203     void testSetUp() override
204     {
205         constexpr char kVS[] =
206             "#version 300 es\n"
207             "precision highp float;\n"
208             "in vec4 position;\n"
209             "out vec2 texcoord;\n"
210             "\n"
211             "void main()\n"
212             "{\n"
213             "    gl_Position = position;\n"
214             "    texcoord = (position.xy * 0.5) + 0.5;\n"
215             "}\n";
216 
217         constexpr char kFS[] =
218             "#version 300 es\n"
219             "precision highp float;\n"
220             "precision highp usampler2D;\n"
221             "uniform usampler2D tex;\n"
222             "in vec2 texcoord;\n"
223             "out vec4 my_FragColor;\n"
224             "\n"
225             "void main()\n"
226             "{\n"
227             "    uvec4 s = texture(tex, texcoord);\n"
228             "    if (s[0] == 1u) s[0] = 255u;\n"
229             "    if (s[1] == 1u) s[1] = 255u;\n"
230             "    if (s[2] == 1u) s[2] = 255u;\n"
231             "    if (s[3] == 1u) s[3] = 255u;\n"
232             "    my_FragColor = vec4(s) / 255.0;\n"
233             "}\n";
234 
235         mProgram = CompileProgram(kVS, kFS);
236         ASSERT_NE(0u, mProgram);
237 
238         mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
239         ASSERT_NE(-1, mTextureUniformLocation);
240 
241         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
242         ASSERT_GL_NO_ERROR();
243     }
244 };
245 
TEST_P(SwizzleTest,RGBA8_2D)246 TEST_P(SwizzleTest, RGBA8_2D)
247 {
248     GLubyte data[] = {1, 64, 128, 200};
249     init2DTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
250     runTest2D();
251 }
252 
TEST_P(SwizzleTest,RGB8_2D)253 TEST_P(SwizzleTest, RGB8_2D)
254 {
255     GLubyte data[] = {77, 66, 55};
256     init2DTexture(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, data);
257     runTest2D();
258 }
259 
TEST_P(SwizzleTest,RG8_2D)260 TEST_P(SwizzleTest, RG8_2D)
261 {
262     GLubyte data[] = {11, 99};
263     init2DTexture(GL_RG8, GL_RG, GL_UNSIGNED_BYTE, data);
264     runTest2D();
265 }
266 
TEST_P(SwizzleTest,R8_2D)267 TEST_P(SwizzleTest, R8_2D)
268 {
269     GLubyte data[] = {2};
270     init2DTexture(GL_R8, GL_RED, GL_UNSIGNED_BYTE, data);
271     runTest2D();
272 }
273 
TEST_P(SwizzleTest,RGB10_A2_2D)274 TEST_P(SwizzleTest, RGB10_A2_2D)
275 {
276     GLuint data[] = {20u | (40u << 10) | (60u << 20) | (2u << 30)};
277     init2DTexture(GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, data);
278     runTest2D();
279 }
280 
TEST_P(SwizzleTest,RGBA32F_2D)281 TEST_P(SwizzleTest, RGBA32F_2D)
282 {
283     GLfloat data[] = {0.25f, 0.5f, 0.75f, 0.8f};
284     init2DTexture(GL_RGBA32F, GL_RGBA, GL_FLOAT, data);
285     runTest2D();
286 }
287 
TEST_P(SwizzleTest,RGB32F_2D)288 TEST_P(SwizzleTest, RGB32F_2D)
289 {
290     ANGLE_SKIP_TEST_IF(IsVulkan());  // anglebug.com/2898 - float textures
291     GLfloat data[] = {0.1f, 0.2f, 0.3f};
292     init2DTexture(GL_RGB32F, GL_RGB, GL_FLOAT, data);
293     runTest2D();
294 }
295 
TEST_P(SwizzleTest,RG32F_2D)296 TEST_P(SwizzleTest, RG32F_2D)
297 {
298     GLfloat data[] = {0.9f, 0.1f};
299     init2DTexture(GL_RG32F, GL_RG, GL_FLOAT, data);
300     runTest2D();
301 }
302 
TEST_P(SwizzleTest,R32F_2D)303 TEST_P(SwizzleTest, R32F_2D)
304 {
305     GLfloat data[] = {0.5f};
306     init2DTexture(GL_R32F, GL_RED, GL_FLOAT, data);
307     runTest2D();
308 }
309 
TEST_P(SwizzleTest,D32F_2D)310 TEST_P(SwizzleTest, D32F_2D)
311 {
312     GLfloat data[] = {0.5f};
313     init2DTexture(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, data);
314     runTest2D();
315 }
316 
TEST_P(SwizzleTest,D16_2D)317 TEST_P(SwizzleTest, D16_2D)
318 {
319     GLushort data[] = {0xFF};
320     init2DTexture(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, data);
321     runTest2D();
322 }
323 
TEST_P(SwizzleTest,D24_2D)324 TEST_P(SwizzleTest, D24_2D)
325 {
326     ANGLE_SKIP_TEST_IF(IsVulkan() && IsAMD() && IsWindows());  // anglebug.com/3545
327     GLuint data[] = {0xFFFF};
328     init2DTexture(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, data);
329     runTest2D();
330 }
331 
TEST_P(SwizzleTest,L8_2D)332 TEST_P(SwizzleTest, L8_2D)
333 {
334     GLubyte data[] = {0x77};
335     init2DTexture(GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
336     runTest2D();
337 }
338 
TEST_P(SwizzleTest,A8_2D)339 TEST_P(SwizzleTest, A8_2D)
340 {
341     GLubyte data[] = {0x55};
342     init2DTexture(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, data);
343     runTest2D();
344 }
345 
TEST_P(SwizzleTest,LA8_2D)346 TEST_P(SwizzleTest, LA8_2D)
347 {
348     GLubyte data[] = {0x77, 0x66};
349     init2DTexture(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data);
350     runTest2D();
351 }
352 
TEST_P(SwizzleTest,L32F_2D)353 TEST_P(SwizzleTest, L32F_2D)
354 {
355     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
356 
357     GLfloat data[] = {0.7f};
358     init2DTexture(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT, data);
359     runTest2D();
360 }
361 
TEST_P(SwizzleTest,A32F_2D)362 TEST_P(SwizzleTest, A32F_2D)
363 {
364     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
365 
366     GLfloat data[] = {
367         0.4f,
368     };
369     init2DTexture(GL_ALPHA, GL_ALPHA, GL_FLOAT, data);
370     runTest2D();
371 }
372 
TEST_P(SwizzleTest,LA32F_2D)373 TEST_P(SwizzleTest, LA32F_2D)
374 {
375     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_float"));
376 
377     GLfloat data[] = {
378         0.5f,
379         0.6f,
380     };
381     init2DTexture(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT, data);
382     runTest2D();
383 }
384 
385 #include "media/pixel.inc"
386 
TEST_P(SwizzleTest,CompressedDXT_2D)387 TEST_P(SwizzleTest, CompressedDXT_2D)
388 {
389     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
390 
391     init2DCompressedTexture(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width, pixel_0_height,
392                             pixel_0_size, pixel_0_data);
393     runTest2D();
394 }
395 
TEST_P(SwizzleIntegerTest,RGB8UI_2D)396 TEST_P(SwizzleIntegerTest, RGB8UI_2D)
397 {
398     ANGLE_SKIP_TEST_IF(IsVulkan());  // anglebug.com/3196 - integer textures
399     GLubyte data[] = {77, 66, 55};
400     init2DTexture(GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, data);
401     runTest2D();
402 }
403 
404 // Test that updating the texture data still generates the correct swizzles
TEST_P(SwizzleTest,SubUpdate)405 TEST_P(SwizzleTest, SubUpdate)
406 {
407     GLColor data(1, 64, 128, 200);
408     init2DTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &data);
409 
410     glUseProgram(mProgram);
411     glBindTexture(GL_TEXTURE_2D, mTexture);
412     glUniform1i(mTextureUniformLocation, 0);
413 
414     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
415     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
416     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
417     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
418 
419     glClear(GL_COLOR_BUFFER_BIT);
420     drawQuad(mProgram, "position", 0.5f);
421 
422     GLColor expectedData(data.R, data.R, data.R, data.R);
423     EXPECT_PIXEL_COLOR_EQ(0, 0, expectedData);
424 
425     GLColor updateData(32, 234, 28, 232);
426     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &updateData);
427 
428     glClear(GL_COLOR_BUFFER_BIT);
429     drawQuad(mProgram, "position", 0.5f);
430 
431     GLColor expectedUpdateData(updateData.R, updateData.R, updateData.R, updateData.R);
432     EXPECT_PIXEL_COLOR_EQ(0, 0, expectedUpdateData);
433 }
434 
435 ANGLE_INSTANTIATE_TEST_ES3(SwizzleTest);
436 ANGLE_INSTANTIATE_TEST_ES3(SwizzleIntegerTest);
437 
438 }  // namespace
439