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         GLenum swizzles[] =
29         {
30             GL_RED,
31             GL_GREEN,
32             GL_BLUE,
33             GL_ALPHA,
34             GL_ZERO,
35             GL_ONE,
36         };
37 
38         for (int r = 0; r < 6; r++)
39         {
40             for (int g = 0; g < 6; g++)
41             {
42                 for (int b = 0; b < 6; b++)
43                 {
44                     for (int a = 0; a < 6; a++)
45                     {
46                         swizzlePermutation permutation;
47                         permutation.swizzleRed = swizzles[r];
48                         permutation.swizzleGreen = swizzles[g];
49                         permutation.swizzleBlue = swizzles[b];
50                         permutation.swizzleAlpha = swizzles[a];
51                         mPermutations.push_back(permutation);
52                     }
53                 }
54             }
55         }
56     }
57 
SetUp()58     void SetUp() override
59     {
60         ANGLETest::SetUp();
61 
62         const std::string vertexShaderSource = SHADER_SOURCE
63         (
64             precision highp float;
65             attribute vec4 position;
66             varying vec2 texcoord;
67 
68             void main()
69             {
70                 gl_Position = position;
71                 texcoord = (position.xy * 0.5) + 0.5;
72             }
73         );
74 
75         const std::string fragmentShaderSource = SHADER_SOURCE
76         (
77             precision highp float;
78             uniform sampler2D tex;
79             varying vec2 texcoord;
80 
81             void main()
82             {
83                 gl_FragColor = texture2D(tex, texcoord);
84             }
85         );
86 
87         mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
88         ASSERT_NE(0u, mProgram);
89 
90         mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
91         ASSERT_NE(-1, mTextureUniformLocation);
92 
93         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
94         ASSERT_GL_NO_ERROR();
95     }
96 
TearDown()97     void TearDown() override
98     {
99         glDeleteProgram(mProgram);
100         glDeleteTextures(1, &mTexture);
101 
102         ANGLETest::TearDown();
103     }
104 
105     template <typename T>
init2DTexture(GLenum internalFormat,GLenum dataFormat,GLenum dataType,const T * data)106     void init2DTexture(GLenum internalFormat, GLenum dataFormat, GLenum dataType, const T* data)
107     {
108         glGenTextures(1, &mTexture);
109         glBindTexture(GL_TEXTURE_2D, mTexture);
110         glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, dataFormat, dataType, data);
111 
112         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
113         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
114     }
115 
init2DCompressedTexture(GLenum internalFormat,GLsizei width,GLsizei height,GLsizei dataSize,const GLubyte * data)116     void init2DCompressedTexture(GLenum internalFormat, GLsizei width, GLsizei height, GLsizei dataSize, const GLubyte* data)
117     {
118         glGenTextures(1, &mTexture);
119         glBindTexture(GL_TEXTURE_2D, mTexture);
120         glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, width, height, 0, 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:   return unswizzled[0];
131           case GL_GREEN: return unswizzled[1];
132           case GL_BLUE:  return unswizzled[2];
133           case GL_ALPHA: return unswizzled[3];
134           case GL_ZERO:  return 0;
135           case GL_ONE:   return 255;
136           default:       return 0;
137         }
138     }
139 
runTest2D()140     void runTest2D()
141     {
142         // TODO(jmadill): Figure out why this fails on Intel.
143         if (IsIntel() && GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
144         {
145             std::cout << "Test skipped on Intel." << std::endl;
146             return;
147         }
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 (size_t i = 0; i < mPermutations.size(); i++)
167         {
168             const swizzlePermutation& permutation = mPermutations[i];
169 
170             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, permutation.swizzleRed);
171             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, permutation.swizzleGreen);
172             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, permutation.swizzleBlue);
173             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, permutation.swizzleAlpha);
174 
175             glClear(GL_COLOR_BUFFER_BIT);
176             drawQuad(mProgram, "position", 0.5f);
177 
178             EXPECT_PIXEL_EQ(0, 0,
179                             getExpectedValue(permutation.swizzleRed, unswizzled),
180                             getExpectedValue(permutation.swizzleGreen, unswizzled),
181                             getExpectedValue(permutation.swizzleBlue, unswizzled),
182                             getExpectedValue(permutation.swizzleAlpha, unswizzled));
183 
184             ASSERT_GL_NO_ERROR();
185         }
186     }
187 
188     GLuint mProgram;
189     GLint mTextureUniformLocation;
190 
191     GLuint mTexture;
192 
193     struct swizzlePermutation
194     {
195         GLenum swizzleRed;
196         GLenum swizzleGreen;
197         GLenum swizzleBlue;
198         GLenum swizzleAlpha;
199     };
200     std::vector<swizzlePermutation> mPermutations;
201 };
202 
203 class SwizzleIntegerTest : public SwizzleTest
204 {
205   protected:
SetUp()206     void SetUp() override
207     {
208         ANGLETest::SetUp();
209 
210         const std::string vertexShaderSource =
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         const std::string fragmentShaderSource =
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(vertexShaderSource, fragmentShaderSource);
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     GLubyte data[] = { 1, 64, 128, 200 };
254     init2DTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
255     runTest2D();
256 }
257 
TEST_P(SwizzleTest,RGB8_2D)258 TEST_P(SwizzleTest, RGB8_2D)
259 {
260     GLubyte data[] = { 77, 66, 55 };
261     init2DTexture(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, data);
262     runTest2D();
263 }
264 
TEST_P(SwizzleTest,RG8_2D)265 TEST_P(SwizzleTest, RG8_2D)
266 {
267     GLubyte data[] = { 11, 99 };
268     init2DTexture(GL_RG8, GL_RG, GL_UNSIGNED_BYTE, data);
269     runTest2D();
270 }
271 
TEST_P(SwizzleTest,R8_2D)272 TEST_P(SwizzleTest, R8_2D)
273 {
274     GLubyte data[] = { 2 };
275     init2DTexture(GL_R8, GL_RED, GL_UNSIGNED_BYTE, data);
276     runTest2D();
277 }
278 
TEST_P(SwizzleTest,RGB10_A2_2D)279 TEST_P(SwizzleTest, RGB10_A2_2D)
280 {
281     GLuint data[] = {20u | (40u << 10) | (60u << 20) | (2u << 30)};
282     init2DTexture(GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, data);
283     runTest2D();
284 }
285 
TEST_P(SwizzleTest,RGBA32F_2D)286 TEST_P(SwizzleTest, RGBA32F_2D)
287 {
288     GLfloat data[] = { 0.25f, 0.5f, 0.75f, 0.8f };
289     init2DTexture(GL_RGBA32F, GL_RGBA, GL_FLOAT, data);
290     runTest2D();
291 }
292 
TEST_P(SwizzleTest,RGB32F_2D)293 TEST_P(SwizzleTest, RGB32F_2D)
294 {
295     GLfloat data[] = { 0.1f, 0.2f, 0.3f };
296     init2DTexture(GL_RGB32F, GL_RGB, GL_FLOAT, data);
297     runTest2D();
298 }
299 
TEST_P(SwizzleTest,RG32F_2D)300 TEST_P(SwizzleTest, RG32F_2D)
301 {
302     GLfloat data[] = { 0.9f, 0.1f  };
303     init2DTexture(GL_RG32F, GL_RG, GL_FLOAT, data);
304     runTest2D();
305 }
306 
TEST_P(SwizzleTest,R32F_2D)307 TEST_P(SwizzleTest, R32F_2D)
308 {
309     GLfloat data[] = { 0.5f };
310     init2DTexture(GL_R32F, GL_RED, GL_FLOAT, data);
311     runTest2D();
312 }
313 
TEST_P(SwizzleTest,D32F_2D)314 TEST_P(SwizzleTest, D32F_2D)
315 {
316     GLfloat data[] = { 0.5f };
317     init2DTexture(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, data);
318     runTest2D();
319 }
320 
TEST_P(SwizzleTest,D16_2D)321 TEST_P(SwizzleTest, D16_2D)
322 {
323     GLushort data[] = { 0xFF };
324     init2DTexture(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, data);
325     runTest2D();
326 }
327 
TEST_P(SwizzleTest,D24_2D)328 TEST_P(SwizzleTest, D24_2D)
329 {
330     GLuint data[] = { 0xFFFF };
331     init2DTexture(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, data);
332     runTest2D();
333 }
334 
TEST_P(SwizzleTest,L8_2D)335 TEST_P(SwizzleTest, L8_2D)
336 {
337     GLubyte data[] = {0x77};
338     init2DTexture(GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
339     runTest2D();
340 }
341 
TEST_P(SwizzleTest,A8_2D)342 TEST_P(SwizzleTest, A8_2D)
343 {
344     GLubyte data[] = {0x55};
345     init2DTexture(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, data);
346     runTest2D();
347 }
348 
TEST_P(SwizzleTest,LA8_2D)349 TEST_P(SwizzleTest, LA8_2D)
350 {
351     GLubyte data[] = {0x77, 0x66};
352     init2DTexture(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data);
353     runTest2D();
354 }
355 
TEST_P(SwizzleTest,L32F_2D)356 TEST_P(SwizzleTest, L32F_2D)
357 {
358     GLfloat data[] = {0.7f};
359     init2DTexture(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT, data);
360     runTest2D();
361 }
362 
TEST_P(SwizzleTest,A32F_2D)363 TEST_P(SwizzleTest, A32F_2D)
364 {
365     GLfloat data[] = {
366         0.4f,
367     };
368     init2DTexture(GL_ALPHA, GL_ALPHA, GL_FLOAT, data);
369     runTest2D();
370 }
371 
TEST_P(SwizzleTest,LA32F_2D)372 TEST_P(SwizzleTest, LA32F_2D)
373 {
374     GLfloat data[] = {
375         0.5f, 0.6f,
376     };
377     init2DTexture(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT, data);
378     runTest2D();
379 }
380 
381 #include "media/pixel.inl"
382 
TEST_P(SwizzleTest,CompressedDXT_2D)383 TEST_P(SwizzleTest, CompressedDXT_2D)
384 {
385     if (!extensionEnabled("GL_EXT_texture_compression_dxt1"))
386     {
387         std::cout << "Test skipped due to missing GL_EXT_texture_compression_dxt1." << std::endl;
388         return;
389     }
390 
391     init2DCompressedTexture(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixel_0_width, pixel_0_height, pixel_0_size, pixel_0_data);
392     runTest2D();
393 }
394 
TEST_P(SwizzleIntegerTest,RGB8UI_2D)395 TEST_P(SwizzleIntegerTest, RGB8UI_2D)
396 {
397     GLubyte data[] = {77, 66, 55};
398     init2DTexture(GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, data);
399     runTest2D();
400 }
401 
402 // Test that updating the texture data still generates the correct swizzles
TEST_P(SwizzleTest,SubUpdate)403 TEST_P(SwizzleTest, SubUpdate)
404 {
405     GLColor data(1, 64, 128, 200);
406     init2DTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &data);
407 
408     glUseProgram(mProgram);
409     glBindTexture(GL_TEXTURE_2D, mTexture);
410     glUniform1i(mTextureUniformLocation, 0);
411 
412     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
413     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
414     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
415     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
416 
417     glClear(GL_COLOR_BUFFER_BIT);
418     drawQuad(mProgram, "position", 0.5f);
419 
420     GLColor expectedData(data.R, data.R, data.R, data.R);
421     EXPECT_PIXEL_COLOR_EQ(0, 0, expectedData);
422 
423     GLColor updateData(32, 234, 28, 232);
424     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &updateData);
425 
426     glClear(GL_COLOR_BUFFER_BIT);
427     drawQuad(mProgram, "position", 0.5f);
428 
429     GLColor expectedUpdateData(updateData.R, updateData.R, updateData.R, updateData.R);
430     EXPECT_PIXEL_COLOR_EQ(0, 0, expectedUpdateData);
431 }
432 
433 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
434 ANGLE_INSTANTIATE_TEST(SwizzleTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGL(3, 3), ES3_OPENGLES());
435 ANGLE_INSTANTIATE_TEST(SwizzleIntegerTest,
436                        ES3_D3D11(),
437                        ES3_OPENGL(),
438                        ES3_OPENGL(3, 3),
439                        ES3_OPENGLES());
440 
441 } // namespace
442