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 // StateChangeTest:
7 // Specifically designed for an ANGLE implementation of GL, these tests validate that
8 // ANGLE's dirty bits systems don't get confused by certain sequences of state changes.
9 //
10
11 #include "test_utils/ANGLETest.h"
12 #include "test_utils/gl_raii.h"
13 #include "shader_utils.h"
14
15 using namespace angle;
16
17 namespace
18 {
19
20 const GLint kWidth = 64;
21 const GLint kHeight = 64;
22
23 // test drawing with GL_MULTISAMPLE_EXT enabled/disabled.
24 class EXTMultisampleCompatibilityTest : public ANGLETest
25 {
26
27 protected:
EXTMultisampleCompatibilityTest()28 EXTMultisampleCompatibilityTest()
29 {
30 setWindowWidth(64);
31 setWindowHeight(64);
32 setConfigRedBits(8);
33 setConfigBlueBits(8);
34 setConfigAlphaBits(8);
35 }
36
SetUp()37 void SetUp() override
38 {
39 ANGLETest::SetUp();
40
41 static const char* v_shader_str =
42 "attribute vec4 a_Position;\n"
43 "void main()\n"
44 "{ gl_Position = a_Position; }";
45
46 static const char* f_shader_str =
47 "precision mediump float;\n"
48 "uniform vec4 color;"
49 "void main() { gl_FragColor = color; }";
50
51 mProgram = CompileProgram(v_shader_str, f_shader_str);
52
53 GLuint position_loc = glGetAttribLocation(mProgram, "a_Position");
54 mColorLoc = glGetUniformLocation(mProgram, "color");
55
56 glGenBuffers(1, &mVBO);
57 glBindBuffer(GL_ARRAY_BUFFER, mVBO);
58 static float vertices[] = {
59 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
60 -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
61 };
62 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
63 glEnableVertexAttribArray(position_loc);
64 glVertexAttribPointer(position_loc, 2, GL_FLOAT, GL_FALSE, 0, 0);
65 }
66
TearDown()67 void TearDown() override
68 {
69 glDeleteBuffers(1, &mVBO);
70 glDeleteProgram(mProgram);
71
72 ANGLETest::TearDown();
73 }
74
prepareForDraw()75 void prepareForDraw()
76 {
77 // Create a sample buffer.
78 GLsizei num_samples = 4, max_samples = 0;
79 glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
80 num_samples = std::min(num_samples, max_samples);
81
82 glGenRenderbuffers(1, &mSampleRB);
83 glBindRenderbuffer(GL_RENDERBUFFER, mSampleRB);
84 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, num_samples,
85 GL_RGBA8_OES, kWidth, kHeight);
86 GLint param = 0;
87 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES,
88 ¶m);
89 EXPECT_GE(param, num_samples);
90
91 glGenFramebuffers(1, &mSampleFBO);
92 glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
93 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
94 GL_RENDERBUFFER, mSampleRB);
95 EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
96 glCheckFramebufferStatus(GL_FRAMEBUFFER));
97 glBindFramebuffer(GL_FRAMEBUFFER, 0);
98
99 // Create another FBO to resolve the multisample buffer into.
100 glGenTextures(1, &mResolveTex);
101 glBindTexture(GL_TEXTURE_2D, mResolveTex);
102 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA,
103 GL_UNSIGNED_BYTE, NULL);
104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
107 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
108 glGenFramebuffers(1, &mResolveFBO);
109 glBindFramebuffer(GL_FRAMEBUFFER, mResolveFBO);
110 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
111 mResolveTex, 0);
112 EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
113 glCheckFramebufferStatus(GL_FRAMEBUFFER));
114
115 glUseProgram(mProgram);
116 glViewport(0, 0, kWidth, kHeight);
117 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
118 glEnable(GL_BLEND);
119 glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
120 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
121 glClear(GL_COLOR_BUFFER_BIT);
122 }
123
prepareForVerify()124 void prepareForVerify()
125 {
126 // Resolve.
127 glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleFBO);
128 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mResolveFBO);
129 glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
130 glClear(GL_COLOR_BUFFER_BIT);
131 glBlitFramebufferANGLE(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
132 GL_COLOR_BUFFER_BIT, GL_NEAREST);
133 glBindFramebuffer(GL_READ_FRAMEBUFFER, mResolveFBO);
134
135 ASSERT_GL_NO_ERROR();
136 }
137
cleanup()138 void cleanup()
139 {
140 glBindFramebuffer(GL_FRAMEBUFFER, 0);
141 glDeleteFramebuffers(1, &mResolveFBO);
142 glDeleteFramebuffers(1, &mSampleFBO);
143 glDeleteTextures(1, &mResolveTex);
144 glDeleteRenderbuffers(1, &mSampleRB);
145
146 ASSERT_GL_NO_ERROR();
147
148 }
149
isApplicable() const150 bool isApplicable() const
151 {
152 return extensionEnabled("GL_EXT_multisample_compatibility") &&
153 extensionEnabled("GL_ANGLE_framebuffer_multisample") &&
154 extensionEnabled("GL_OES_rgb8_rgba8") &&
155 !IsAMD();
156 }
157 GLuint mSampleFBO;
158 GLuint mResolveFBO;
159 GLuint mSampleRB;
160 GLuint mResolveTex;
161
162 GLuint mColorLoc;
163 GLuint mProgram;
164 GLuint mVBO;
165 };
166
167 } //
168
169 // Test simple state tracking
TEST_P(EXTMultisampleCompatibilityTest,TestStateTracking)170 TEST_P(EXTMultisampleCompatibilityTest, TestStateTracking)
171 {
172 if (!isApplicable())
173 return;
174
175 EXPECT_TRUE(glIsEnabled(GL_MULTISAMPLE_EXT));
176 glDisable(GL_MULTISAMPLE_EXT);
177 EXPECT_FALSE(glIsEnabled(GL_MULTISAMPLE_EXT));
178 glEnable(GL_MULTISAMPLE_EXT);
179 EXPECT_TRUE(glIsEnabled(GL_MULTISAMPLE_EXT));
180
181 EXPECT_FALSE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
182 glEnable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
183 EXPECT_TRUE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
184 glDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
185 EXPECT_FALSE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
186
187 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
188 }
189
190 // Test that disabling GL_MULTISAMPLE_EXT is handled correctly.
TEST_P(EXTMultisampleCompatibilityTest,DrawAndResolve)191 TEST_P(EXTMultisampleCompatibilityTest, DrawAndResolve)
192 {
193 if (!isApplicable())
194 return;
195
196 static const float kBlue[] = {0.0f, 0.0f, 1.0f, 1.0f};
197 static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
198 static const float kRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
199
200 // Different drivers seem to behave differently with respect to resulting
201 // values. These might be due to different MSAA sample counts causing
202 // different samples to hit. Other option is driver bugs. Just test that
203 // disabling multisample causes a difference.
204 std::unique_ptr<uint8_t[]> results[3];
205 const GLint kResultSize = kWidth * kHeight * 4;
206 for (int pass = 0; pass < 3; pass++)
207 {
208 prepareForDraw();
209 // Green: from top right to bottom left.
210 glUniform4fv(mColorLoc, 1, kGreen);
211 glDrawArrays(GL_TRIANGLES, 0, 3);
212
213 // Blue: from top left to bottom right.
214 glUniform4fv(mColorLoc, 1, kBlue);
215 glDrawArrays(GL_TRIANGLES, 3, 3);
216
217 // Red, with and without MSAA: from bottom left to top right.
218 if (pass == 1)
219 {
220 glDisable(GL_MULTISAMPLE_EXT);
221 }
222 glUniform4fv(mColorLoc, 1, kRed);
223 glDrawArrays(GL_TRIANGLES, 6, 3);
224 if (pass == 1)
225 {
226 glEnable(GL_MULTISAMPLE_EXT);
227 }
228 prepareForVerify();
229 results[pass].reset(new uint8_t[kResultSize]);
230 memset(results[pass].get(), 123u, kResultSize);
231 glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
232 results[pass].get());
233
234 cleanup();
235 }
236 EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
237 // Verify that rendering is deterministic, so that the pass above does not
238 // come from non-deterministic rendering.
239 EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
240 }
241
242 // Test that enabling GL_SAMPLE_ALPHA_TO_ONE_EXT affects rendering.
TEST_P(EXTMultisampleCompatibilityTest,DrawAlphaOneAndResolve)243 TEST_P(EXTMultisampleCompatibilityTest, DrawAlphaOneAndResolve)
244 {
245 if (!isApplicable())
246 return;
247
248 // SAMPLE_ALPHA_TO_ONE is specified to transform alpha values of
249 // covered samples to 1.0. In order to detect it, we use non-1.0
250 // alpha.
251 static const float kBlue[] = {0.0f, 0.0f, 1.0f, 0.5f};
252 static const float kGreen[] = {0.0f, 1.0f, 0.0f, 0.5f};
253 static const float kRed[] = {1.0f, 0.0f, 0.0f, 0.5f};
254
255 // Different drivers seem to behave differently with respect to resulting
256 // alpha value. These might be due to different MSAA sample counts causing
257 // different samples to hit. Other option is driver bugs. Testing exact or
258 // even approximate sample values is not that easy. Thus, just test
259 // representative positions which have fractional pixels, inspecting that
260 // normal rendering is different to SAMPLE_ALPHA_TO_ONE rendering.
261 std::unique_ptr<uint8_t[]> results[3];
262 const GLint kResultSize = kWidth * kHeight * 4;
263
264 for (int pass = 0; pass < 3; ++pass)
265 {
266 prepareForDraw();
267 if (pass == 1)
268 {
269 glEnable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
270 }
271 glEnable(GL_MULTISAMPLE_EXT);
272 glUniform4fv(mColorLoc, 1, kGreen);
273 glDrawArrays(GL_TRIANGLES, 0, 3);
274
275 glUniform4fv(mColorLoc, 1, kBlue);
276 glDrawArrays(GL_TRIANGLES, 3, 3);
277
278 glDisable(GL_MULTISAMPLE_EXT);
279 glUniform4fv(mColorLoc, 1, kRed);
280 glDrawArrays(GL_TRIANGLES, 6, 3);
281
282 prepareForVerify();
283 results[pass].reset(new uint8_t[kResultSize]);
284 memset(results[pass].get(), 123u, kResultSize);
285 glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
286 results[pass].get());
287 if (pass == 1)
288 {
289 glDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
290 }
291
292 cleanup();
293 }
294 EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
295 // Verify that rendering is deterministic, so that the pass above does not
296 // come from non-deterministic rendering.
297 EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
298 }
299
300 ANGLE_INSTANTIATE_TEST(EXTMultisampleCompatibilityTest, ES2_OPENGL(), ES2_OPENGLES(), ES3_OPENGL());
301
302 class MultisampleCompatibilityTest : public ANGLETest
303 {
304
305 protected:
MultisampleCompatibilityTest()306 MultisampleCompatibilityTest()
307 {
308 setWindowWidth(64);
309 setWindowHeight(64);
310 setConfigRedBits(8);
311 setConfigBlueBits(8);
312 setConfigAlphaBits(8);
313 }
314
prepareForDraw(GLsizei numSamples)315 void prepareForDraw(GLsizei numSamples)
316 {
317 // Create a sample buffer.
318 glGenRenderbuffers(1, &mSampleRB);
319 glBindRenderbuffer(GL_RENDERBUFFER, mSampleRB);
320 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, numSamples, GL_RGBA8, kWidth,
321 kHeight);
322 GLint param = 0;
323 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, ¶m);
324 EXPECT_GE(param, numSamples);
325 glGenFramebuffers(1, &mSampleFBO);
326 glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
327 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mSampleRB);
328 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
329 glBindFramebuffer(GL_FRAMEBUFFER, 0);
330 // Create another FBO to resolve the multisample buffer into.
331 glGenTextures(1, &mResolveTex);
332 glBindTexture(GL_TEXTURE_2D, mResolveTex);
333 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
334 NULL);
335 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
336 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
338 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
339 glGenFramebuffers(1, &mResolveFBO);
340 glBindFramebuffer(GL_FRAMEBUFFER, mResolveFBO);
341 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mResolveTex, 0);
342 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
343 glViewport(0, 0, kWidth, kHeight);
344 glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
345 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
346 glClear(GL_COLOR_BUFFER_BIT);
347 ASSERT_GL_NO_ERROR();
348 }
349
prepareForVerify()350 void prepareForVerify()
351 {
352 // Resolve.
353 glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleFBO);
354 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mResolveFBO);
355 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
356 glClear(GL_COLOR_BUFFER_BIT);
357 glBlitFramebufferANGLE(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
358 GL_NEAREST);
359 glBindFramebuffer(GL_READ_FRAMEBUFFER, mResolveFBO);
360
361 ASSERT_GL_NO_ERROR();
362 }
363
cleanup()364 void cleanup()
365 {
366 glBindFramebuffer(GL_FRAMEBUFFER, 0);
367 glDeleteFramebuffers(1, &mResolveFBO);
368 glDeleteFramebuffers(1, &mSampleFBO);
369 glDeleteTextures(1, &mResolveTex);
370 glDeleteRenderbuffers(1, &mSampleRB);
371
372 ASSERT_GL_NO_ERROR();
373 }
374
isApplicable() const375 bool isApplicable() const
376 {
377 return extensionEnabled("GL_ANGLE_framebuffer_multisample") &&
378 extensionEnabled("GL_OES_rgb8_rgba8");
379 }
380
381 GLuint mSampleFBO;
382 GLuint mResolveFBO;
383 GLuint mSampleRB;
384 GLuint mResolveTex;
385 };
386
387 // Test that enabling GL_SAMPLE_COVERAGE affects rendering.
TEST_P(MultisampleCompatibilityTest,DrawCoverageAndResolve)388 TEST_P(MultisampleCompatibilityTest, DrawCoverageAndResolve)
389 {
390 if (!isApplicable())
391 return;
392
393 // TODO: Figure out why this fails on Android.
394 if (IsAndroid())
395 {
396 std::cout << "Test skipped on Android." << std::endl;
397 return;
398 }
399
400 const std::string &vertex =
401 "attribute vec4 position;\n"
402 "void main()\n"
403 "{ gl_Position = position; }";
404 const std::string &fragment =
405 "void main()\n"
406 "{ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }";
407
408 ANGLE_GL_PROGRAM(drawRed, vertex, fragment);
409
410 GLsizei maxSamples = 0;
411 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
412 int iterationCount = maxSamples + 1;
413 for (int samples = 1; samples < iterationCount; samples++)
414 {
415 prepareForDraw(samples);
416 glEnable(GL_SAMPLE_COVERAGE);
417 glSampleCoverage(1.0, false);
418 drawQuad(drawRed.get(), "position", 0.5f);
419
420 prepareForVerify();
421 GLsizei pixelCount = kWidth * kHeight;
422 std::vector<GLColor> actual(pixelCount, GLColor::black);
423 glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, actual.data());
424 glDisable(GL_SAMPLE_COVERAGE);
425 cleanup();
426
427 std::vector<GLColor> expected(pixelCount, GLColor::red);
428 EXPECT_EQ(expected, actual);
429 }
430 }
431
432 ANGLE_INSTANTIATE_TEST(MultisampleCompatibilityTest,
433 ES2_D3D9(),
434 ES2_OPENGL(),
435 ES2_OPENGLES(),
436 ES3_D3D11(),
437 ES3_OPENGL(),
438 ES3_OPENGLES());