xref: /aosp_15_r20/external/angle/src/tests/gl_tests/MultisampleTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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/42262135
64     ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIAShield() && IsOpenGLES());
65     // http://anglebug.com/42264264
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/42264264
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/42262135
171     ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIAShield() && IsOpenGLES());
172     // http://anglebug.com/42264264
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/42262135
214     ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIAShield() && IsOpenGLES());
215     // http://anglebug.com/42263216
216     ANGLE_SKIP_TEST_IF(IsD3D11());
217     // http://anglebug.com/42264264
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/42264264
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 // Test that CopyTexImage2D from an MSAA default fbo works
TEST_P(MultisampleTestES3,CopyTexImage2DFromMsaaDefaultFbo)420 TEST_P(MultisampleTestES3, CopyTexImage2DFromMsaaDefaultFbo)
421 {
422     constexpr char kFS[] = R"(#version 300 es
423 #extension GL_OES_sample_variables : require
424 precision highp float;
425 out vec4 my_FragColor;
426 
427 void main()
428 {
429     switch (uint(gl_SampleID))
430     {
431         case 0u:
432             my_FragColor = vec4(1.0, 0.9, 0.8, 0.7);
433             break;
434         case 1u:
435             my_FragColor = vec4(0.0, 0.1, 0.2, 0.3);
436             break;
437         case 2u:
438             my_FragColor = vec4(0.5, 0.25, 0.75, 1.0);
439             break;
440         case 3u:
441             my_FragColor = vec4(0.4, 0.6, 0.2, 0.8);
442             break;
443         default:
444             my_FragColor = vec4(0.0);
445             break;
446     }
447 }
448 )";
449 
450     ANGLE_GL_PROGRAM(programMs, essl3_shaders::vs::Simple(), kFS);
451     glUseProgram(programMs);
452 
453     // Clear the default framebuffer and draw
454     glBindFramebuffer(GL_FRAMEBUFFER, 0);
455     glClearColor(0.25, 0.5, 0.75, 0.25);
456     glClear(GL_COLOR_BUFFER_BIT);
457     drawQuad(programMs, essl3_shaders::PositionAttrib(), 0.0);
458 
459     // Create a texture for copy
460     GLTexture copyTexture;
461     glBindTexture(GL_TEXTURE_2D, copyTexture);
462     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWindowWidth, kWindowHeight, 0, GL_RGBA,
463                  GL_UNSIGNED_BYTE, nullptr);
464     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
465     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
466 
467     constexpr int kCopyWidth  = 10;
468     constexpr int kCopyHeight = 5;
469     // Copy MSAA default framebuffer into the texture
470     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kCopyWidth, kCopyHeight, 0);
471     ASSERT_GL_NO_ERROR();
472 
473     GLFramebuffer readFbo;
474     glBindFramebuffer(GL_FRAMEBUFFER, readFbo);
475     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTexture, 0);
476 
477     const GLColor kResult = GLColor(121, 118, 124, 178);
478     EXPECT_PIXEL_COLOR_NEAR(0, 0, kResult, 1);
479     EXPECT_PIXEL_COLOR_NEAR(kCopyWidth - 1, 0, kResult, 1);
480     EXPECT_PIXEL_COLOR_NEAR(0, kCopyHeight - 1, kResult, 1);
481     EXPECT_PIXEL_COLOR_NEAR(kCopyWidth - 1, kCopyHeight - 1, kResult, 1);
482     EXPECT_PIXEL_COLOR_NEAR(kCopyWidth / 2, kCopyHeight / 2, kResult, 1);
483 }
484 
485 class MultisampleResolveTest : public ANGLETest<>
486 {
487   protected:
488     static const GLColor kEXPECTED_R8;
489     static const GLColor kEXPECTED_RG8;
490     static const GLColor kEXPECTED_RGB8;
491     static const GLColor kEXPECTED_RGBA8;
492     static const GLColor32F kEXPECTED_RF;
493     static const GLColor32F kEXPECTED_RGF;
494     static const GLColor32F kEXPECTED_RGBF;
495     static const GLColor32F kEXPECTED_RGBAF;
496     static constexpr GLint kWidth  = 13;
497     static constexpr GLint kHeight = 11;
498 
MultisampleResolveTest()499     MultisampleResolveTest() {}
500 
501     struct GLResources
502     {
503         GLFramebuffer fb;
504         GLRenderbuffer rb;
505     };
506 
resolveToFBO(GLenum format,GLint samples,GLint width,GLint height,GLResources & resources)507     void resolveToFBO(GLenum format,
508                       GLint samples,
509                       GLint width,
510                       GLint height,
511                       GLResources &resources)
512     {
513         constexpr char kVS[] = R"(#version 300 es
514         layout(location = 0) in vec4 position;
515         void main() {
516            gl_Position = position;
517         }
518         )";
519 
520         constexpr char kFS[] = R"(#version 300 es
521         precision highp float;
522         out vec4 color;
523         void main() {
524            color = vec4(0.5, 0.6, 0.7, 0.8);
525         }
526         )";
527 
528         ANGLE_GL_PROGRAM(program, kVS, kFS);
529 
530         // Make samples = 4 multi-sample framebuffer.
531         GLFramebuffer fb0;
532         glBindFramebuffer(GL_FRAMEBUFFER, fb0);
533 
534         GLRenderbuffer rb0;
535         glBindRenderbuffer(GL_RENDERBUFFER, rb0);
536         glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
537         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb0);
538         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
539 
540         // Make samples = 0 multi-sample framebuffer.
541         glBindFramebuffer(GL_FRAMEBUFFER, resources.fb);
542 
543         glBindRenderbuffer(GL_RENDERBUFFER, resources.rb);
544         glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, format, width, height);
545         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
546                                   resources.rb);
547         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
548 
549         // Draw quad to fb0.
550         glBindFramebuffer(GL_FRAMEBUFFER, fb0);
551         glViewport(0, 0, width, height);
552         glUseProgram(program);
553         GLBuffer buf;
554         glBindBuffer(GL_ARRAY_BUFFER, buf);
555 
556         constexpr float vertices[] = {
557             -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
558         };
559         glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
560         glEnableVertexAttribArray(0);
561         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
562         glDrawArrays(GL_TRIANGLES, 0, 6);
563 
564         // Blit fb0 to fb1.
565         glBindFramebuffer(GL_READ_FRAMEBUFFER, fb0);
566         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resources.fb);
567         glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT,
568                           GL_NEAREST);
569         ASSERT_GL_NO_ERROR();
570 
571         // Prep for read pixels.
572         glBindFramebuffer(GL_READ_FRAMEBUFFER, resources.fb);
573     }
574 
testResolveToUNormFBO(GLenum format,const GLColor & expected_color,GLint samples,GLint width,GLint height)575     void testResolveToUNormFBO(GLenum format,
576                                const GLColor &expected_color,
577                                GLint samples,
578                                GLint width,
579                                GLint height)
580     {
581         GLResources resources;
582         resolveToFBO(format, samples, width, height, resources);
583 
584         // Check the results
585         for (GLint y = 0; y < kHeight; ++y)
586         {
587             for (GLint x = 0; x < kWidth; ++x)
588             {
589                 EXPECT_PIXEL_COLOR_NEAR(x, y, expected_color, 2);
590             }
591         }
592         ASSERT_GL_NO_ERROR();
593     }
594 
testResolveToHalfFBO(GLenum format,const GLColor32F & expected_color,GLint samples,GLint width,GLint height)595     void testResolveToHalfFBO(GLenum format,
596                               const GLColor32F &expected_color,
597                               GLint samples,
598                               GLint width,
599                               GLint height)
600     {
601         if (!IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"))
602         {
603             return;
604         }
605 
606         GLResources resources;
607         resolveToFBO(format, samples, width, height, resources);
608 
609         // Check the results
610         for (GLint y = 0; y < kHeight; ++y)
611         {
612             for (GLint x = 0; x < kWidth; ++x)
613             {
614                 EXPECT_PIXEL_COLOR32F_NEAR(x, y, expected_color, 2.0f / 255.0f);
615             }
616         }
617         ASSERT_GL_NO_ERROR();
618     }
619 
testResolveToFloatFBO(GLenum format,const GLColor32F & expected_color,GLint samples,GLint width,GLint height)620     void testResolveToFloatFBO(GLenum format,
621                                const GLColor32F &expected_color,
622                                GLint samples,
623                                GLint width,
624                                GLint height)
625     {
626         if (!IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"))
627         {
628             return;
629         }
630 
631         GLResources resources;
632         resolveToFBO(format, samples, width, height, resources);
633 
634         // Check the results
635         for (GLint y = 0; y < kHeight; ++y)
636         {
637             for (GLint x = 0; x < kWidth; ++x)
638             {
639                 EXPECT_PIXEL_COLOR32F_NEAR(x, y, expected_color, 2.0f / 255.0f);
640             }
641         }
642         ASSERT_GL_NO_ERROR();
643     }
644 
testResolveToRGBFloatFBO(GLenum format,const GLColor32F & expected_color,GLint samples,GLint width,GLint height)645     void testResolveToRGBFloatFBO(GLenum format,
646                                   const GLColor32F &expected_color,
647                                   GLint samples,
648                                   GLint width,
649                                   GLint height)
650     {
651         if (!IsGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"))
652         {
653             return;
654         }
655 
656         GLResources resources;
657         resolveToFBO(format, samples, width, height, resources);
658 
659         // Check the results
660         for (GLint y = 0; y < kHeight; ++y)
661         {
662             for (GLint x = 0; x < kWidth; ++x)
663             {
664                 EXPECT_PIXEL_COLOR32F_NEAR(x, y, expected_color, 2.0f / 255.0f);
665             }
666         }
667         ASSERT_GL_NO_ERROR();
668     }
669 
peelDepth(GLint colorLoc)670     void peelDepth(GLint colorLoc)
671     {
672         // Draw full quads from front to back and increasing depths
673         // with depth test = less.
674         glDepthMask(GL_FALSE);
675         constexpr int steps = 64;
676         for (int i = 0; i < steps; ++i)
677         {
678             float l = float(i) / float(steps);
679             float c = l;
680             float z = c * 2.0f - 1.0f;
681             glVertexAttrib4f(1, 0, 0, z, 0);
682             glUniform4f(colorLoc, c, c, c, c);
683             glDrawArrays(GL_TRIANGLES, 0, 6);
684         }
685         glDepthMask(GL_TRUE);
686     }
687 
testResolveDepthToFBO(GLenum format,GLenum attachment,GLint samples,GLint width,GLint height)688     void testResolveDepthToFBO(GLenum format,
689                                GLenum attachment,
690                                GLint samples,
691                                GLint width,
692                                GLint height)
693     {
694         constexpr char kVS[] = R"(#version 300 es
695         layout(location = 0) in vec4 position;
696         void main() {
697            gl_Position = position;
698         }
699         )";
700 
701         constexpr char kFS[] = R"(#version 300 es
702         precision highp float;
703         out vec4 color;
704         void main() {
705            color = vec4(0.5, 0.6, 0.7, 0.8);
706         }
707         )";
708 
709         constexpr char kDepthVS[] = R"(#version 300 es
710         layout(location = 0) in vec4 position;
711         layout(location = 1) in vec4 offset;
712         void main() {
713            gl_Position = position + offset;
714         }
715         )";
716 
717         constexpr char kDepthFS[] = R"(#version 300 es
718         precision highp float;
719         uniform vec4 color;
720         out vec4 outColor;
721         void main() {
722            outColor = color;
723         }
724         )";
725 
726         ANGLE_GL_PROGRAM(program, kVS, kFS);
727         ANGLE_GL_PROGRAM(depthProgram, kDepthVS, kDepthFS);
728 
729         // Make samples = 4 multi-sample framebuffer.
730         GLFramebuffer fb0;
731         glBindFramebuffer(GL_FRAMEBUFFER, fb0);
732 
733         GLRenderbuffer rb0;
734         glBindRenderbuffer(GL_RENDERBUFFER, rb0);
735         glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA8, width, height);
736         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb0);
737 
738         GLRenderbuffer db0;
739         glBindRenderbuffer(GL_RENDERBUFFER, db0);
740         glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
741         glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, db0);
742 
743         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
744 
745         // Make samples = 0 multi-sample framebuffer.
746         GLFramebuffer fb1;
747         glBindFramebuffer(GL_FRAMEBUFFER, fb1);
748 
749         GLRenderbuffer rb1;
750         glBindRenderbuffer(GL_RENDERBUFFER, rb1);
751         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
752         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb1);
753         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
754 
755         GLRenderbuffer db1;
756         glBindRenderbuffer(GL_RENDERBUFFER, db1);
757         glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
758         glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, db1);
759 
760         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
761 
762         // Draw quad to fb0.
763         glBindFramebuffer(GL_FRAMEBUFFER, fb0);
764         glViewport(0, 0, width, height);
765         glClearColor(1, 1, 1, 1);
766         glUseProgram(program);
767 
768         GLVertexArray va0;
769         glBindVertexArray(va0);
770 
771         GLBuffer buf0;
772         glBindBuffer(GL_ARRAY_BUFFER, buf0);
773 
774         // clang-format off
775         constexpr float vertices[] = {
776             -1.0f, -1.0f, -1.0,
777              1.0f, -1.0f,  0.0,
778             -1.0f,  1.0f,  0.0,
779             -1.0f,  1.0f,  0.0,
780              1.0f, -1.0f,  0.0,
781              1.0f,  1.0f,  1.0,
782         };
783         // clang-format on
784 
785         glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
786         glEnableVertexAttribArray(0);
787         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
788         glEnable(GL_DEPTH_TEST);
789         glDepthFunc(GL_ALWAYS);
790         glDrawArrays(GL_TRIANGLES, 0, 6);
791 
792         // Blit fb0 to fb1.
793         glBindFramebuffer(GL_READ_FRAMEBUFFER, fb0);
794         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb1);
795         glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT,
796                           GL_NEAREST);
797         ASSERT_GL_NO_ERROR();
798 
799         GLVertexArray va1;
800         glBindVertexArray(va1);
801 
802         // clang-format off
803         constexpr float depthVertices[] = {
804             -1.0f, -1.0f,
805              1.0f, -1.0f,
806             -1.0f,  1.0f,
807             -1.0f,  1.0f,
808              1.0f, -1.0f,
809              1.0f,  1.0f,
810         };
811         // clang-format on
812 
813         GLBuffer buf1;
814         glBindBuffer(GL_ARRAY_BUFFER, buf1);
815         glBufferData(GL_ARRAY_BUFFER, sizeof(depthVertices), depthVertices, GL_STATIC_DRAW);
816         glEnableVertexAttribArray(0);
817         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
818 
819         glUseProgram(depthProgram);
820         GLint colorLoc = glGetUniformLocation(depthProgram, "color");
821 
822         // Extract the depth results.
823         glBindFramebuffer(GL_FRAMEBUFFER, fb1);
824         glClear(GL_COLOR_BUFFER_BIT);
825         glDepthFunc(GL_LESS);
826         peelDepth(colorLoc);
827         std::vector<GLColor> actual(width * height);
828         glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, actual.data());
829 
830         // Render what should be a similar result to the non-multi-sampled fb
831         glBindVertexArray(va0);
832         glDepthFunc(GL_ALWAYS);
833         glUseProgram(program);
834         glDrawArrays(GL_TRIANGLES, 0, 6);
835 
836         // Extract the expected depth results.
837         glBindVertexArray(va1);
838         glUseProgram(depthProgram);
839         glClear(GL_COLOR_BUFFER_BIT);
840         glDepthFunc(GL_LESS);
841         peelDepth(colorLoc);
842         std::vector<GLColor> expected(width * height);
843         glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, expected.data());
844 
845         for (size_t i = 0; i < expected.size(); ++i)
846         {
847             EXPECT_NEAR(expected[i].R, actual[i].R, 8)
848                 << "at " << (i % width) << "," << (i / width);
849         }
850 
851         // Verify we read the depth buffer.
852         const GLint minDimension = std::min(width, height);
853         for (GLint i = 1; i < minDimension; ++i)
854         {
855             const GLColor &c1 = expected[i - 1];
856             const GLColor &c2 = expected[i * width + i];
857             EXPECT_LT(c1.R, c2.R);
858         }
859         ASSERT_GL_NO_ERROR();
860     }
861 };
862 
863 // Test the multisampled optimized resolve subpass
TEST_P(MultisampleResolveTest,DISABLED_ResolveSubpassMSImage)864 TEST_P(MultisampleResolveTest, DISABLED_ResolveSubpassMSImage)
865 {
866     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
867 
868     // Draw green.
869     drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);
870     swapBuffers();
871 
872     // Wait for visual verification.
873     angle::Sleep(2000);
874 }
875 
876 // This is a test that must be verified visually.
877 //
878 // Tests that clear of the default framebuffer with multisample applies to the window.
TEST_P(MultisampleTestES3,DISABLED_ClearMSAAReachesWindow)879 TEST_P(MultisampleTestES3, DISABLED_ClearMSAAReachesWindow)
880 {
881     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
882 
883     // Draw blue.
884     drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
885     swapBuffers();
886 
887     // Use glClear to clear to red.  Regression test for the Vulkan backend where this clear
888     // remained "deferred" and didn't make it to the window on swap.
889     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
890     glClear(GL_COLOR_BUFFER_BIT);
891     swapBuffers();
892 
893     // Wait for visual verification.
894     angle::Sleep(2000);
895 }
896 
897 // According to the spec, the minimum value for the multisample line width range limits is one.
TEST_P(MultisampleTestES32,MultisampleLineWidthRangeCheck)898 TEST_P(MultisampleTestES32, MultisampleLineWidthRangeCheck)
899 {
900     GLfloat range[2] = {0, 0};
901     glGetFloatv(GL_MULTISAMPLE_LINE_WIDTH_RANGE, range);
902     EXPECT_GL_NO_ERROR();
903     EXPECT_GE(range[0], 1.0f);
904     EXPECT_GE(range[1], 1.0f);
905 }
906 
907 // The multisample line width granularity should not be negative.
TEST_P(MultisampleTestES32,MultisampleLineWidthGranularityCheck)908 TEST_P(MultisampleTestES32, MultisampleLineWidthGranularityCheck)
909 {
910     GLfloat granularity = -1.0f;
911     glGetFloatv(GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY, &granularity);
912     EXPECT_GL_NO_ERROR();
913     EXPECT_GE(granularity, 0.0f);
914 }
915 
916 // These colors match the shader in resolveToFBO which returns (0.5, 0.6, 0.7, 0.8).
917 const GLColor MultisampleResolveTest::kEXPECTED_R8(128, 0, 0, 255);
918 const GLColor MultisampleResolveTest::kEXPECTED_RG8(128, 153, 0, 255);
919 const GLColor MultisampleResolveTest::kEXPECTED_RGB8(128, 153, 178, 255);
920 const GLColor MultisampleResolveTest::kEXPECTED_RGBA8(128, 153, 178, 204);
921 const GLColor32F MultisampleResolveTest::kEXPECTED_RF(0.5f, 0.0f, 0.0f, 1.0f);
922 const GLColor32F MultisampleResolveTest::kEXPECTED_RGF(0.5f, 0.6f, 0.0f, 1.0f);
923 const GLColor32F MultisampleResolveTest::kEXPECTED_RGBF(0.5f, 0.6f, 0.7f, 1.0f);
924 const GLColor32F MultisampleResolveTest::kEXPECTED_RGBAF(0.5f, 0.6f, 0.7f, 0.8f);
925 
926 // Test we can render to and resolve an RGBA8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGBA8ToFBO4Samples)927 TEST_P(MultisampleResolveTest, ResolveRGBA8ToFBO4Samples)
928 {
929     testResolveToUNormFBO(GL_RGBA8, kEXPECTED_RGBA8, 4, kWidth, kHeight);
930 }
931 
932 // Test we can render to and resolve an RGB8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGB8ToFBO4Samples)933 TEST_P(MultisampleResolveTest, ResolveRGB8ToFBO4Samples)
934 {
935     testResolveToUNormFBO(GL_RGB8, kEXPECTED_RGB8, 4, kWidth, kHeight);
936 }
937 
938 // Test we can render to and resolve an RG8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveRG8ToFBO4Samples)939 TEST_P(MultisampleResolveTest, ResolveRG8ToFBO4Samples)
940 {
941     testResolveToUNormFBO(GL_RG8, kEXPECTED_RG8, 4, kWidth, kHeight);
942 }
943 
944 // Test we can render to and resolve an R8 renderbuffer
TEST_P(MultisampleResolveTest,ResolveR8ToFBO4Samples)945 TEST_P(MultisampleResolveTest, ResolveR8ToFBO4Samples)
946 {
947     testResolveToUNormFBO(GL_R8, kEXPECTED_R8, 4, kWidth, kHeight);
948 }
949 
950 // Test we can render to and resolve an R16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveR16FToFBO4Samples)951 TEST_P(MultisampleResolveTest, ResolveR16FToFBO4Samples)
952 {
953     testResolveToHalfFBO(GL_R16F, kEXPECTED_RF, 4, kWidth, kHeight);
954 }
955 
956 // Test we can render to and resolve an RG16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRG16FToFBO4Samples)957 TEST_P(MultisampleResolveTest, ResolveRG16FToFBO4Samples)
958 {
959     testResolveToHalfFBO(GL_RG16F, kEXPECTED_RGF, 4, kWidth, kHeight);
960 }
961 
962 // Test we can render to and resolve an RGB16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGB16FToFBO4Samples)963 TEST_P(MultisampleResolveTest, ResolveRGB16FToFBO4Samples)
964 {
965     testResolveToHalfFBO(GL_RGB16F, kEXPECTED_RGBF, 4, kWidth, kHeight);
966 }
967 
968 // Test we can render to and resolve an RGBA16F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGBA16FToFBO4Samples)969 TEST_P(MultisampleResolveTest, ResolveRGBA16FToFBO4Samples)
970 {
971     testResolveToHalfFBO(GL_RGBA16F, kEXPECTED_RGBAF, 4, kWidth, kHeight);
972 }
973 
974 // Test we can render to and resolve an R32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveR32FToFBO4Samples)975 TEST_P(MultisampleResolveTest, ResolveR32FToFBO4Samples)
976 {
977     testResolveToFloatFBO(GL_R32F, kEXPECTED_RF, 4, kWidth, kHeight);
978 }
979 
980 // Test we can render to and resolve an RG32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRG32FToFBO4Samples)981 TEST_P(MultisampleResolveTest, ResolveRG32FToFBO4Samples)
982 {
983     testResolveToFloatFBO(GL_RG32F, kEXPECTED_RGF, 4, kWidth, kHeight);
984 }
985 
986 // Test we can render to and resolve an RGB32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGB32FToFBO4Samples)987 TEST_P(MultisampleResolveTest, ResolveRGB32FToFBO4Samples)
988 {
989     testResolveToRGBFloatFBO(GL_RGB32F, kEXPECTED_RGBF, 4, kWidth, kHeight);
990 }
991 
992 // Test we can render to and resolve an RGBA32F renderbuffer
TEST_P(MultisampleResolveTest,ResolveRGBA32FToFBO4Samples)993 TEST_P(MultisampleResolveTest, ResolveRGBA32FToFBO4Samples)
994 {
995     testResolveToFloatFBO(GL_RGBA32F, kEXPECTED_RGBAF, 4, kWidth, kHeight);
996 }
997 
TEST_P(MultisampleResolveTest,ResolveD32FS8F4Samples)998 TEST_P(MultisampleResolveTest, ResolveD32FS8F4Samples)
999 {
1000     testResolveDepthToFBO(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, 4, kWidth, kHeight);
1001 }
1002 
TEST_P(MultisampleResolveTest,ResolveD24S8Samples)1003 TEST_P(MultisampleResolveTest, ResolveD24S8Samples)
1004 {
1005     testResolveDepthToFBO(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, 4, kWidth, kHeight);
1006 }
1007 
TEST_P(MultisampleResolveTest,ResolveD32FSamples)1008 TEST_P(MultisampleResolveTest, ResolveD32FSamples)
1009 {
1010     testResolveDepthToFBO(GL_DEPTH_COMPONENT32F, GL_DEPTH_ATTACHMENT, 4, kWidth, kHeight);
1011 }
1012 
TEST_P(MultisampleResolveTest,ResolveD24Samples)1013 TEST_P(MultisampleResolveTest, ResolveD24Samples)
1014 {
1015     testResolveDepthToFBO(GL_DEPTH_COMPONENT24, GL_DEPTH_ATTACHMENT, 4, kWidth, kHeight);
1016 }
1017 
TEST_P(MultisampleResolveTest,ResolveD16Samples)1018 TEST_P(MultisampleResolveTest, ResolveD16Samples)
1019 {
1020     testResolveDepthToFBO(GL_DEPTH_COMPONENT16, GL_DEPTH_ATTACHMENT, 4, kWidth, kHeight);
1021 }
1022 
drawRectAndBlit(GLuint msFramebuffer,GLuint resolveFramebuffer,GLint width,GLint height,GLint matLoc,GLint colorLoc,float x,float y,float w,float h,const GLColor & color)1023 void drawRectAndBlit(GLuint msFramebuffer,
1024                      GLuint resolveFramebuffer,
1025                      GLint width,
1026                      GLint height,
1027                      GLint matLoc,
1028                      GLint colorLoc,
1029                      float x,
1030                      float y,
1031                      float w,
1032                      float h,
1033                      const GLColor &color)
1034 {
1035     glBindFramebuffer(GL_FRAMEBUFFER, msFramebuffer);
1036     float matrix[16] = {
1037         w, 0, 0, 0, 0, h, 0, 0, 0, 0, 1, 0, x, y, 0, 1,
1038     };
1039     glUniformMatrix4fv(matLoc, 1, false, matrix);
1040     angle::Vector4 c(color.toNormalizedVector());
1041     glUniform4f(colorLoc, c[0], c[1], c[2], c[3]);
1042     glDrawArrays(GL_TRIANGLES, 0, 6);
1043 
1044     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFramebuffer);
1045     glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1046 }
1047 
1048 // Tests if we resolve(blit) a multisample renderbuffer that it
1049 // does not lose its contents.
TEST_P(MultisampleResolveTest,DrawAndResolveMultipleTimes)1050 TEST_P(MultisampleResolveTest, DrawAndResolveMultipleTimes)
1051 {
1052     constexpr GLint samples = 4;
1053     constexpr GLenum format = GL_RGBA8;
1054     constexpr GLint width   = 16;
1055     constexpr GLint height  = 16;
1056 
1057     constexpr char kVS[] = R"(#version 300 es
1058     layout(location = 0) in vec4 position;
1059     uniform mat4 mat;
1060     void main() {
1061        gl_Position = mat * position;
1062     }
1063     )";
1064 
1065     constexpr char kFS[] = R"(#version 300 es
1066     precision highp float;
1067     uniform vec4 color;
1068     out vec4 outColor;
1069     void main() {
1070        outColor = color;
1071     }
1072     )";
1073 
1074     glViewport(0, 0, width, height);
1075 
1076     ANGLE_GL_PROGRAM(program, kVS, kFS);
1077     GLint matLoc   = glGetUniformLocation(program, "mat");
1078     GLint colorLoc = glGetUniformLocation(program, "color");
1079     glUseProgram(program);
1080 
1081     GLBuffer buf;
1082     glBindBuffer(GL_ARRAY_BUFFER, buf);
1083 
1084     constexpr float vertices[] = {
1085         0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1086     };
1087     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
1088     glEnableVertexAttribArray(0);
1089     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
1090 
1091     // Make samples = 4 multi-sample framebuffer.
1092     GLFramebuffer msFB;
1093     glBindFramebuffer(GL_FRAMEBUFFER, msFB);
1094 
1095     GLRenderbuffer msRB;
1096     glBindRenderbuffer(GL_RENDERBUFFER, msRB);
1097     glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, format, width, height);
1098     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msRB);
1099     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1100 
1101     // Make non-multi-sample framebuffer.
1102     GLFramebuffer drawFB;
1103     glBindFramebuffer(GL_FRAMEBUFFER, drawFB);
1104 
1105     GLRenderbuffer drawRB;
1106     glBindRenderbuffer(GL_RENDERBUFFER, drawRB);
1107     glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
1108     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, drawRB);
1109     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1110 
1111     drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, -1, -1, 2, 2, GLColor::red);
1112     drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, 0, -1, 1, 1, GLColor::green);
1113     drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, -1, 0, 1, 1, GLColor::blue);
1114     drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, 0, 0, 1, 1, GLColor::yellow);
1115     glEnable(GL_BLEND);
1116     glBlendFunc(GL_ONE, GL_ONE);
1117     drawRectAndBlit(msFB, drawFB, width, height, matLoc, colorLoc, -0.5, -0.5, 1, 1,
1118                     GLColor(0x80, 0x80, 0x80, 0x80));
1119     glDisable(GL_BLEND);
1120     ASSERT_GL_NO_ERROR();
1121 
1122     /*
1123        expected
1124        +-------------+--------------+
1125        | blue        |       yellow |
1126        |   +---------+----------+   |
1127        |   |.5,.5,1,1| 1,1,.5,1 |   |
1128        +---+---------+----------+---+
1129        |   |1,.5,.5,1| .5,1,.5,1|   |
1130        |   +---------+----------+   |
1131        | red         |        green |
1132        +-------------+--------------+
1133       0,0
1134     */
1135 
1136     glBindFramebuffer(GL_FRAMEBUFFER, drawFB);
1137     EXPECT_PIXEL_RECT_EQ(0, 0, width / 2, height / 4, GLColor::red);
1138     EXPECT_PIXEL_RECT_EQ(width / 2, 0, width / 2, height / 4, GLColor::green);
1139     EXPECT_PIXEL_RECT_EQ(0, height * 3 / 4, width / 2, height / 4, GLColor::blue);
1140     EXPECT_PIXEL_RECT_EQ(width / 2, height * 3 / 4, width / 2, height / 4, GLColor::yellow);
1141 
1142     EXPECT_PIXEL_RECT_EQ(width / 4, height / 4, width / 4, height / 4, GLColor(255, 128, 128, 255));
1143     EXPECT_PIXEL_RECT_EQ(width / 2, height / 4, width / 4, height / 4, GLColor(128, 255, 128, 255));
1144     EXPECT_PIXEL_RECT_EQ(width / 4, height / 2, width / 4, height / 4, GLColor(128, 128, 255, 255));
1145     EXPECT_PIXEL_RECT_EQ(width / 2, height / 2, width / 4, height / 4, GLColor(255, 255, 128, 255));
1146 }
1147 
1148 // Tests resolve after the read framebuffer's attachment has been swapped out.
TEST_P(MultisampleResolveTest,SwitchAttachmentsBeforeResolve)1149 TEST_P(MultisampleResolveTest, SwitchAttachmentsBeforeResolve)
1150 {
1151     constexpr GLuint kWidth  = 16;
1152     constexpr GLuint kHeight = 24;
1153 
1154     GLRenderbuffer msaaColor0, msaaColor1;
1155     glBindRenderbuffer(GL_RENDERBUFFER, msaaColor0);
1156     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, kWidth, kHeight);
1157     glBindRenderbuffer(GL_RENDERBUFFER, msaaColor1);
1158     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, kWidth, kHeight);
1159 
1160     {
1161         // First, make one of the MSAA color buffers green.
1162         GLFramebuffer clearFbo;
1163         glBindFramebuffer(GL_FRAMEBUFFER, clearFbo);
1164         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1165                                   msaaColor1);
1166         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1167 
1168         glClearColor(0, 1, 0, 1);
1169         glClear(GL_COLOR_BUFFER_BIT);
1170 
1171         // Make sure clear is performed.
1172         GLTexture resolveTexture;
1173         glBindTexture(GL_TEXTURE_2D, resolveTexture);
1174         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1175                      nullptr);
1176 
1177         GLFramebuffer verifyFBO;
1178         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, verifyFBO);
1179         glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1180                                resolveTexture, 0);
1181 
1182         glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
1183                           GL_NEAREST);
1184 
1185         glBindFramebuffer(GL_READ_FRAMEBUFFER, verifyFBO);
1186         EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
1187     }
1188 
1189     // Set up the msaa framebuffer with the other MSAA color buffer.
1190     GLFramebuffer msaaFBO;
1191     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
1192     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaaColor0);
1193     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1194 
1195     // Draw into it to start a render pass
1196     ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1197     drawQuad(red, essl1_shaders::PositionAttrib(), 0.5f);
1198 
1199     // Set up the resolve framebuffer
1200     GLRenderbuffer resolveColor;
1201     glBindRenderbuffer(GL_RENDERBUFFER, resolveColor);
1202     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
1203 
1204     GLFramebuffer resolveFBO;
1205     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1206     glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1207                               resolveColor);
1208     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1209 
1210     // Before resolve the MSAA framebuffer, switch its attachment.  Regression test for a bug where
1211     // the resolve used the previous attachment.
1212     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1213                               msaaColor1);
1214 
1215     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
1216                       GL_NEAREST);
1217 
1218     // Verify that the resolve happened on the pre-cleared attachment, not the rendered one.
1219     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1220     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
1221 }
1222 
1223 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31_AND(
1224     MultisampleTest,
1225     ES3_VULKAN().enable(Feature::EmulatedPrerotation90),
1226     ES3_VULKAN().enable(Feature::EmulatedPrerotation180),
1227     ES3_VULKAN().enable(Feature::EmulatedPrerotation270),
1228     // Simulate missing msaa auto resolve feature in Metal.
1229     ES2_METAL().disable(Feature::AllowMultisampleStoreAndResolve));
1230 
1231 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultisampleTestES3);
1232 ANGLE_INSTANTIATE_TEST_ES3_AND_ES31_AND(MultisampleTestES3,
1233                                         ES3_VULKAN().enable(Feature::EmulatedPrerotation90),
1234                                         ES3_VULKAN().enable(Feature::EmulatedPrerotation180),
1235                                         ES3_VULKAN().enable(Feature::EmulatedPrerotation270));
1236 
1237 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultisampleTestES32);
1238 ANGLE_INSTANTIATE_TEST_ES32_AND(MultisampleTestES32,
1239                                 ES32_VULKAN().enable(Feature::EmulatedPrerotation90),
1240                                 ES32_VULKAN().enable(Feature::EmulatedPrerotation180),
1241                                 ES32_VULKAN().enable(Feature::EmulatedPrerotation270));
1242 
1243 ANGLE_INSTANTIATE_TEST_ES3_AND(
1244     MultisampleResolveTest,
1245     ES3_VULKAN().enable(Feature::EmulatedPrerotation90),
1246     ES3_VULKAN().enable(Feature::EmulatedPrerotation180),
1247     ES3_VULKAN().enable(Feature::EmulatedPrerotation270),
1248     ES3_VULKAN().enable(Feature::PreferDrawClearOverVkCmdClearAttachments));
1249 
1250 }  // anonymous namespace
1251