• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 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 // MultisampleTest: Tests of multisampled default framebuffer
8 
9 #include "test_utils/ANGLETest.h"
10 
11 #include "test_utils/gl_raii.h"
12 #include "util/OSWindow.h"
13 #include "util/shader_utils.h"
14 #include "util/test_utils.h"
15 
16 using namespace angle;
17 
18 namespace
19 {
20 
21 using MultisampleTestParams = std::tuple<angle::PlatformParameters, bool>;
22 
PrintToStringParamName(const::testing::TestParamInfo<MultisampleTestParams> & info)23 std::string PrintToStringParamName(const ::testing::TestParamInfo<MultisampleTestParams> &info)
24 {
25     ::std::stringstream ss;
26     ss << std::get<0>(info.param);
27     if (std::get<1>(info.param))
28     {
29         ss << "__NoStoreAndResolve";
30     }
31     return ss.str();
32 }
33 
34 class MultisampleTest : public ANGLETestWithParam<MultisampleTestParams>
35 {
36   protected:
testSetUp()37     void testSetUp() override
38     {
39         const angle::PlatformParameters platform = ::testing::get<0>(GetParam());
40         std::vector<const char *> disabledFeatures;
41         if (::testing::get<1>(GetParam()))
42         {
43             disabledFeatures.push_back("allow_msaa_store_and_resolve");
44         }
45         disabledFeatures.push_back(nullptr);
46 
47         // Get display.
48         EGLAttrib dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, platform.getRenderer(),
49                                  EGL_FEATURE_OVERRIDES_DISABLED_ANGLE,
50                                  reinterpret_cast<EGLAttrib>(disabledFeatures.data()), EGL_NONE};
51         mDisplay              = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
52                                          reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
53         ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);
54 
55         ASSERT_TRUE(eglInitialize(mDisplay, nullptr, nullptr) == EGL_TRUE);
56 
57         // Nexus 5X and 6P fail to eglMakeCurrent with a config they advertise they support.
58         // http://anglebug.com/3464
59         ANGLE_SKIP_TEST_IF(IsNexus5X());
60 
61         // Find a config that uses RGBA8 and allows 4x multisampling.
62         const EGLint configAttributes[] = {EGL_SURFACE_TYPE,
63                                            EGL_WINDOW_BIT,
64                                            EGL_RED_SIZE,
65                                            8,
66                                            EGL_GREEN_SIZE,
67                                            8,
68                                            EGL_BLUE_SIZE,
69                                            8,
70                                            EGL_ALPHA_SIZE,
71                                            8,
72                                            EGL_DEPTH_SIZE,
73                                            24,
74                                            EGL_STENCIL_SIZE,
75                                            8,
76                                            EGL_SAMPLE_BUFFERS,
77                                            1,
78                                            EGL_SAMPLES,
79                                            4,
80                                            EGL_NONE};
81 
82         EGLint configCount;
83         EGLConfig multisampledConfig;
84         EGLint ret =
85             eglChooseConfig(mDisplay, configAttributes, &multisampledConfig, 1, &configCount);
86         mMultisampledConfigExists = ret && configCount > 0;
87 
88         if (!mMultisampledConfigExists)
89         {
90             return;
91         }
92 
93         // Create a window, context and surface if multisampling is possible.
94         mOSWindow = OSWindow::New();
95         mOSWindow->initialize("MultisampleTest", kWindowWidth, kWindowHeight);
96         setWindowVisible(mOSWindow, true);
97 
98         EGLint contextAttributes[] = {
99             EGL_CONTEXT_MAJOR_VERSION_KHR,
100             platform.majorVersion,
101             EGL_CONTEXT_MINOR_VERSION_KHR,
102             platform.minorVersion,
103             EGL_NONE,
104         };
105 
106         mContext =
107             eglCreateContext(mDisplay, multisampledConfig, EGL_NO_CONTEXT, contextAttributes);
108         ASSERT_TRUE(mContext != EGL_NO_CONTEXT);
109 
110         mSurface = eglCreateWindowSurface(mDisplay, multisampledConfig,
111                                           mOSWindow->getNativeWindow(), nullptr);
112         ASSERT_EGL_SUCCESS();
113 
114         eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);
115         ASSERT_EGL_SUCCESS();
116     }
117 
testTearDown()118     void testTearDown() override
119     {
120         if (mSurface)
121         {
122             eglSwapBuffers(mDisplay, mSurface);
123         }
124 
125         eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
126 
127         if (mSurface)
128         {
129             eglDestroySurface(mDisplay, mSurface);
130             ASSERT_EGL_SUCCESS();
131         }
132 
133         if (mContext != EGL_NO_CONTEXT)
134         {
135             eglDestroyContext(mDisplay, mContext);
136             ASSERT_EGL_SUCCESS();
137         }
138 
139         if (mOSWindow)
140         {
141             OSWindow::Delete(&mOSWindow);
142         }
143 
144         eglTerminate(mDisplay);
145     }
146 
prepareVertexBuffer(GLBuffer & vertexBuffer,const Vector3 * vertices,size_t vertexCount,GLint positionLocation)147     void prepareVertexBuffer(GLBuffer &vertexBuffer,
148                              const Vector3 *vertices,
149                              size_t vertexCount,
150                              GLint positionLocation)
151     {
152         glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
153         glBufferData(GL_ARRAY_BUFFER, sizeof(*vertices) * vertexCount, vertices, GL_STATIC_DRAW);
154         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
155         glEnableVertexAttribArray(positionLocation);
156     }
157 
158   protected:
159     static constexpr int kWindowWidth  = 16;
160     static constexpr int kWindowHeight = 8;
161 
162     OSWindow *mOSWindow            = nullptr;
163     EGLDisplay mDisplay            = EGL_NO_DISPLAY;
164     EGLContext mContext            = EGL_NO_CONTEXT;
165     EGLSurface mSurface            = EGL_NO_SURFACE;
166     bool mMultisampledConfigExists = false;
167 };
168 
169 class MultisampleTestES3 : public MultisampleTest
170 {};
171 
172 // Test point rendering on a multisampled surface.  GLES2 section 3.3.1.
TEST_P(MultisampleTest,Point)173 TEST_P(MultisampleTest, Point)
174 {
175     ANGLE_SKIP_TEST_IF(!mMultisampledConfigExists);
176     // http://anglebug.com/3470
177     ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIAShield() && IsOpenGLES());
178     // http://anglebug.com/5727
179     ANGLE_SKIP_TEST_IF(IsOzone());
180 
181     constexpr char kPointsVS[] = R"(precision highp float;
182 attribute vec4 a_position;
183 
184 void main()
185 {
186     gl_PointSize = 3.0;
187     gl_Position = a_position;
188 })";
189 
190     ANGLE_GL_PROGRAM(program, kPointsVS, essl1_shaders::fs::Red());
191     glUseProgram(program);
192     const GLint positionLocation = glGetAttribLocation(program, "a_position");
193 
194     GLBuffer vertexBuffer;
195     const Vector3 vertices[1] = {{0.0f, 0.0f, 0.0f}};
196     prepareVertexBuffer(vertexBuffer, vertices, 1, positionLocation);
197 
198     glClear(GL_COLOR_BUFFER_BIT);
199     glDrawArrays(GL_POINTS, 0, 1);
200 
201     ASSERT_GL_NO_ERROR();
202 
203     // The center pixels should be all red.
204     EXPECT_PIXEL_COLOR_EQ(kWindowWidth / 2, kWindowHeight / 2, GLColor::red);
205     EXPECT_PIXEL_COLOR_EQ(kWindowWidth / 2 - 1, kWindowHeight / 2, GLColor::red);
206     EXPECT_PIXEL_COLOR_EQ(kWindowWidth / 2, kWindowHeight / 2 - 1, GLColor::red);
207     EXPECT_PIXEL_COLOR_EQ(kWindowWidth / 2 - 1, kWindowHeight / 2 - 1, GLColor::red);
208 
209     // Border pixels should be between red and black, and not exactly either; corners are darker and
210     // sides are brighter.
211     const GLColor kSideColor   = {128, 0, 0, 128};
212     const GLColor kCornerColor = {64, 0, 0, 64};
213     constexpr int kErrorMargin = 16;
214     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 - 2, kWindowHeight / 2 - 2, kCornerColor,
215                             kErrorMargin);
216     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 - 2, kWindowHeight / 2 + 1, kCornerColor,
217                             kErrorMargin);
218     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 + 1, kWindowHeight / 2 - 2, kCornerColor,
219                             kErrorMargin);
220     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 + 1, kWindowHeight / 2 + 1, kCornerColor,
221                             kErrorMargin);
222 
223     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 - 2, kWindowHeight / 2 - 1, kSideColor, kErrorMargin);
224     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 - 2, kWindowHeight / 2, kSideColor, kErrorMargin);
225     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 - 1, kWindowHeight / 2 - 2, kSideColor, kErrorMargin);
226     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 - 1, kWindowHeight / 2 + 1, kSideColor, kErrorMargin);
227     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2, kWindowHeight / 2 - 2, kSideColor, kErrorMargin);
228     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2, kWindowHeight / 2 + 1, kSideColor, kErrorMargin);
229     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 + 1, kWindowHeight / 2 - 1, kSideColor, kErrorMargin);
230     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2 + 1, kWindowHeight / 2, kSideColor, kErrorMargin);
231 }
232 
233 // Test line rendering on a multisampled surface.  GLES2 section 3.4.4.
TEST_P(MultisampleTest,Line)234 TEST_P(MultisampleTest, Line)
235 {
236     ANGLE_SKIP_TEST_IF(!mMultisampledConfigExists);
237     ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
238     // http://anglebug.com/5727
239     ANGLE_SKIP_TEST_IF(IsOzone());
240 
241     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
242     glUseProgram(program);
243     const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
244 
245     GLBuffer vertexBuffer;
246     const Vector3 vertices[2] = {{-1.0f, -0.3f, 0.0f}, {1.0f, 0.3f, 0.0f}};
247     prepareVertexBuffer(vertexBuffer, vertices, 2, positionLocation);
248 
249     glClear(GL_COLOR_BUFFER_BIT);
250     glDrawArrays(GL_LINES, 0, 2);
251 
252     ASSERT_GL_NO_ERROR();
253 
254     // The line goes from left to right at about -17 degrees slope.  It renders as such (captured
255     // with renderdoc):
256     //
257     // D                    D = Dark Red (0.25) or (0.5)
258     //  BRA                 R = Red (1.0)
259     //     ARB              M = Middle Red (0.75)
260     //        D             B = Bright Red (1.0 or 0.75)
261     //                      A = Any red (0.5, 0.75 or 1.0)
262     //
263     // Verify that rendering is done as above.
264 
265     const GLColor kDarkRed     = {128, 0, 0, 128};
266     const GLColor kMidRed      = {192, 0, 0, 192};
267     constexpr int kErrorMargin = 16;
268     constexpr int kLargeMargin = 80;
269 
270     static_assert(kWindowWidth == 16, "Verification code written for 16x8 window");
271     EXPECT_PIXEL_COLOR_NEAR(0, 2, kDarkRed, kLargeMargin);
272     EXPECT_PIXEL_COLOR_NEAR(3, 3, GLColor::red, kLargeMargin);
273     EXPECT_PIXEL_COLOR_NEAR(4, 3, GLColor::red, kErrorMargin);
274     EXPECT_PIXEL_COLOR_NEAR(6, 3, kMidRed, kLargeMargin);
275     EXPECT_PIXEL_COLOR_NEAR(8, 4, kMidRed, kLargeMargin);
276     EXPECT_PIXEL_COLOR_NEAR(11, 4, GLColor::red, kErrorMargin);
277     EXPECT_PIXEL_COLOR_NEAR(12, 4, GLColor::red, kLargeMargin);
278     EXPECT_PIXEL_COLOR_NEAR(15, 5, kDarkRed, kLargeMargin);
279 }
280 
281 // Test polygon rendering on a multisampled surface.  GLES2 section 3.5.3.
TEST_P(MultisampleTest,Triangle)282 TEST_P(MultisampleTest, Triangle)
283 {
284     ANGLE_SKIP_TEST_IF(!mMultisampledConfigExists);
285     // http://anglebug.com/3470
286     ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIAShield() && IsOpenGLES());
287     // http://anglebug.com/5727
288     ANGLE_SKIP_TEST_IF(IsOzone());
289 
290     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
291     glUseProgram(program);
292     const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
293 
294     GLBuffer vertexBuffer;
295     const Vector3 vertices[3] = {{-1.0f, -1.0f, 0.0f}, {-1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}};
296     prepareVertexBuffer(vertexBuffer, vertices, 3, positionLocation);
297 
298     glClear(GL_COLOR_BUFFER_BIT);
299     glDrawArrays(GL_TRIANGLES, 0, 3);
300 
301     ASSERT_GL_NO_ERROR();
302 
303     // Top-left pixels should be all red.
304     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
305     EXPECT_PIXEL_COLOR_EQ(kWindowWidth / 4, kWindowHeight / 4, GLColor::red);
306 
307     // Diagonal pixels from bottom-left to top-right are between red and black.  Pixels above the
308     // diagonal are red and pixels below it are black.
309     const GLColor kMidRed = {128, 0, 0, 128};
310     // D3D11 is off by 63 for red (191 instead of 128), where other back-ends get 128
311     constexpr int kErrorMargin = 64;
312 
313     for (int i = 2; i + 2 < kWindowWidth; i += 2)
314     {
315         int j = kWindowHeight - 1 - (i / 2);
316         EXPECT_PIXEL_COLOR_NEAR(i, j, kMidRed, kErrorMargin);
317         EXPECT_PIXEL_COLOR_EQ(i, j - 1, GLColor::red);
318         EXPECT_PIXEL_COLOR_EQ(i, j + 1, GLColor::transparentBlack);
319     }
320 }
321 
322 // Test polygon rendering on a multisampled surface. And rendering is interrupted by a compute pass
323 // that converts the index buffer. Make sure the rendering's multisample result is preserved after
324 // interruption.
TEST_P(MultisampleTest,ContentPresevedAfterInterruption)325 TEST_P(MultisampleTest, ContentPresevedAfterInterruption)
326 {
327     ANGLE_SKIP_TEST_IF(!mMultisampledConfigExists);
328     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_rgb8_rgba8"));
329     // http://anglebug.com/3470
330     ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIAShield() && IsOpenGLES());
331     // http://anglebug.com/4609
332     ANGLE_SKIP_TEST_IF(IsD3D11());
333     // http://anglebug.com/5727
334     ANGLE_SKIP_TEST_IF(IsOzone());
335 
336     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
337     glUseProgram(program);
338     const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
339 
340     if (IsGLExtensionEnabled("GL_EXT_discard_framebuffer"))
341     {
342         GLenum attachments[] = {GL_COLOR_EXT, GL_DEPTH_EXT, GL_STENCIL_EXT};
343         glDiscardFramebufferEXT(GL_FRAMEBUFFER, 3, attachments);
344     }
345     // Draw triangle
346     GLBuffer vertexBuffer;
347     const Vector3 vertices[3] = {{-1.0f, -1.0f, 0.0f}, {-1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}};
348     prepareVertexBuffer(vertexBuffer, vertices, 3, positionLocation);
349 
350     glClear(GL_COLOR_BUFFER_BIT);
351     glDrawArrays(GL_TRIANGLES, 0, 3);
352 
353     ASSERT_GL_NO_ERROR();
354 
355     // Draw a line
356     GLBuffer vertexBuffer2;
357     GLBuffer indexBuffer2;
358     const Vector3 vertices2[2] = {{-1.0f, -0.3f, 0.0f}, {1.0f, 0.3f, 0.0f}};
359     const GLubyte indices2[]   = {0, 1};
360     prepareVertexBuffer(vertexBuffer2, vertices2, 2, positionLocation);
361     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer2);
362     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW);
363 
364     glDrawElements(GL_LINES, 2, GL_UNSIGNED_BYTE, 0);
365 
366     ASSERT_GL_NO_ERROR();
367 
368     // Top-left pixels should be all red.
369     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
370     EXPECT_PIXEL_COLOR_EQ(kWindowWidth / 4, kWindowHeight / 4, GLColor::red);
371 
372     // Triangle edge:
373     // Diagonal pixels from bottom-left to top-right are between red and black.  Pixels above the
374     // diagonal are red and pixels below it are black.
375     {
376         const GLColor kMidRed      = {128, 0, 0, 128};
377         constexpr int kErrorMargin = 16;
378 
379         for (int i = 2; i + 2 < kWindowWidth; i += 2)
380         {
381             // Exclude the middle pixel where the triangle and line cross each other.
382             if (abs(kWindowHeight / 2 - (i / 2)) <= 1)
383             {
384                 continue;
385             }
386             int j = kWindowHeight - 1 - (i / 2);
387             EXPECT_PIXEL_COLOR_NEAR(i, j, kMidRed, kErrorMargin);
388             EXPECT_PIXEL_COLOR_EQ(i, j - 1, GLColor::red);
389             EXPECT_PIXEL_COLOR_EQ(i, j + 1, GLColor::transparentBlack);
390         }
391     }
392 
393     // Line edge:
394     {
395         const GLColor kDarkRed     = {128, 0, 0, 128};
396         constexpr int kErrorMargin = 16;
397         constexpr int kLargeMargin = 80;
398 
399         static_assert(kWindowWidth == 16, "Verification code written for 16x8 window");
400         // Exclude the triangle region.
401         EXPECT_PIXEL_COLOR_NEAR(11, 4, GLColor::red, kErrorMargin);
402         EXPECT_PIXEL_COLOR_NEAR(12, 4, GLColor::red, kLargeMargin);
403         EXPECT_PIXEL_COLOR_NEAR(15, 5, kDarkRed, kLargeMargin);
404     }
405 }
406 
407 // Test that alpha to coverage is enabled works properly along with early fragment test.
TEST_P(MultisampleTest,AlphaToSampleCoverage)408 TEST_P(MultisampleTest, AlphaToSampleCoverage)
409 {
410     ANGLE_SKIP_TEST_IF(!mMultisampledConfigExists);
411     // http://anglebug.com/5727
412     ANGLE_SKIP_TEST_IF(IsOzone());
413 
414     constexpr char kFS[] =
415         "precision highp float;\n"
416         "void main()\n"
417         "{\n"
418         "    gl_FragColor = vec4(1.0, 0.0, 0.0, 0.0);\n"
419         "}\n";
420     ANGLE_GL_PROGRAM(transparentRedProgram, essl1_shaders::vs::Simple(), kFS);
421     glUseProgram(transparentRedProgram);
422     glEnable(GL_DEPTH_TEST);
423     glDepthFunc(GL_LESS);
424     glClearDepthf(1.0f);
425     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);  // clear to green
426     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
427     // This should pass depth test, but because of the alpha to coverage enabled, and alpha is 0,
428     // the fragment should be discarded. If early fragment test is disabled, no depth will be
429     // written. depth buffer should be 1.0.
430     glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
431     // There was a bug in ANGLE that we are checking sampler coverage enabled or not instead of
432     // alpha to sample coverage enabled or not. This is specically try to trick ANGLE so that it
433     // will enable early fragment test. When early fragment test is accidentally enabled, then the
434     // depth test will occur before fragment shader, and depth buffer maybe written with value
435     // (0.0+1.0)/2.0=0.5.
436     glEnable(GL_SAMPLE_COVERAGE);
437     drawQuad(transparentRedProgram, essl1_shaders::PositionAttrib(), 0.0f);
438 
439     // Now draw with blue color but to test against 0.0f. This should fail depth test
440     glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
441     glDisable(GL_SAMPLE_COVERAGE);
442     glDepthFunc(GL_GREATER);
443     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
444     // Zd = 0.5f means (0.5+1.0)/2.0=0.75. Depends on early fragment on or off this will pass or
445     // fail depth test.
446     drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
447     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
448 
449     ASSERT_GL_NO_ERROR();
450 }
451 
452 // Test that resolve from multisample default framebuffer works.
TEST_P(MultisampleTestES3,ResolveToFBO)453 TEST_P(MultisampleTestES3, ResolveToFBO)
454 {
455     ANGLE_SKIP_TEST_IF(!mMultisampledConfigExists);
456 
457     GLTexture resolveTexture;
458     glBindTexture(GL_TEXTURE_2D, resolveTexture);
459     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWindowWidth, kWindowHeight, 0, GL_RGBA,
460                  GL_UNSIGNED_BYTE, nullptr);
461     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
462     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
463 
464     GLFramebuffer resolveFBO;
465     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
466     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
467 
468     // Clear the default framebuffer
469     glBindFramebuffer(GL_FRAMEBUFFER, 0);
470     glClearColor(0.25, 0.5, 0.75, 0.25);
471     glClear(GL_COLOR_BUFFER_BIT);
472 
473     // Resolve into FBO
474     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
475     glClearColor(1, 0, 0, 1);
476     glClear(GL_COLOR_BUFFER_BIT);
477     glBlitFramebuffer(0, 0, kWindowWidth, kWindowHeight, 0, 0, kWindowWidth, kWindowHeight,
478                       GL_COLOR_BUFFER_BIT, GL_NEAREST);
479     ASSERT_GL_NO_ERROR();
480 
481     const GLColor kResult = GLColor(63, 127, 191, 63);
482     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
483     EXPECT_PIXEL_COLOR_NEAR(0, 0, kResult, 1);
484     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth - 1, 0, kResult, 1);
485     EXPECT_PIXEL_COLOR_NEAR(0, kWindowHeight - 1, kResult, 1);
486     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth - 1, kWindowHeight - 1, kResult, 1);
487     EXPECT_PIXEL_COLOR_NEAR(kWindowWidth / 2, kWindowHeight / 2, kResult, 1);
488 }
489 
490 class MultisampleResolveTest : public ANGLETest
491 {
492   protected:
493     static const GLColor kEXPECTED_R8;
494     static const GLColor kEXPECTED_RG8;
495     static const GLColor kEXPECTED_RGB8;
496     static const GLColor kEXPECTED_RGBA8;
497     static const GLColor32F kEXPECTED_RF;
498     static const GLColor32F kEXPECTED_RGF;
499     static const GLColor32F kEXPECTED_RGBF;
500     static const GLColor32F kEXPECTED_RGBAF;
501     static constexpr GLint kWidth  = 13;
502     static constexpr GLint kHeight = 11;
503 
MultisampleResolveTest()504     MultisampleResolveTest() {}
505 
506     struct GLResources
507     {
508         GLFramebuffer fb;
509         GLRenderbuffer rb;
510     };
511 
resolveToFBO(GLenum format,GLint samples,GLint width,GLint height,GLResources & resources)512     void resolveToFBO(GLenum format,
513                       GLint samples,
514                       GLint width,
515                       GLint height,
516                       GLResources &resources)
517     {
518         constexpr char kVS[] = R"(#version 300 es
519         layout(location = 0) in vec4 position;
520         void main() {
521            gl_Position = position;
522         }
523         )";
524 
525         constexpr char kFS[] = R"(#version 300 es
526         precision highp float;
527         out vec4 color;
528         void main() {
529            color = vec4(0.5, 0.6, 0.7, 0.8);
530         }
531         )";
532 
533         ANGLE_GL_PROGRAM(program, kVS, kFS);
534 
535         // Make samples = 4 multi-sample framebuffer.
536         GLFramebuffer fb0;
537         glBindFramebuffer(GL_FRAMEBUFFER, fb0);
538 
539         GLRenderbuffer rb0;
540         glBindRenderbuffer(GL_RENDERBUFFER, rb0);
541         glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
542         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb0);
543         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
544 
545         // Make samples = 0 multi-sample framebuffer.
546         glBindFramebuffer(GL_FRAMEBUFFER, resources.fb);
547 
548         glBindRenderbuffer(GL_RENDERBUFFER, resources.rb);
549         glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, format, width, height);
550         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
551                                   resources.rb);
552         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
553 
554         // Draw quad to fb0.
555         glBindFramebuffer(GL_FRAMEBUFFER, fb0);
556         glViewport(0, 0, width, height);
557         glUseProgram(program);
558         GLBuffer buf;
559         glBindBuffer(GL_ARRAY_BUFFER, buf);
560 
561         constexpr float vertices[] = {
562             -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
563         };
564         glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
565         glEnableVertexAttribArray(0);
566         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
567         glDrawArrays(GL_TRIANGLES, 0, 6);
568 
569         // Blit fb0 to fb1.
570         glBindFramebuffer(GL_READ_FRAMEBUFFER, fb0);
571         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resources.fb);
572         glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT,
573                           GL_NEAREST);
574         ASSERT_GL_NO_ERROR();
575 
576         // Prep for read pixels.
577         glBindFramebuffer(GL_READ_FRAMEBUFFER, resources.fb);
578     }
579 
testResolveToUNormFBO(GLenum format,const GLColor & expected_color,GLint samples,GLint width,GLint height)580     void testResolveToUNormFBO(GLenum format,
581                                const GLColor &expected_color,
582                                GLint samples,
583                                GLint width,
584                                GLint height)
585     {
586         GLResources resources;
587         resolveToFBO(format, samples, width, height, resources);
588 
589         // Check the results
590         for (GLint y = 0; y < kHeight; ++y)
591         {
592             for (GLint x = 0; x < kWidth; ++x)
593             {
594                 EXPECT_PIXEL_COLOR_NEAR(x, y, expected_color, 2);
595             }
596         }
597         ASSERT_GL_NO_ERROR();
598     }
599 
testResolveToHalfFBO(GLenum format,const GLColor32F & expected_color,GLint samples,GLint width,GLint height)600     void testResolveToHalfFBO(GLenum format,
601                               const GLColor32F &expected_color,
602                               GLint samples,
603                               GLint width,
604                               GLint height)
605     {
606         if (!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"))
607         {
608             return;
609         }
610 
611         GLResources resources;
612         resolveToFBO(format, samples, width, height, resources);
613 
614         // Check the results
615         for (GLint y = 0; y < kHeight; ++y)
616         {
617             for (GLint x = 0; x < kWidth; ++x)
618             {
619                 EXPECT_PIXEL_COLOR32F_NEAR(x, y, expected_color, 2.0f / 255.0f);
620             }
621         }
622         ASSERT_GL_NO_ERROR();
623     }
624 
testResolveToFloatFBO(GLenum format,const GLColor32F & expected_color,GLint samples,GLint width,GLint height)625     void testResolveToFloatFBO(GLenum format,
626                                const GLColor32F &expected_color,
627                                GLint samples,
628                                GLint width,
629                                GLint height)
630     {
631         if (!IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"))
632         {
633             return;
634         }
635 
636         GLResources resources;
637         resolveToFBO(format, samples, width, height, resources);
638 
639         // Check the results
640         for (GLint y = 0; y < kHeight; ++y)
641         {
642             for (GLint x = 0; x < kWidth; ++x)
643             {
644                 EXPECT_PIXEL_COLOR32F_NEAR(x, y, expected_color, 2.0f / 255.0f);
645             }
646         }
647         ASSERT_GL_NO_ERROR();
648     }
649 
testResolveToRGBFloatFBO(GLenum format,const GLColor32F & expected_color,GLint samples,GLint width,GLint height)650     void testResolveToRGBFloatFBO(GLenum format,
651                                   const GLColor32F &expected_color,
652                                   GLint samples,
653                                   GLint width,
654                                   GLint height)
655     {
656         if (!IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"))
657         {
658             return;
659         }
660 
661         GLResources resources;
662         resolveToFBO(format, samples, width, height, resources);
663 
664         // Check the results
665         for (GLint y = 0; y < kHeight; ++y)
666         {
667             for (GLint x = 0; x < kWidth; ++x)
668             {
669                 EXPECT_PIXEL_COLOR32F_NEAR(x, y, expected_color, 2.0f / 255.0f);
670             }
671         }
672         ASSERT_GL_NO_ERROR();
673     }
674 
peelDepth(GLint colorLoc)675     void peelDepth(GLint colorLoc)
676     {
677         // Draw full quads from front to back and increasing depths
678         // with depth test = less.
679         glDepthMask(GL_FALSE);
680         constexpr int steps = 64;
681         for (int i = 0; i < steps; ++i)
682         {
683             float l = float(i) / float(steps);
684             float c = l;
685             float z = c * 2.0f - 1.0f;
686             glVertexAttrib4f(1, 0, 0, z, 0);
687             glUniform4f(colorLoc, c, c, c, c);
688             glDrawArrays(GL_TRIANGLES, 0, 6);
689         }
690         glDepthMask(GL_TRUE);
691     }
692 
testResolveDepthToFBO(GLenum format,GLenum attachment,GLint samples,GLint width,GLint height)693     void testResolveDepthToFBO(GLenum format,
694                                GLenum attachment,
695                                GLint samples,
696                                GLint width,
697                                GLint height)
698     {
699         constexpr char kVS[] = R"(#version 300 es
700         layout(location = 0) in vec4 position;
701         void main() {
702            gl_Position = position;
703         }
704         )";
705 
706         constexpr char kFS[] = R"(#version 300 es
707         precision highp float;
708         out vec4 color;
709         void main() {
710            color = vec4(0.5, 0.6, 0.7, 0.8);
711         }
712         )";
713 
714         constexpr char kDepthVS[] = R"(#version 300 es
715         layout(location = 0) in vec4 position;
716         layout(location = 1) in vec4 offset;
717         void main() {
718            gl_Position = position + offset;
719         }
720         )";
721 
722         constexpr char kDepthFS[] = R"(#version 300 es
723         precision highp float;
724         uniform vec4 color;
725         out vec4 outColor;
726         void main() {
727            outColor = color;
728         }
729         )";
730 
731         ANGLE_GL_PROGRAM(program, kVS, kFS);
732         ANGLE_GL_PROGRAM(depthProgram, kDepthVS, kDepthFS);
733 
734         // Make samples = 4 multi-sample framebuffer.
735         GLFramebuffer fb0;
736         glBindFramebuffer(GL_FRAMEBUFFER, fb0);
737 
738         GLRenderbuffer rb0;
739         glBindRenderbuffer(GL_RENDERBUFFER, rb0);
740         glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA8, width, height);
741         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb0);
742 
743         GLRenderbuffer db0;
744         glBindRenderbuffer(GL_RENDERBUFFER, db0);
745         glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
746         glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, db0);
747 
748         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
749 
750         // Make samples = 0 multi-sample framebuffer.
751         GLFramebuffer fb1;
752         glBindFramebuffer(GL_FRAMEBUFFER, fb1);
753 
754         GLRenderbuffer rb1;
755         glBindRenderbuffer(GL_RENDERBUFFER, rb1);
756         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
757         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb1);
758         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
759 
760         GLRenderbuffer db1;
761         glBindRenderbuffer(GL_RENDERBUFFER, db1);
762         glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
763         glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, db1);
764 
765         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
766 
767         // Draw quad to fb0.
768         glBindFramebuffer(GL_FRAMEBUFFER, fb0);
769         glViewport(0, 0, width, height);
770         glClearColor(1, 1, 1, 1);
771         glUseProgram(program);
772 
773         GLVertexArray va0;
774         glBindVertexArray(va0);
775 
776         GLBuffer buf0;
777         glBindBuffer(GL_ARRAY_BUFFER, buf0);
778 
779         // clang-format off
780         constexpr float vertices[] = {
781             -1.0f, -1.0f, -1.0,
782              1.0f, -1.0f,  0.0,
783             -1.0f,  1.0f,  0.0,
784             -1.0f,  1.0f,  0.0,
785              1.0f, -1.0f,  0.0,
786              1.0f,  1.0f,  1.0,
787         };
788         // clang-format on
789 
790         glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
791         glEnableVertexAttribArray(0);
792         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
793         glEnable(GL_DEPTH_TEST);
794         glDepthFunc(GL_ALWAYS);
795         glDrawArrays(GL_TRIANGLES, 0, 6);
796 
797         // Blit fb0 to fb1.
798         glBindFramebuffer(GL_READ_FRAMEBUFFER, fb0);
799         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb1);
800         glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT,
801                           GL_NEAREST);
802         ASSERT_GL_NO_ERROR();
803 
804         GLVertexArray va1;
805         glBindVertexArray(va1);
806 
807         // clang-format off
808         constexpr float depthVertices[] = {
809             -1.0f, -1.0f,
810              1.0f, -1.0f,
811             -1.0f,  1.0f,
812             -1.0f,  1.0f,
813              1.0f, -1.0f,
814              1.0f,  1.0f,
815         };
816         // clang-format on
817 
818         GLBuffer buf1;
819         glBindBuffer(GL_ARRAY_BUFFER, buf1);
820         glBufferData(GL_ARRAY_BUFFER, sizeof(depthVertices), depthVertices, GL_STATIC_DRAW);
821         glEnableVertexAttribArray(0);
822         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
823 
824         glUseProgram(depthProgram);
825         GLint colorLoc = glGetUniformLocation(depthProgram, "color");
826 
827         // Extract the depth results.
828         glBindFramebuffer(GL_FRAMEBUFFER, fb1);
829         glClear(GL_COLOR_BUFFER_BIT);
830         glDepthFunc(GL_LESS);
831         peelDepth(colorLoc);
832         std::vector<GLColor> actual(width * height);
833         glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, actual.data());
834 
835         // Render what should be a similar result to the non-multi-sampled fb
836         glBindVertexArray(va0);
837         glDepthFunc(GL_ALWAYS);
838         glUseProgram(program);
839         glDrawArrays(GL_TRIANGLES, 0, 6);
840 
841         // Extract the expected depth results.
842         glBindVertexArray(va1);
843         glUseProgram(depthProgram);
844         glClear(GL_COLOR_BUFFER_BIT);
845         glDepthFunc(GL_LESS);
846         peelDepth(colorLoc);
847         std::vector<GLColor> expected(width * height);
848         glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, expected.data());
849 
850         for (size_t i = 0; i < expected.size(); ++i)
851         {
852             EXPECT_NEAR(expected[i].R, actual[i].R, 8)
853                 << "at " << (i % width) << "," << (i / width);
854         }
855 
856         // Verify we read the depth buffer.
857         const GLint minDimension = std::min(width, height);
858         for (GLint i = 1; i < minDimension; ++i)
859         {
860             const GLColor &c1 = expected[i - 1];
861             const GLColor &c2 = expected[i * width + i];
862             EXPECT_LT(c1.R, c2.R);
863         }
864         ASSERT_GL_NO_ERROR();
865     }
866 };
867 
868 // Test the multisampled optimized resolve subpass
TEST_P(MultisampleResolveTest,DISABLED_ResolveSubpassMSImage)869 TEST_P(MultisampleResolveTest, DISABLED_ResolveSubpassMSImage)
870 {
871     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
872 
873     // Draw green.
874     drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
875     swapBuffers();
876 
877     // Wait for visual verification.
878     angle::Sleep(2000);
879 }
880 
881 // These colors match the shader in resolveToFBO which returns (0.5, 0.6, 0.7, 0.8).
882 const GLColor MultisampleResolveTest::kEXPECTED_R8(128, 0, 0, 255);
883 const GLColor MultisampleResolveTest::kEXPECTED_RG8(128, 153, 0, 255);
884 const GLColor MultisampleResolveTest::kEXPECTED_RGB8(128, 153, 178, 255);
885 const GLColor MultisampleResolveTest::kEXPECTED_RGBA8(128, 153, 178, 204);
886 const GLColor32F MultisampleResolveTest::kEXPECTED_RF(0.5f, 0.0f, 0.0f, 1.0f);
887 const GLColor32F MultisampleResolveTest::kEXPECTED_RGF(0.5f, 0.6f, 0.0f, 1.0f);
888 const GLColor32F MultisampleResolveTest::kEXPECTED_RGBF(0.5f, 0.6f, 0.7f, 1.0f);
889 const GLColor32F MultisampleResolveTest::kEXPECTED_RGBAF(0.5f, 0.6f, 0.7f, 0.8f);
890 
891 // Test we can render to and resolve an RGBA8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGBA8ToFBO4Samples)892 TEST_P(MultisampleResolveTest, ResolveRGBA8ToFBO4Samples)
893 {
894     testResolveToUNormFBO(GL_RGBA8, kEXPECTED_RGBA8, 4, kWidth, kHeight);
895 }
896 
897 // Test we can render to and resolve an RGB8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGB8ToFBO4Samples)898 TEST_P(MultisampleResolveTest, ResolveRGB8ToFBO4Samples)
899 {
900     testResolveToUNormFBO(GL_RGB8, kEXPECTED_RGB8, 4, kWidth, kHeight);
901 }
902 
903 // Test we can render to and resolve an RG8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveRG8ToFBO4Samples)904 TEST_P(MultisampleResolveTest, ResolveRG8ToFBO4Samples)
905 {
906     testResolveToUNormFBO(GL_RG8, kEXPECTED_RG8, 4, kWidth, kHeight);
907 }
908 
909 // Test we can render to and resolve an R8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveR8ToFBO4Samples)910 TEST_P(MultisampleResolveTest, ResolveR8ToFBO4Samples)
911 {
912     testResolveToUNormFBO(GL_R8, kEXPECTED_R8, 4, kWidth, kHeight);
913 }
914 
915 // Test we can render to and resolve an R16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveR16FToFBO4Samples)916 TEST_P(MultisampleResolveTest, ResolveR16FToFBO4Samples)
917 {
918     testResolveToHalfFBO(GL_R16F, kEXPECTED_RF, 4, kWidth, kHeight);
919 }
920 
921 // Test we can render to and resolve an RG16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRG16FToFBO4Samples)922 TEST_P(MultisampleResolveTest, ResolveRG16FToFBO4Samples)
923 {
924     testResolveToHalfFBO(GL_RG16F, kEXPECTED_RGF, 4, kWidth, kHeight);
925 }
926 
927 // Test we can render to and resolve an RGB16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGB16FToFBO4Samples)928 TEST_P(MultisampleResolveTest, ResolveRGB16FToFBO4Samples)
929 {
930     testResolveToHalfFBO(GL_RGB16F, kEXPECTED_RGBF, 4, kWidth, kHeight);
931 }
932 
933 // Test we can render to and resolve an RGBA16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGBA16FToFBO4Samples)934 TEST_P(MultisampleResolveTest, ResolveRGBA16FToFBO4Samples)
935 {
936     testResolveToHalfFBO(GL_RGBA16F, kEXPECTED_RGBAF, 4, kWidth, kHeight);
937 }
938 
939 // Test we can render to and resolve an R32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveR32FToFBO4Samples)940 TEST_P(MultisampleResolveTest, ResolveR32FToFBO4Samples)
941 {
942     testResolveToFloatFBO(GL_R32F, kEXPECTED_RF, 4, kWidth, kHeight);
943 }
944 
945 // Test we can render to and resolve an RG32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRG32FToFBO4Samples)946 TEST_P(MultisampleResolveTest, ResolveRG32FToFBO4Samples)
947 {
948     testResolveToFloatFBO(GL_RG32F, kEXPECTED_RGF, 4, kWidth, kHeight);
949 }
950 
951 // Test we can render to and resolve an RGB32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGB32FToFBO4Samples)952 TEST_P(MultisampleResolveTest, ResolveRGB32FToFBO4Samples)
953 {
954     testResolveToRGBFloatFBO(GL_RGB32F, kEXPECTED_RGBF, 4, kWidth, kHeight);
955 }
956 
957 // Test we can render to and resolve an RGBA32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGBA32FToFBO4Samples)958 TEST_P(MultisampleResolveTest, ResolveRGBA32FToFBO4Samples)
959 {
960     testResolveToFloatFBO(GL_RGBA32F, kEXPECTED_RGBAF, 4, kWidth, kHeight);
961 }
962 
TEST_P(MultisampleResolveTest,ResolveD32FS8F4Samples)963 TEST_P(MultisampleResolveTest, ResolveD32FS8F4Samples)
964 {
965     testResolveDepthToFBO(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, 4, kWidth, kHeight);
966 }
967 
TEST_P(MultisampleResolveTest,ResolveD24S8Samples)968 TEST_P(MultisampleResolveTest, ResolveD24S8Samples)
969 {
970     testResolveDepthToFBO(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, 4, kWidth, kHeight);
971 }
972 
TEST_P(MultisampleResolveTest,ResolveD32FSamples)973 TEST_P(MultisampleResolveTest, ResolveD32FSamples)
974 {
975     testResolveDepthToFBO(GL_DEPTH_COMPONENT32F, GL_DEPTH_ATTACHMENT, 4, kWidth, kHeight);
976 }
977 
TEST_P(MultisampleResolveTest,ResolveD24Samples)978 TEST_P(MultisampleResolveTest, ResolveD24Samples)
979 {
980     testResolveDepthToFBO(GL_DEPTH_COMPONENT24, GL_DEPTH_ATTACHMENT, 4, kWidth, kHeight);
981 }
982 
TEST_P(MultisampleResolveTest,ResolveD16Samples)983 TEST_P(MultisampleResolveTest, ResolveD16Samples)
984 {
985     testResolveDepthToFBO(GL_DEPTH_COMPONENT16, GL_DEPTH_ATTACHMENT, 4, kWidth, kHeight);
986 }
987 
drawRectAndBlit(GLuint msFramebuffer,GLuint resolveFramebuffer,GLint width,GLint height,GLint matLoc,GLint colorLoc,float x,float y,float w,float h,const GLColor & color)988 void drawRectAndBlit(GLuint msFramebuffer,
989                      GLuint resolveFramebuffer,
990                      GLint width,
991                      GLint height,
992                      GLint matLoc,
993                      GLint colorLoc,
994                      float x,
995                      float y,
996                      float w,
997                      float h,
998                      const GLColor &color)
999 {
1000     glBindFramebuffer(GL_FRAMEBUFFER, msFramebuffer);
1001     float matrix[16] = {
1002         w, 0, 0, 0, 0, h, 0, 0, 0, 0, 1, 0, x, y, 0, 1,
1003     };
1004     glUniformMatrix4fv(matLoc, 1, false, matrix);
1005     angle::Vector4 c(color.toNormalizedVector());
1006     glUniform4f(colorLoc, c[0], c[1], c[2], c[3]);
1007     glDrawArrays(GL_TRIANGLES, 0, 6);
1008 
1009     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFramebuffer);
1010     glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1011 }
1012 
1013 // Tests if we resolve(blit) a multisample renderbuffer that it
1014 // does not lose its contents.
TEST_P(MultisampleResolveTest,DrawAndResolveMultipleTimes)1015 TEST_P(MultisampleResolveTest, DrawAndResolveMultipleTimes)
1016 {
1017     constexpr GLint samples = 4;
1018     constexpr GLenum format = GL_RGBA8;
1019     constexpr GLint width   = 16;
1020     constexpr GLint height  = 16;
1021 
1022     constexpr char kVS[] = R"(#version 300 es
1023     layout(location = 0) in vec4 position;
1024     uniform mat4 mat;
1025     void main() {
1026        gl_Position = mat * position;
1027     }
1028     )";
1029 
1030     constexpr char kFS[] = R"(#version 300 es
1031     precision highp float;
1032     uniform vec4 color;
1033     out vec4 outColor;
1034     void main() {
1035        outColor = color;
1036     }
1037     )";
1038 
1039     glViewport(0, 0, width, height);
1040 
1041     ANGLE_GL_PROGRAM(program, kVS, kFS);
1042     GLint matLoc   = glGetUniformLocation(program, "mat");
1043     GLint colorLoc = glGetUniformLocation(program, "color");
1044     glUseProgram(program);
1045 
1046     GLBuffer buf;
1047     glBindBuffer(GL_ARRAY_BUFFER, buf);
1048 
1049     constexpr float vertices[] = {
1050         0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1051     };
1052     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
1053     glEnableVertexAttribArray(0);
1054     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
1055 
1056     // Make samples = 4 multi-sample framebuffer.
1057     GLFramebuffer msFB;
1058     glBindFramebuffer(GL_FRAMEBUFFER, msFB);
1059 
1060     GLRenderbuffer msRB;
1061     glBindRenderbuffer(GL_RENDERBUFFER, msRB);
1062     glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
1063     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msRB);
1064     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1065 
1066     // Make non-multi-sample framebuffer.
1067     GLFramebuffer drawFB;
1068     glBindFramebuffer(GL_FRAMEBUFFER, drawFB);
1069 
1070     GLRenderbuffer drawRB;
1071     glBindRenderbuffer(GL_RENDERBUFFER, drawRB);
1072     glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
1073     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, drawRB);
1074     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1075 
1076     drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, -1, -1, 2, 2, GLColor::red);
1077     drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, 0, -1, 1, 1, GLColor::green);
1078     drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, -1, 0, 1, 1, GLColor::blue);
1079     drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, 0, 0, 1, 1, GLColor::yellow);
1080     glEnable(GL_BLEND);
1081     glBlendFunc(GL_ONE, GL_ONE);
1082     drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, -0.5, -0.5, 1, 1,
1083                     GLColor(0x80, 0x80, 0x80, 0x80));
1084     glDisable(GL_BLEND);
1085     ASSERT_GL_NO_ERROR();
1086 
1087     /*
1088        expected
1089        +-------------+--------------+
1090        | blue        |       yellow |
1091        |   +---------+----------+   |
1092        |   |.5,.5,1,1| 1,1,.5,1 |   |
1093        +---+---------+----------+---+
1094        |   |1,.5,.5,1| .5,1,.5,1|   |
1095        |   +---------+----------+   |
1096        | red         |        green |
1097        +-------------+--------------+
1098       0,0
1099     */
1100 
1101     glBindFramebuffer(GL_FRAMEBUFFER, drawFB);
1102     EXPECT_PIXEL_RECT_EQ(0, 0, width / 2, height / 4, GLColor::red);
1103     EXPECT_PIXEL_RECT_EQ(width / 2, 0, width / 2, height / 4, GLColor::green);
1104     EXPECT_PIXEL_RECT_EQ(0, height * 3 / 4, width / 2, height / 4, GLColor::blue);
1105     EXPECT_PIXEL_RECT_EQ(width / 2, height * 3 / 4, width / 2, height / 4, GLColor::yellow);
1106 
1107     EXPECT_PIXEL_RECT_EQ(width / 4, height / 4, width / 4, height / 4, GLColor(255, 128, 128, 255));
1108     EXPECT_PIXEL_RECT_EQ(width / 2, height / 4, width / 4, height / 4, GLColor(128, 255, 128, 255));
1109     EXPECT_PIXEL_RECT_EQ(width / 4, height / 2, width / 4, height / 4, GLColor(128, 128, 255, 255));
1110     EXPECT_PIXEL_RECT_EQ(width / 2, height / 2, width / 4, height / 4, GLColor(255, 255, 128, 255));
1111 }
1112 
1113 ANGLE_INSTANTIATE_TEST_COMBINE_1(MultisampleTest,
1114                                  PrintToStringParamName,
1115                                  testing::Values(false),
1116                                  WithNoFixture(ES2_D3D11()),
1117                                  WithNoFixture(ES3_D3D11()),
1118                                  WithNoFixture(ES31_D3D11()),
1119                                  WithNoFixture(ES2_METAL()),
1120                                  WithNoFixture(ES2_OPENGL()),
1121                                  WithNoFixture(ES3_OPENGL()),
1122                                  WithNoFixture(ES31_OPENGL()),
1123                                  WithNoFixture(ES2_OPENGLES()),
1124                                  WithNoFixture(ES3_OPENGLES()),
1125                                  WithNoFixture(ES31_OPENGLES()),
1126                                  WithNoFixture(ES2_VULKAN()),
1127                                  WithNoFixture(ES3_VULKAN()),
1128                                  WithNoFixture(ES31_VULKAN()));
1129 
1130 namespace store_and_resolve_feature_off
1131 {
1132 // Simulate missing msaa auto resolve feature in Metal.
1133 ANGLE_INSTANTIATE_TEST_COMBINE_1(MultisampleTest,
1134                                  PrintToStringParamName,
1135                                  testing::Values(true),
1136                                  WithNoFixture(ES2_METAL()));
1137 }  // namespace store_and_resolve_feature_off
1138 
1139 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultisampleTestES3);
1140 ANGLE_INSTANTIATE_TEST_COMBINE_1(MultisampleTestES3,
1141                                  PrintToStringParamName,
1142                                  testing::Values(false),
1143                                  WithNoFixture(ES3_D3D11()),
1144                                  WithNoFixture(ES31_D3D11()),
1145                                  WithNoFixture(ES3_OPENGL()),
1146                                  WithNoFixture(ES31_OPENGL()),
1147                                  WithNoFixture(ES3_OPENGLES()),
1148                                  WithNoFixture(ES31_OPENGLES()),
1149                                  WithNoFixture(ES3_VULKAN()),
1150                                  WithNoFixture(ES31_VULKAN()),
1151                                  WithNoFixture(ES3_METAL()));
1152 
1153 ANGLE_INSTANTIATE_TEST_ES3(MultisampleResolveTest);
1154 
1155 }  // anonymous namespace
1156