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