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