• 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     // http://anglebug.com/5270
176     ANGLE_SKIP_TEST_IF(IsOSX() && IsIntelUHD630Mobile() && IsDesktopOpenGL());
177 
178     static const float kBlue[]  = {0.0f, 0.0f, 1.0f, 1.0f};
179     static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
180     static const float kRed[]   = {1.0f, 0.0f, 0.0f, 1.0f};
181 
182     // Different drivers seem to behave differently with respect to resulting
183     // values. These might be due to different MSAA sample counts causing
184     // different samples to hit.  Other option is driver bugs. Just test that
185     // disabling multisample causes a difference.
186     std::unique_ptr<uint8_t[]> results[3];
187     const GLint kResultSize = kWidth * kHeight * 4;
188     for (int pass = 0; pass < 3; pass++)
189     {
190         prepareForDraw();
191         // Green: from top right to bottom left.
192         glUniform4fv(mColorLoc, 1, kGreen);
193         glDrawArrays(GL_TRIANGLES, 0, 3);
194 
195         // Blue: from top left to bottom right.
196         glUniform4fv(mColorLoc, 1, kBlue);
197         glDrawArrays(GL_TRIANGLES, 3, 3);
198 
199         // Red, with and without MSAA: from bottom left to top right.
200         if (pass == 1)
201         {
202             glDisable(GL_MULTISAMPLE_EXT);
203         }
204         glUniform4fv(mColorLoc, 1, kRed);
205         glDrawArrays(GL_TRIANGLES, 6, 3);
206         if (pass == 1)
207         {
208             glEnable(GL_MULTISAMPLE_EXT);
209         }
210         prepareForVerify();
211         results[pass].reset(new uint8_t[kResultSize]);
212         memset(results[pass].get(), 123u, kResultSize);
213         glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, results[pass].get());
214 
215         cleanup();
216     }
217     EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
218     // Verify that rendering is deterministic, so that the pass above does not
219     // come from non-deterministic rendering.
220     EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
221 }
222 
223 // Test that enabling GL_SAMPLE_ALPHA_TO_ONE_EXT affects rendering.
TEST_P(EXTMultisampleCompatibilityTest,DrawAlphaOneAndResolve)224 TEST_P(EXTMultisampleCompatibilityTest, DrawAlphaOneAndResolve)
225 {
226     if (!isApplicable())
227         return;
228 
229     // SAMPLE_ALPHA_TO_ONE is specified to transform alpha values of
230     // covered samples to 1.0. In order to detect it, we use non-1.0
231     // alpha.
232     static const float kBlue[]  = {0.0f, 0.0f, 1.0f, 0.5f};
233     static const float kGreen[] = {0.0f, 1.0f, 0.0f, 0.5f};
234     static const float kRed[]   = {1.0f, 0.0f, 0.0f, 0.5f};
235 
236     // Different drivers seem to behave differently with respect to resulting
237     // alpha value. These might be due to different MSAA sample counts causing
238     // different samples to hit.  Other option is driver bugs. Testing exact or
239     // even approximate sample values is not that easy.  Thus, just test
240     // representative positions which have fractional pixels, inspecting that
241     // normal rendering is different to SAMPLE_ALPHA_TO_ONE rendering.
242     std::unique_ptr<uint8_t[]> results[3];
243     const GLint kResultSize = kWidth * kHeight * 4;
244 
245     for (int pass = 0; pass < 3; ++pass)
246     {
247         prepareForDraw();
248         if (pass == 1)
249         {
250             glEnable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
251         }
252         glEnable(GL_MULTISAMPLE_EXT);
253         glUniform4fv(mColorLoc, 1, kGreen);
254         glDrawArrays(GL_TRIANGLES, 0, 3);
255 
256         glUniform4fv(mColorLoc, 1, kBlue);
257         glDrawArrays(GL_TRIANGLES, 3, 3);
258 
259         glDisable(GL_MULTISAMPLE_EXT);
260         glUniform4fv(mColorLoc, 1, kRed);
261         glDrawArrays(GL_TRIANGLES, 6, 3);
262 
263         prepareForVerify();
264         results[pass].reset(new uint8_t[kResultSize]);
265         memset(results[pass].get(), 123u, kResultSize);
266         glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, results[pass].get());
267         if (pass == 1)
268         {
269             glDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
270         }
271 
272         cleanup();
273     }
274     EXPECT_NE(0, memcmp(results[0].get(), results[1].get(), kResultSize));
275     // Verify that rendering is deterministic, so that the pass above does not
276     // come from non-deterministic rendering.
277     EXPECT_EQ(0, memcmp(results[0].get(), results[2].get(), kResultSize));
278 }
279 
280 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(EXTMultisampleCompatibilityTest);
281 
282 class MultisampleCompatibilityTest : public ANGLETest
283 {
284 
285   protected:
MultisampleCompatibilityTest()286     MultisampleCompatibilityTest()
287     {
288         setWindowWidth(64);
289         setWindowHeight(64);
290         setConfigRedBits(8);
291         setConfigBlueBits(8);
292         setConfigAlphaBits(8);
293     }
294 
prepareForDraw(GLsizei numSamples)295     void prepareForDraw(GLsizei numSamples)
296     {
297         // Create a sample buffer.
298         glGenRenderbuffers(1, &mSampleRB);
299         glBindRenderbuffer(GL_RENDERBUFFER, mSampleRB);
300         glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, numSamples, GL_RGBA8, kWidth,
301                                               kHeight);
302         GLint param = 0;
303         glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &param);
304         EXPECT_GE(param, numSamples);
305         glGenFramebuffers(1, &mSampleFBO);
306         glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
307         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mSampleRB);
308         EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
309         glBindFramebuffer(GL_FRAMEBUFFER, 0);
310         // Create another FBO to resolve the multisample buffer into.
311         glGenTextures(1, &mResolveTex);
312         glBindTexture(GL_TEXTURE_2D, mResolveTex);
313         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
314                      nullptr);
315         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
316         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
317         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
318         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
319         glGenFramebuffers(1, &mResolveFBO);
320         glBindFramebuffer(GL_FRAMEBUFFER, mResolveFBO);
321         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mResolveTex, 0);
322         EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
323         glViewport(0, 0, kWidth, kHeight);
324         glBindFramebuffer(GL_FRAMEBUFFER, mSampleFBO);
325         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
326         glClear(GL_COLOR_BUFFER_BIT);
327         ASSERT_GL_NO_ERROR();
328     }
329 
prepareForVerify()330     void prepareForVerify()
331     {
332         // Resolve.
333         glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleFBO);
334         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mResolveFBO);
335         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
336         glClear(GL_COLOR_BUFFER_BIT);
337         glBlitFramebufferANGLE(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
338                                GL_NEAREST);
339         glBindFramebuffer(GL_READ_FRAMEBUFFER, mResolveFBO);
340 
341         ASSERT_GL_NO_ERROR();
342     }
343 
cleanup()344     void cleanup()
345     {
346         glBindFramebuffer(GL_FRAMEBUFFER, 0);
347         glDeleteFramebuffers(1, &mResolveFBO);
348         glDeleteFramebuffers(1, &mSampleFBO);
349         glDeleteTextures(1, &mResolveTex);
350         glDeleteRenderbuffers(1, &mSampleRB);
351 
352         ASSERT_GL_NO_ERROR();
353     }
354 
isApplicable() const355     bool isApplicable() const
356     {
357         return IsGLExtensionEnabled("GL_ANGLE_framebuffer_multisample") &&
358                IsGLExtensionEnabled("GL_OES_rgb8_rgba8");
359     }
360 
361     GLuint mSampleFBO;
362     GLuint mResolveFBO;
363     GLuint mSampleRB;
364     GLuint mResolveTex;
365 };
366 
367 // Test that enabling GL_SAMPLE_COVERAGE affects rendering.
TEST_P(MultisampleCompatibilityTest,DrawCoverageAndResolve)368 TEST_P(MultisampleCompatibilityTest, DrawCoverageAndResolve)
369 {
370     if (!isApplicable())
371         return;
372 
373     // TODO: Figure out why this fails on Android.
374     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
375 
376     ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
377 
378     GLsizei maxSamples = 0;
379     glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
380     int iterationCount = maxSamples + 1;
381     for (int samples = 1; samples < iterationCount; samples++)
382     {
383         prepareForDraw(samples);
384         glEnable(GL_SAMPLE_COVERAGE);
385         glSampleCoverage(1.0, false);
386         drawQuad(drawRed.get(), essl1_shaders::PositionAttrib(), 0.5f);
387 
388         prepareForVerify();
389         GLsizei pixelCount = kWidth * kHeight;
390         std::vector<GLColor> actual(pixelCount, GLColor::black);
391         glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, actual.data());
392         glDisable(GL_SAMPLE_COVERAGE);
393         cleanup();
394 
395         std::vector<GLColor> expected(pixelCount, GLColor::red);
396         EXPECT_EQ(expected, actual);
397     }
398 }
399 
400 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(MultisampleCompatibilityTest);
401