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