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