• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // Framebuffer tests:
7 //   Various tests related for Frambuffers.
8 //
9 
10 #include "common/mathutil.h"
11 #include "platform/autogen/FeaturesD3D_autogen.h"
12 #include "test_utils/ANGLETest.h"
13 #include "test_utils/gl_raii.h"
14 #include "util/OSWindow.h"
15 
16 using namespace angle;
17 
18 namespace
19 {
20 
ExpectFramebufferCompleteOrUnsupported(GLenum binding)21 void ExpectFramebufferCompleteOrUnsupported(GLenum binding)
22 {
23     GLenum status = glCheckFramebufferStatus(binding);
24     EXPECT_TRUE(status == GL_FRAMEBUFFER_COMPLETE || status == GL_FRAMEBUFFER_UNSUPPORTED);
25 }
26 
27 }  // anonymous namespace
28 
29 class FramebufferFormatsTest : public ANGLETest<>
30 {
31   protected:
FramebufferFormatsTest()32     FramebufferFormatsTest() : mFramebuffer(0), mTexture(0), mRenderbuffer(0), mProgram(0)
33     {
34         setWindowWidth(128);
35         setWindowHeight(128);
36         setConfigRedBits(8);
37         setConfigGreenBits(8);
38         setConfigBlueBits(8);
39         setConfigAlphaBits(8);
40     }
41 
checkBitCount(GLuint fbo,GLenum channel,GLint minBits)42     void checkBitCount(GLuint fbo, GLenum channel, GLint minBits)
43     {
44         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
45 
46         GLint bits = 0;
47         glGetIntegerv(channel, &bits);
48 
49         if (minBits == 0)
50         {
51             EXPECT_EQ(minBits, bits);
52         }
53         else
54         {
55             EXPECT_GE(bits, minBits);
56         }
57     }
58 
testBitCounts(GLuint fbo,GLint minRedBits,GLint minGreenBits,GLint minBlueBits,GLint minAlphaBits,GLint minDepthBits,GLint minStencilBits)59     void testBitCounts(GLuint fbo,
60                        GLint minRedBits,
61                        GLint minGreenBits,
62                        GLint minBlueBits,
63                        GLint minAlphaBits,
64                        GLint minDepthBits,
65                        GLint minStencilBits)
66     {
67         checkBitCount(fbo, GL_RED_BITS, minRedBits);
68         checkBitCount(fbo, GL_GREEN_BITS, minGreenBits);
69         checkBitCount(fbo, GL_BLUE_BITS, minBlueBits);
70         checkBitCount(fbo, GL_ALPHA_BITS, minAlphaBits);
71         checkBitCount(fbo, GL_DEPTH_BITS, minDepthBits);
72         checkBitCount(fbo, GL_STENCIL_BITS, minStencilBits);
73     }
74 
testTextureFormat(GLenum internalFormat,GLint minRedBits,GLint minGreenBits,GLint minBlueBits,GLint minAlphaBits)75     void testTextureFormat(GLenum internalFormat,
76                            GLint minRedBits,
77                            GLint minGreenBits,
78                            GLint minBlueBits,
79                            GLint minAlphaBits)
80     {
81         glGenTextures(1, &mTexture);
82         glBindTexture(GL_TEXTURE_2D, mTexture);
83 
84         if (getClientMajorVersion() >= 3)
85         {
86             glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
87         }
88         else
89         {
90             glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
91         }
92 
93         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
94 
95         testBitCounts(mFramebuffer, minRedBits, minGreenBits, minBlueBits, minAlphaBits, 0, 0);
96     }
97 
testRenderbufferMultisampleFormat(int minESVersion,GLenum attachmentType,GLenum internalFormat)98     void testRenderbufferMultisampleFormat(int minESVersion,
99                                            GLenum attachmentType,
100                                            GLenum internalFormat)
101     {
102         int clientVersion = getClientMajorVersion();
103         if (clientVersion < minESVersion)
104         {
105             return;
106         }
107 
108         // Check that multisample is supported with at least two samples (minimum required is 1)
109         bool supports2Samples = false;
110 
111         if (clientVersion == 2)
112         {
113             if (IsGLExtensionEnabled("ANGLE_framebuffer_multisample"))
114             {
115                 int maxSamples;
116                 glGetIntegerv(GL_MAX_SAMPLES_ANGLE, &maxSamples);
117                 supports2Samples = maxSamples >= 2;
118             }
119         }
120         else
121         {
122             assert(clientVersion >= 3);
123             int maxSamples;
124             glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
125             supports2Samples = maxSamples >= 2;
126         }
127 
128         if (!supports2Samples)
129         {
130             return;
131         }
132 
133         glGenRenderbuffers(1, &mRenderbuffer);
134         glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
135 
136         EXPECT_GL_NO_ERROR();
137         glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, internalFormat, 128, 128);
138         EXPECT_GL_NO_ERROR();
139         glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentType, GL_RENDERBUFFER, mRenderbuffer);
140         EXPECT_GL_NO_ERROR();
141     }
142 
testZeroHeightRenderbuffer()143     void testZeroHeightRenderbuffer()
144     {
145         glGenRenderbuffers(1, &mRenderbuffer);
146         glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
147         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 0);
148         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
149                                   mRenderbuffer);
150         EXPECT_GL_NO_ERROR();
151     }
152 
testSetUp()153     void testSetUp() override
154     {
155         glGenFramebuffers(1, &mFramebuffer);
156         glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
157     }
158 
testTearDown()159     void testTearDown() override
160     {
161         if (mTexture != 0)
162         {
163             glDeleteTextures(1, &mTexture);
164             mTexture = 0;
165         }
166 
167         if (mRenderbuffer != 0)
168         {
169             glDeleteRenderbuffers(1, &mRenderbuffer);
170             mRenderbuffer = 0;
171         }
172 
173         if (mFramebuffer != 0)
174         {
175             glDeleteFramebuffers(1, &mFramebuffer);
176             mFramebuffer = 0;
177         }
178 
179         if (mProgram != 0)
180         {
181             glDeleteProgram(mProgram);
182             mProgram = 0;
183         }
184     }
185 
186     GLuint mFramebuffer;
187     GLuint mTexture;
188     GLuint mRenderbuffer;
189     GLuint mProgram;
190 };
191 
TEST_P(FramebufferFormatsTest,RGBA4)192 TEST_P(FramebufferFormatsTest, RGBA4)
193 {
194     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
195                        !IsGLExtensionEnabled("GL_EXT_texture_storage"));
196 
197     testTextureFormat(GL_RGBA4, 4, 4, 4, 4);
198 }
199 
TEST_P(FramebufferFormatsTest,RGB565)200 TEST_P(FramebufferFormatsTest, RGB565)
201 {
202     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
203                        !IsGLExtensionEnabled("GL_EXT_texture_storage"));
204 
205     testTextureFormat(GL_RGB565, 5, 6, 5, 0);
206 }
207 
TEST_P(FramebufferFormatsTest,RGB8)208 TEST_P(FramebufferFormatsTest, RGB8)
209 {
210     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
211                        (!IsGLExtensionEnabled("GL_OES_rgb8_rgba8") ||
212                         !IsGLExtensionEnabled("GL_EXT_texture_storage")));
213 
214     testTextureFormat(GL_RGB8_OES, 8, 8, 8, 0);
215 }
216 
TEST_P(FramebufferFormatsTest,BGRA8)217 TEST_P(FramebufferFormatsTest, BGRA8)
218 {
219     ANGLE_SKIP_TEST_IF(
220         !IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888") ||
221         (getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_texture_storage")));
222 
223     testTextureFormat(GL_BGRA8_EXT, 8, 8, 8, 8);
224 }
225 
TEST_P(FramebufferFormatsTest,RGBA8)226 TEST_P(FramebufferFormatsTest, RGBA8)
227 {
228     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
229                        (!IsGLExtensionEnabled("GL_OES_rgb8_rgba8") ||
230                         !IsGLExtensionEnabled("GL_EXT_texture_storage")));
231 
232     testTextureFormat(GL_RGBA8_OES, 8, 8, 8, 8);
233 }
234 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH16)235 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH16)
236 {
237     testRenderbufferMultisampleFormat(2, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16);
238 }
239 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH24)240 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24)
241 {
242     testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24);
243 }
244 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH32F)245 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F)
246 {
247     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
248 
249     testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT32F);
250 }
251 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH24_STENCIL8)252 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24_STENCIL8)
253 {
254     testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH24_STENCIL8);
255 }
256 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH32F_STENCIL8)257 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F_STENCIL8)
258 {
259     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
260 
261     testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH32F_STENCIL8);
262 }
263 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_STENCIL_INDEX8)264 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_STENCIL_INDEX8)
265 {
266     // TODO(geofflang): Figure out how to support GLSTENCIL_INDEX8 on desktop GL
267     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
268 
269     testRenderbufferMultisampleFormat(2, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8);
270 }
271 
272 // Test that binding an incomplete cube map is rejected by ANGLE.
TEST_P(FramebufferFormatsTest,IncompleteCubeMap)273 TEST_P(FramebufferFormatsTest, IncompleteCubeMap)
274 {
275     // http://anglebug.com/3145
276     ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
277 
278     // First make a complete CubeMap.
279     glGenTextures(1, &mTexture);
280     glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
281     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
282                  nullptr);
283     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
284                  nullptr);
285     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
286                  nullptr);
287     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
288                  nullptr);
289     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
290                  nullptr);
291     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
292                  nullptr);
293     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
294     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
295 
296     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
297                            mTexture, 0);
298 
299     // Verify the framebuffer is complete.
300     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
301 
302     // Make the CubeMap cube-incomplete.
303     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
304                  nullptr);
305 
306     // Verify the framebuffer is incomplete.
307     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
308                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
309 
310     ASSERT_GL_NO_ERROR();
311 
312     // Verify drawing with the incomplete framebuffer produces a GL error
313     mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
314     ASSERT_NE(0u, mProgram);
315     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
316     ASSERT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
317 }
318 
319 // Test that a renderbuffer with zero height but nonzero width is handled without crashes/asserts.
TEST_P(FramebufferFormatsTest,ZeroHeightRenderbuffer)320 TEST_P(FramebufferFormatsTest, ZeroHeightRenderbuffer)
321 {
322     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
323 
324     testZeroHeightRenderbuffer();
325 }
326 
327 // Test to cover a bug where the read framebuffer affects the completeness of the draw framebuffer.
TEST_P(FramebufferFormatsTest,ReadDrawCompleteness)328 TEST_P(FramebufferFormatsTest, ReadDrawCompleteness)
329 {
330     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
331 
332     GLTexture incompleteTexture;
333     glBindTexture(GL_TEXTURE_2D, incompleteTexture);
334 
335     GLFramebuffer incompleteFBO;
336     glBindFramebuffer(GL_FRAMEBUFFER, incompleteFBO);
337     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, incompleteTexture,
338                            0);
339     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
340                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
341 
342     GLTexture completeTexture;
343     glBindTexture(GL_TEXTURE_2D, completeTexture);
344     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
345 
346     GLFramebuffer completeFBO;
347     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, completeFBO);
348     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
349                            completeTexture, 0);
350 
351     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
352                      glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
353     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
354 
355     ASSERT_GL_NO_ERROR();
356 
357     // Simple draw program.
358     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
359 
360     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
361     EXPECT_GL_NO_ERROR();
362 
363     glBindFramebuffer(GL_READ_FRAMEBUFFER, completeFBO);
364     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
365 }
366 
367 // Test that a renderbuffer with RGB565 format works as expected. This test is intended for some
368 // back-end having no support for native RGB565 renderbuffer and thus having to emulate using RGBA
369 // format.
TEST_P(FramebufferFormatsTest,RGB565Renderbuffer)370 TEST_P(FramebufferFormatsTest, RGB565Renderbuffer)
371 {
372     GLRenderbuffer rbo;
373     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
374     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB565, 1, 1);
375 
376     GLFramebuffer completeFBO;
377     glBindFramebuffer(GL_FRAMEBUFFER, completeFBO);
378     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
379 
380     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
381 
382     ASSERT_GL_NO_ERROR();
383 
384     glClearColor(1, 0, 0, 0.5f);
385     glClear(GL_COLOR_BUFFER_BIT);
386     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
387 }
388 
389 class FramebufferTest_ES3 : public ANGLETest<>
390 {
391   protected:
FramebufferTest_ES3()392     FramebufferTest_ES3()
393     {
394         setWindowWidth(kWidth);
395         setWindowHeight(kHeight);
396         setConfigRedBits(8);
397         setConfigGreenBits(8);
398         setConfigBlueBits(8);
399         setConfigAlphaBits(8);
400         setConfigDepthBits(24);
401         setConfigStencilBits(8);
402     }
403 
404     static constexpr GLsizei kWidth  = 64;
405     static constexpr GLsizei kHeight = 256;
406 };
407 
408 // Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error.
TEST_P(FramebufferTest_ES3,InvalidateIncomplete)409 TEST_P(FramebufferTest_ES3, InvalidateIncomplete)
410 {
411     GLFramebuffer framebuffer;
412     GLRenderbuffer renderbuffer;
413 
414     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
415     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
416     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
417     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
418                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
419 
420     std::vector<GLenum> attachments;
421     attachments.push_back(GL_COLOR_ATTACHMENT0);
422 
423     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
424     EXPECT_GL_NO_ERROR();
425 }
426 
427 // Covers sub-invalidating an incomplete framebuffer. This should be a no-op, but should not error.
TEST_P(FramebufferTest_ES3,SubInvalidateIncomplete)428 TEST_P(FramebufferTest_ES3, SubInvalidateIncomplete)
429 {
430     GLFramebuffer framebuffer;
431     GLRenderbuffer renderbuffer;
432 
433     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
434     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
435     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
436     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
437                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
438 
439     std::vector<GLenum> attachments;
440     attachments.push_back(GL_COLOR_ATTACHMENT0);
441 
442     glInvalidateSubFramebuffer(GL_FRAMEBUFFER, 1, attachments.data(), 5, 5, 10, 10);
443     EXPECT_GL_NO_ERROR();
444 }
445 
446 enum class DisableDitherVsClear
447 {
448     Before,
449     After
450 };
451 
testDitherDisabledProperlyOnRGB565(GLColor gradientColor,DisableDitherVsClear disableDitherVsClear)452 void testDitherDisabledProperlyOnRGB565(GLColor gradientColor,
453                                         DisableDitherVsClear disableDitherVsClear)
454 {
455     GLFramebuffer framebuffer;
456 
457     constexpr GLsizei kFramebufferWidth  = 4;
458     constexpr GLsizei kFramebufferHeight = 4;
459     GLTexture texture;
460     glBindTexture(GL_TEXTURE_2D, texture);
461     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB565, kFramebufferWidth, kFramebufferHeight);
462 
463     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
464     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
465 
466     constexpr char kVS[] = {
467         R"(#version 300 es
468         in highp vec4 a_position;
469         in mediump vec4 a_color;
470         out mediump vec4 v_color;
471         void main()
472         {
473         gl_Position = a_position;
474         v_color = a_color;
475         })",
476     };
477 
478     constexpr char kFS[] = {
479         R"(#version 300 es
480             in mediump vec4 v_color;
481             layout(location = 0) out mediump vec4 o_color;
482             void main()
483             {
484                 o_color = v_color;
485             })",
486     };
487 
488     ANGLE_GL_PROGRAM(program, kVS, kFS);
489 
490     glUseProgram(program);
491 
492     // setup quad data
493     // black ----> gradientColor
494     // **********
495     // *        *
496     // *        *
497     // **********
498     const std::vector<float> positions = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
499                                           1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f};
500 
501     const std::vector<float> color0 = {0.0f,
502                                        0.0f,
503                                        0.0f,
504                                        0.0f,
505                                        0.0f,
506                                        0.0f,
507                                        0.0f,
508                                        0.0f,
509                                        gradientColor.R * 1.0f / 255.0f,
510                                        gradientColor.G * 1.0f / 255.0f,
511                                        gradientColor.B * 1.0f / 255.0f,
512                                        gradientColor.A * 1.0f / 255.0f,
513                                        gradientColor.R * 1.0f / 255.0f,
514                                        gradientColor.G * 1.0f / 255.0f,
515                                        gradientColor.B * 1.0f / 255.0f,
516                                        gradientColor.A * 1.0f / 255.0f};
517 
518     GLBuffer vertexBuffer;
519     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
520     glBufferData(GL_ARRAY_BUFFER, sizeof(positions[0]) * positions.size(), positions.data(),
521                  GL_STATIC_DRAW);
522 
523     GLBuffer colorBuffer;
524     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
525     glBufferData(GL_ARRAY_BUFFER, sizeof(color0[0]) * color0.size(), color0.data(), GL_STATIC_DRAW);
526 
527     GLint vertexPosLocation = glGetAttribLocation(program, "a_position");
528     ASSERT_NE(vertexPosLocation, -1);
529     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
530     glEnableVertexAttribArray(vertexPosLocation);
531     glVertexAttribPointer(vertexPosLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
532 
533     GLint vertexColorLocation = glGetAttribLocation(program, "a_color");
534     ASSERT_NE(vertexColorLocation, -1);
535     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
536     glEnableVertexAttribArray(vertexColorLocation);
537     glVertexAttribPointer(vertexColorLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
538 
539     const std::vector<uint8_t> indices = {0, 2, 1, 1, 2, 3};
540 
541     GLBuffer indexBuffer;
542     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
543     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * indices.size(), indices.data(),
544                  GL_STATIC_DRAW);
545     ASSERT_GL_NO_ERROR();
546 
547     switch (disableDitherVsClear)
548     {
549         case DisableDitherVsClear::Before:
550             glDisable(GL_DITHER);
551             glClearColor(0.125, 0.25, 0.5, 1);
552             glClear(GL_COLOR_BUFFER_BIT);
553             break;
554 
555         case DisableDitherVsClear::After:
556             glClearColor(0.125, 0.25, 0.5, 1);
557             glClear(GL_COLOR_BUFFER_BIT);
558             glDisable(GL_DITHER);
559             break;
560     }
561 
562     // draw quad
563     glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_BYTE, 0);
564     glBindBuffer(GL_ARRAY_BUFFER, 0);
565     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
566 
567     // validate that when disabling dithering, the color selection must be coordinate-independent
568     std::vector<GLColor> pixelData(kFramebufferWidth * kFramebufferHeight);
569     glReadPixels(0, 0, kFramebufferWidth, kFramebufferHeight, GL_RGBA, GL_UNSIGNED_BYTE,
570                  pixelData.data());
571 
572     const int increasingDirectionSize = kFramebufferWidth;
573     const int constantDirectionSize   = kFramebufferHeight;
574 
575     for (int incrPos = 0; incrPos < increasingDirectionSize; incrPos++)
576     {
577         bool colorHasChanged = false;
578 
579         GLColor prevConstantDirectionPixel;
580 
581         for (int constPos = 0; constPos < constantDirectionSize; constPos++)
582         {
583             const int x = incrPos;
584             const int y = constPos;
585 
586             const int currentPixelLoc  = y * kFramebufferWidth + x;
587             const GLColor currentPixel = pixelData[currentPixelLoc];
588 
589             if (constPos > 0 && currentPixel != prevConstantDirectionPixel)
590             {
591                 if (colorHasChanged)
592                 {
593                     ASSERT(false);
594                 }
595                 else
596                 {
597                     colorHasChanged = true;
598                 }
599             }
600 
601             prevConstantDirectionPixel = currentPixel;
602         }
603     }
604 }
605 
606 // repro dEQP-GLES3.functional.dither.disabled.gradient_red failure
TEST_P(FramebufferTest_ES3,RGB565DisableDitheringGradientRedTest)607 TEST_P(FramebufferTest_ES3, RGB565DisableDitheringGradientRedTest)
608 {
609     testDitherDisabledProperlyOnRGB565(GLColor::red, DisableDitherVsClear::Before);
610     testDitherDisabledProperlyOnRGB565(GLColor::red, DisableDitherVsClear::After);
611 }
612 
613 // repro dEQP-GLES3.functional.dither.disabled.gradient_green failure
TEST_P(FramebufferTest_ES3,RGB565DisableDitheringGradientGreenTest)614 TEST_P(FramebufferTest_ES3, RGB565DisableDitheringGradientGreenTest)
615 {
616     testDitherDisabledProperlyOnRGB565(GLColor::green, DisableDitherVsClear::Before);
617     testDitherDisabledProperlyOnRGB565(GLColor::green, DisableDitherVsClear::After);
618 }
619 
620 // repro dEQP-GLES3.functional.dither.disabled.gradient_blue failure
TEST_P(FramebufferTest_ES3,RGB565DisableDitheringGradientBlueTest)621 TEST_P(FramebufferTest_ES3, RGB565DisableDitheringGradientBlueTest)
622 {
623     testDitherDisabledProperlyOnRGB565(GLColor::blue, DisableDitherVsClear::Before);
624     testDitherDisabledProperlyOnRGB565(GLColor::blue, DisableDitherVsClear::After);
625 }
626 
627 // repro dEQP-GLES3.functional.dither.disabled.gradient_white failure
TEST_P(FramebufferTest_ES3,RGB565DisableDitheringGradientWhiteTest)628 TEST_P(FramebufferTest_ES3, RGB565DisableDitheringGradientWhiteTest)
629 {
630     testDitherDisabledProperlyOnRGB565(GLColor::white, DisableDitherVsClear::Before);
631     testDitherDisabledProperlyOnRGB565(GLColor::white, DisableDitherVsClear::After);
632 }
633 
634 // Test that subinvalidate with no prior command works.  Regression test for the Vulkan backend that
635 // assumed a render pass is started when sub invalidate is called.
TEST_P(FramebufferTest_ES3,SubInvalidateFirst)636 TEST_P(FramebufferTest_ES3, SubInvalidateFirst)
637 {
638     glBindFramebuffer(GL_FRAMEBUFFER, 0);
639 
640     // Invalidate half of the framebuffer using swapped dimensions.
641     std::array<GLenum, 1> attachments = {GL_COLOR};
642     glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 1, attachments.data(), 0, 0, kHeight, kWidth);
643     EXPECT_GL_NO_ERROR();
644 }
645 
646 // Test that subinvalidate doesn't discard data outside area.  Uses swapped width/height for
647 // invalidate which results in a partial invalidate, but also prevents bugs with Vulkan
648 // pre-rotation.
TEST_P(FramebufferTest_ES3,SubInvalidatePartial)649 TEST_P(FramebufferTest_ES3, SubInvalidatePartial)
650 {
651     glBindFramebuffer(GL_FRAMEBUFFER, 0);
652 
653     // Clear the attachment.
654     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
655     glClear(GL_COLOR_BUFFER_BIT);
656     EXPECT_GL_NO_ERROR();
657 
658     // Invalidate half of the framebuffer using swapped dimensions.
659     std::array<GLenum, 1> attachments = {GL_COLOR};
660     glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 1, attachments.data(), 0, 0, kHeight, kWidth);
661     EXPECT_GL_NO_ERROR();
662 
663     // Make sure the other half is correct.
664     EXPECT_PIXEL_COLOR_EQ(0, kWidth, GLColor::red);
665     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kWidth, GLColor::red);
666     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
667     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::red);
668 }
669 
670 // Test that invalidating depth/stencil of the default framebuffer doesn't crash.
TEST_P(FramebufferTest_ES3,InvalidateDefaultFramebufferDepthStencil)671 TEST_P(FramebufferTest_ES3, InvalidateDefaultFramebufferDepthStencil)
672 {
673     glBindFramebuffer(GL_FRAMEBUFFER, 0);
674 
675     std::array<GLenum, 2> attachments = {GL_DEPTH, GL_STENCIL};
676 
677     // Invalidate default framebuffer depth/stencil attachments
678     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments.data());
679     EXPECT_GL_NO_ERROR();
680 }
681 
682 // Test that invalidating color of the default framebuffer doesn't crash.
TEST_P(FramebufferTest_ES3,InvalidateDefaultFramebufferColor)683 TEST_P(FramebufferTest_ES3, InvalidateDefaultFramebufferColor)
684 {
685     glBindFramebuffer(GL_FRAMEBUFFER, 0);
686 
687     std::array<GLenum, 1> attachments = {GL_COLOR};
688 
689     // Invalidate default framebuffer color attachment.
690     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
691     EXPECT_GL_NO_ERROR();
692 }
693 
694 // Test that invalidating all attachments on the default framebuffer doesn't crash.
TEST_P(FramebufferTest_ES3,InvalidateDefaultFramebuffer)695 TEST_P(FramebufferTest_ES3, InvalidateDefaultFramebuffer)
696 {
697     glBindFramebuffer(GL_FRAMEBUFFER, 0);
698 
699     std::array<GLenum, 3> attachments = {GL_COLOR, GL_DEPTH, GL_STENCIL};
700 
701     // Invalidate all default framebuffer attachments.
702     glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments.data());
703     EXPECT_GL_NO_ERROR();
704 }
705 
706 // Test that invalidating combined depth/stencil attachment doesn't crash.
TEST_P(FramebufferTest_ES3,InvalidateDepthStencil)707 TEST_P(FramebufferTest_ES3, InvalidateDepthStencil)
708 {
709     // Create the framebuffer that will be invalidated
710     GLRenderbuffer depthStencil;
711     glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
712     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 2, 2);
713 
714     GLFramebuffer fbo;
715     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
716     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencil);
717     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
718 
719     EXPECT_GL_NO_ERROR();
720 
721     std::array<GLenum, 2> attachments = {GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT};
722 
723     // Invalidate both depth and stencil.
724     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments.data());
725     EXPECT_GL_NO_ERROR();
726 }
727 
728 // Test that invalidating an FB with a stencil attachment, which
729 // generates Validation errors, will not fail
TEST_P(FramebufferTest_ES3,InvalidateStencilAttachmentOnly)730 TEST_P(FramebufferTest_ES3, InvalidateStencilAttachmentOnly)
731 {
732     constexpr GLsizei kBufferSize = 4096;
733     std::vector<uint8_t> abdata(kBufferSize);
734     GLBuffer arrayBuffer;
735     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
736     glBufferData(GL_ARRAY_BUFFER, kBufferSize, abdata.data(), GL_STATIC_DRAW);
737 
738     std::vector<uint8_t> eabdata(kBufferSize);
739     GLBuffer elementArrayBuffer;
740     glBindBuffer(GL_ARRAY_BUFFER, elementArrayBuffer);
741     glBufferData(GL_ARRAY_BUFFER, kBufferSize, eabdata.data(), GL_STATIC_DRAW);
742 
743     GLTexture stencilTexture;
744     glBindTexture(GL_TEXTURE_2D, stencilTexture);
745     glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, 32, 32);
746 
747     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
748     glUseProgram(program);
749 
750     glEnableVertexAttribArray(0);
751     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
752     glVertexAttribPointer(0, 4, GL_SHORT, GL_TRUE, 8, nullptr);
753     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
754 
755     GLFramebuffer framebuffer;
756     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
757     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, stencilTexture, 0);
758     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
759 
760     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
761     GLVertexArray vertexArray;
762     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
763     glDrawElements(GL_TRIANGLE_STRIP, 26, GL_UNSIGNED_INT, nullptr);
764     EXPECT_GL_NO_ERROR();
765 
766     std::array<GLenum, 1> attachments = {GL_STENCIL_ATTACHMENT};
767     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
768     EXPECT_GL_NO_ERROR();
769 }
770 
771 // Test that invalidating stencil-only attachment doesn't crash.
TEST_P(FramebufferTest_ES3,InvalidateStencilOnly)772 TEST_P(FramebufferTest_ES3, InvalidateStencilOnly)
773 {
774     // Create the framebuffer that will be invalidated
775     GLRenderbuffer stencil;
776     glBindRenderbuffer(GL_RENDERBUFFER, stencil);
777     glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 2, 2);
778 
779     GLFramebuffer fbo;
780     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
781     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencil);
782     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
783 
784     EXPECT_GL_NO_ERROR();
785 
786     std::array<GLenum, 1> attachments = {GL_STENCIL_ATTACHMENT};
787 
788     // Invalidate both depth and stencil.
789     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
790     EXPECT_GL_NO_ERROR();
791 }
792 
793 // Test that invalidating stencil of a depth-only attachment doesn't crash.
TEST_P(FramebufferTest_ES3,DepthOnlyAttachmentInvalidateStencil)794 TEST_P(FramebufferTest_ES3, DepthOnlyAttachmentInvalidateStencil)
795 {
796     // Create the framebuffer that will be invalidated
797     GLRenderbuffer depth;
798     glBindRenderbuffer(GL_RENDERBUFFER, depth);
799     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 2, 2);
800 
801     GLFramebuffer fbo;
802     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
803     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
804     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
805 
806     EXPECT_GL_NO_ERROR();
807 
808     // Invalidate stencil only.
809     std::array<GLenum, 2> attachments = {GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT};
810     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
811     EXPECT_GL_NO_ERROR();
812 
813     // Invalidate both depth and stencil.
814     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments.data());
815     EXPECT_GL_NO_ERROR();
816 }
817 
818 // Test that invalidating depth of a stencil-only attachment doesn't crash.
TEST_P(FramebufferTest_ES3,StencilOnlyAttachmentInvalidateDepth)819 TEST_P(FramebufferTest_ES3, StencilOnlyAttachmentInvalidateDepth)
820 {
821     // Create the framebuffer that will be invalidated
822     GLRenderbuffer depth;
823     glBindRenderbuffer(GL_RENDERBUFFER, depth);
824     glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 2, 2);
825 
826     GLFramebuffer fbo;
827     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
828     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depth);
829     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
830 
831     EXPECT_GL_NO_ERROR();
832 
833     // Invalidate depth only.
834     std::array<GLenum, 2> attachments = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
835     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
836     EXPECT_GL_NO_ERROR();
837 
838     // Invalidate both depth and stencil.
839     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments.data());
840     EXPECT_GL_NO_ERROR();
841 }
842 
843 // Test that a scissored draw followed by subinvalidate followed by a non-scissored draw retains the
844 // part that is not invalidated.  Uses swapped width/height for invalidate which results in a
845 // partial invalidate, but also prevents bugs with Vulkan pre-rotation.
TEST_P(FramebufferTest_ES3,ScissoredDrawSubInvalidateThenNonScissoredDraw)846 TEST_P(FramebufferTest_ES3, ScissoredDrawSubInvalidateThenNonScissoredDraw)
847 {
848     glBindFramebuffer(GL_FRAMEBUFFER, 0);
849 
850     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
851     glUseProgram(drawColor);
852     GLint colorUniformLocation =
853         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
854     ASSERT_NE(colorUniformLocation, -1);
855 
856     // Clear color to red and the depth/stencil buffer to 1.0 and 0x55
857     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
858     glClearDepthf(1);
859     glClearStencil(0x55);
860     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
861     EXPECT_GL_NO_ERROR();
862 
863     // Break rendering so the following draw call starts rendering with a scissored area.
864     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
865 
866     // Issue a scissored draw call that changes depth to 0.5 and stencil 0x3C
867     glScissor(0, 0, kHeight, kWidth);
868     glEnable(GL_SCISSOR_TEST);
869 
870     glEnable(GL_DEPTH_TEST);
871     glDepthFunc(GL_ALWAYS);
872 
873     glEnable(GL_STENCIL_TEST);
874     glStencilFunc(GL_ALWAYS, 0x3C, 0xFF);
875     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
876     glStencilMask(0xFF);
877 
878     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
879     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0);
880 
881     // Invalidate the draw region (half of the framebuffer using swapped dimensions).
882     std::array<GLenum, 3> attachments = {GL_COLOR, GL_DEPTH, GL_STENCIL};
883     glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 3, attachments.data(), 0, 0, kHeight, kWidth);
884     EXPECT_GL_NO_ERROR();
885 
886     // Match the scissor to the framebuffer size and issue a draw call that blends blue, and expects
887     // depth to be 1 and stencil to be 0x55.  This is only valid for the half that was not
888     // invalidated.
889     glScissor(0, 0, kWidth, kHeight);
890     glDepthFunc(GL_LESS);
891     glStencilFunc(GL_EQUAL, 0x55, 0xFF);
892     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
893 
894     glEnable(GL_BLEND);
895     glBlendFunc(GL_ONE, GL_ONE);
896     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
897     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
898     ASSERT_GL_NO_ERROR();
899 
900     // Make sure the half that was not invalidated is correct.
901     EXPECT_PIXEL_COLOR_EQ(0, kWidth, GLColor::magenta);
902     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kWidth, GLColor::magenta);
903     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
904     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
905 }
906 
907 // Test that the framebuffer state tracking robustly handles a depth-only attachment being set
908 // as a depth-stencil attachment. It is equivalent to detaching the depth-stencil attachment.
TEST_P(FramebufferTest_ES3,DepthOnlyAsDepthStencil)909 TEST_P(FramebufferTest_ES3, DepthOnlyAsDepthStencil)
910 {
911     GLFramebuffer framebuffer;
912     GLRenderbuffer renderbuffer;
913 
914     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
915     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
916     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 4, 4);
917 
918     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
919                               renderbuffer);
920     EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
921 }
922 
923 // Test that the framebuffer correctly returns that it is not complete if invalid texture mip levels
924 // are bound
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevels)925 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevels)
926 {
927     GLFramebuffer framebuffer;
928     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
929 
930     GLTexture texture;
931     glBindTexture(GL_TEXTURE_2D, texture);
932 
933     // Create a complete mip chain in mips 1 to 3
934     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
935     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
936     glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
937 
938     // Create another complete mip chain in mips 4 to 5
939     glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
940     glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
941 
942     // Create a non-complete mip chain in mip 6
943     glTexImage2D(GL_TEXTURE_2D, 6, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
944 
945     // Incomplete, mipLevel != baseLevel and texture is not mip complete
946     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
947     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
948                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
949 
950     // Complete, mipLevel == baseLevel
951     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
952     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
953 
954     // Complete, mipLevel != baseLevel but texture is now mip complete
955     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2);
956     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
957     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3);
958     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
959 
960     // Incomplete, attached level below the base level
961     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
962     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
963     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
964                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
965 
966     // Incomplete, attached level is beyond effective max level
967     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 4);
968     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
969                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
970 
971     // Complete, mipLevel == baseLevel
972     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
973     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
974 
975     // Complete, mipLevel != baseLevel but texture is now mip complete
976     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 5);
977     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
978 
979     // Complete, mipLevel == baseLevel
980     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 6);
981     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 6);
982     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
983 }
984 
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevelsReadBack)985 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBack)
986 {
987     GLFramebuffer framebuffer;
988     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
989 
990     GLTexture texture;
991     glBindTexture(GL_TEXTURE_2D, texture);
992 
993     const std::array<GLColor, 4 * 4> mip0Data = {
994         GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
995         GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
996         GLColor::red, GLColor::red, GLColor::red, GLColor::red};
997     const std::array<GLColor, 2 * 2> mip1Data = {GLColor::green, GLColor::green, GLColor::green,
998                                                  GLColor::green};
999 
1000     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data());
1001     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data());
1002 
1003     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1004     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
1005     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1006 
1007     glClearColor(0, 0, 1.0f, 1.0f);
1008     glClear(GL_COLOR_BUFFER_BIT);
1009     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1010 }
1011 
1012 // TextureAttachmentMipLevelsReadBackWithDraw is a copy of TextureAttachmentMipLevelsReadBack except
1013 // for adding a draw after the last clear. The draw forces ANGLE's Vulkan backend to use the
1014 // framebuffer that is level 1 of the texture which will trigger the mismatch use of the GL level
1015 // and Vulkan level in referring to that rendertarget.
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevelsReadBackWithDraw)1016 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBackWithDraw)
1017 {
1018     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1019 
1020     GLFramebuffer framebuffer;
1021     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1022 
1023     GLTexture texture;
1024     glBindTexture(GL_TEXTURE_2D, texture);
1025 
1026     const std::array<GLColor, 4 * 4> mip0Data = {
1027         GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
1028         GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
1029         GLColor::red, GLColor::red, GLColor::red, GLColor::red};
1030     const std::array<GLColor, 2 * 2> mip1Data = {GLColor::green, GLColor::green, GLColor::green,
1031                                                  GLColor::green};
1032 
1033     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data());
1034     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data());
1035 
1036     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1037     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
1038     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1039 
1040     glClearColor(0, 0, 1.0f, 1.0f);
1041     glClear(GL_COLOR_BUFFER_BIT);
1042 
1043     // This draw triggers the use of the framebuffer
1044     glUseProgram(greenProgram);
1045     drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1046     ASSERT_GL_NO_ERROR();
1047     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1048 }
1049 
1050 // Test that passing an attachment COLOR_ATTACHMENTm where m is equal to MAX_COLOR_ATTACHMENTS
1051 // generates an INVALID_OPERATION.
1052 // OpenGL ES Version 3.0.5 (November 3, 2016), 4.4.2.4 Attaching Texture Images to a Framebuffer, p.
1053 // 208
TEST_P(FramebufferTest_ES3,ColorAttachmentIndexOutOfBounds)1054 TEST_P(FramebufferTest_ES3, ColorAttachmentIndexOutOfBounds)
1055 {
1056     GLFramebuffer framebuffer;
1057     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1058 
1059     GLint maxColorAttachments = 0;
1060     glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
1061     GLenum attachment = static_cast<GLenum>(maxColorAttachments + GL_COLOR_ATTACHMENT0);
1062 
1063     GLTexture texture;
1064     glBindTexture(GL_TEXTURE_2D, texture);
1065     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
1066     glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture, 0);
1067     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1068 }
1069 
1070 // Check that depth-only attachments report the correct number of samples.
TEST_P(FramebufferTest_ES3,MultisampleDepthOnly)1071 TEST_P(FramebufferTest_ES3, MultisampleDepthOnly)
1072 {
1073     GLRenderbuffer renderbuffer;
1074     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1075     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT24, 32, 32);
1076 
1077     GLFramebuffer framebuffer;
1078     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1079     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
1080     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1081     EXPECT_GL_NO_ERROR();
1082 
1083     GLint samples = 0;
1084     glGetIntegerv(GL_SAMPLES, &samples);
1085     EXPECT_GL_NO_ERROR();
1086     EXPECT_GE(samples, 2);
1087 }
1088 
1089 // Check that we only compare width and height of attachments, not depth.
TEST_P(FramebufferTest_ES3,AttachmentWith3DLayers)1090 TEST_P(FramebufferTest_ES3, AttachmentWith3DLayers)
1091 {
1092     GLTexture texA;
1093     glBindTexture(GL_TEXTURE_2D, texA);
1094     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1095 
1096     GLTexture texB;
1097     glBindTexture(GL_TEXTURE_3D, texB);
1098     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1099 
1100     GLFramebuffer framebuffer;
1101     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1102     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
1103     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texB, 0, 0);
1104     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1105     EXPECT_GL_NO_ERROR();
1106 }
1107 
1108 // Check that invalid layer is detected in framebuffer completeness check.
1109 TEST_P(FramebufferTest_ES3, 3DAttachmentInvalidLayer)
1110 {
1111     GLTexture tex;
1112     glBindTexture(GL_TEXTURE_3D, tex);
1113     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1114 
1115     GLFramebuffer framebuffer;
1116     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1117     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
1118     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
1119                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
1120 
1121     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
1122     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1123     EXPECT_GL_NO_ERROR();
1124 }
1125 
1126 // Check that invalid layer is detected in framebuffer completeness check.
1127 TEST_P(FramebufferTest_ES3, 2DArrayInvalidLayer)
1128 {
1129     GLTexture tex;
1130     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
1131     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1132 
1133     GLFramebuffer framebuffer;
1134     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1135     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
1136     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
1137                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
1138 
1139     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
1140     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1141     EXPECT_GL_NO_ERROR();
1142 }
1143 
1144 // Test that clearing the stencil buffer when the framebuffer only has a color attachment does not
1145 // crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentStencil)1146 TEST_P(FramebufferTest_ES3, ClearNonexistentStencil)
1147 {
1148     GLRenderbuffer rbo;
1149     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1150     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
1151 
1152     GLFramebuffer fbo;
1153     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1154     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1155 
1156     GLint clearValue = 0;
1157     glClearBufferiv(GL_STENCIL, 0, &clearValue);
1158 
1159     // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
1160     EXPECT_GL_NO_ERROR();
1161 }
1162 
1163 // Test that clearing the depth buffer when the framebuffer only has a color attachment does not
1164 // crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentDepth)1165 TEST_P(FramebufferTest_ES3, ClearNonexistentDepth)
1166 {
1167     GLRenderbuffer rbo;
1168     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1169     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
1170 
1171     GLFramebuffer fbo;
1172     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1173     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1174 
1175     GLfloat clearValue = 0.0f;
1176     glClearBufferfv(GL_DEPTH, 0, &clearValue);
1177 
1178     // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
1179     EXPECT_GL_NO_ERROR();
1180 }
1181 
1182 // Test that clearing a nonexistent color attachment does not crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentColor)1183 TEST_P(FramebufferTest_ES3, ClearNonexistentColor)
1184 {
1185     GLRenderbuffer rbo;
1186     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1187     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
1188 
1189     GLFramebuffer fbo;
1190     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1191     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1192 
1193     std::vector<GLfloat> clearValue = {{0.0f, 1.0f, 0.0f, 1.0f}};
1194     glClearBufferfv(GL_COLOR, 1, clearValue.data());
1195 
1196     // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
1197     EXPECT_GL_NO_ERROR();
1198 }
1199 
1200 // Test that clearing the depth and stencil buffers when the framebuffer only has a color attachment
1201 // does not crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentDepthStencil)1202 TEST_P(FramebufferTest_ES3, ClearNonexistentDepthStencil)
1203 {
1204     GLRenderbuffer rbo;
1205     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1206     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
1207 
1208     GLFramebuffer fbo;
1209     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1210     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1211 
1212     glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
1213 
1214     // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
1215     EXPECT_GL_NO_ERROR();
1216 }
1217 
1218 // Test that clearing a color attachment that has been deleted doesn't crash.
TEST_P(FramebufferTest_ES3,ClearDeletedAttachment)1219 TEST_P(FramebufferTest_ES3, ClearDeletedAttachment)
1220 {
1221     // An INVALID_FRAMEBUFFER_OPERATION error was seen in this test on Mac, not sure where it might
1222     // be originating from. http://anglebug.com/2834
1223     ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
1224 
1225     GLFramebuffer fbo;
1226     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1227 
1228     // There used to be a bug where some draw buffer state used to remain set even after the
1229     // attachment was detached via deletion. That's why we create, attach and delete this RBO here.
1230     GLuint rbo = 0u;
1231     glGenRenderbuffers(1, &rbo);
1232     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1233     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1234     glDeleteRenderbuffers(1, &rbo);
1235 
1236     // There needs to be at least one color attachment to prevent early out from the clear calls.
1237     GLRenderbuffer rbo2;
1238     glBindRenderbuffer(GL_RENDERBUFFER, rbo2);
1239     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
1240     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rbo2);
1241 
1242     ASSERT_GL_NO_ERROR();
1243 
1244     // There's no error specified for clearing nonexistent buffers, it's simply a no-op, so we
1245     // expect no GL errors below.
1246     std::array<GLfloat, 4> floatClearValue = {0.0f, 0.0f, 0.0f, 0.0f};
1247     glClearBufferfv(GL_COLOR, 0, floatClearValue.data());
1248     EXPECT_GL_NO_ERROR();
1249     std::array<GLuint, 4> uintClearValue = {0u, 0u, 0u, 0u};
1250     glClearBufferuiv(GL_COLOR, 0, uintClearValue.data());
1251     EXPECT_GL_NO_ERROR();
1252     std::array<GLint, 4> intClearValue = {0, 0, 0, 0};
1253     glClearBufferiv(GL_COLOR, 0, intClearValue.data());
1254     EXPECT_GL_NO_ERROR();
1255 }
1256 
1257 // Test that resizing the color attachment is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeColorAttachmentSmallToLarge)1258 TEST_P(FramebufferTest_ES3, ResizeColorAttachmentSmallToLarge)
1259 {
1260     GLFramebuffer fbo;
1261     GLTexture smallTexture;
1262     GLTexture largeTexture;
1263 
1264     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1265     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1266 
1267     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1268 
1269     // Bind the small texture
1270     glBindTexture(GL_TEXTURE_2D, smallTexture);
1271     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
1272                  GL_UNSIGNED_BYTE, nullptr);
1273     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1274     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1275     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
1276     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1277 
1278     // Draw to FBO backed by the small texture
1279     glUseProgram(greenProgram);
1280     drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1281     ASSERT_GL_NO_ERROR();
1282     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1283     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
1284 
1285     // Change the attachment to the larger texture that fills the window
1286     glBindTexture(GL_TEXTURE_2D, largeTexture);
1287     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1288                  GL_UNSIGNED_BYTE, nullptr);
1289     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1290     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1291     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
1292     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1293 
1294     // Draw to FBO backed by the large texture
1295     glUseProgram(blueProgram);
1296     drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1297     ASSERT_GL_NO_ERROR();
1298     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1299     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
1300 }
1301 
1302 // Test that resizing the color attachment is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeColorAttachmentLargeToSmall)1303 TEST_P(FramebufferTest_ES3, ResizeColorAttachmentLargeToSmall)
1304 {
1305     GLFramebuffer fbo;
1306     GLTexture smallTexture;
1307     GLTexture largeTexture;
1308 
1309     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1310     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1311 
1312     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1313 
1314     // Bind the large texture
1315     glBindTexture(GL_TEXTURE_2D, largeTexture);
1316     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1317                  GL_UNSIGNED_BYTE, nullptr);
1318     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1319     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1320     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
1321     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1322 
1323     // Draw to FBO backed by the large texture
1324     glUseProgram(blueProgram);
1325     drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1326     ASSERT_GL_NO_ERROR();
1327     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1328     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
1329 
1330     // Change the attachment to the smaller texture
1331     glBindTexture(GL_TEXTURE_2D, smallTexture);
1332     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
1333                  GL_UNSIGNED_BYTE, nullptr);
1334     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1335     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1336     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
1337     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1338 
1339     // Draw to FBO backed by the small texture
1340     glUseProgram(greenProgram);
1341     drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1342     ASSERT_GL_NO_ERROR();
1343     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1344     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
1345 }
1346 
1347 // Test that resizing the texture is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeTextureLargeToSmall)1348 TEST_P(FramebufferTest_ES3, ResizeTextureLargeToSmall)
1349 {
1350     GLFramebuffer fbo;
1351     GLTexture texture;
1352 
1353     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1354     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1355 
1356     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1357 
1358     // Allocate a large texture
1359     glBindTexture(GL_TEXTURE_2D, texture);
1360     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1361                  GL_UNSIGNED_BYTE, nullptr);
1362     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1363     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1364     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1365     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1366 
1367     // Draw to FBO backed by the large texture
1368     glUseProgram(blueProgram);
1369     drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1370     ASSERT_GL_NO_ERROR();
1371     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1372     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
1373 
1374     // Shrink the texture
1375     glBindTexture(GL_TEXTURE_2D, texture);
1376     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
1377                  GL_UNSIGNED_BYTE, nullptr);
1378     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1379     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1380     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1381     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1382 
1383     // Draw to FBO backed by the small texture
1384     glUseProgram(greenProgram);
1385     drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1386     ASSERT_GL_NO_ERROR();
1387     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1388     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
1389 }
1390 
1391 // Test that resizing the texture is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeTextureSmallToLarge)1392 TEST_P(FramebufferTest_ES3, ResizeTextureSmallToLarge)
1393 {
1394     GLFramebuffer fbo;
1395     GLTexture texture;
1396 
1397     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1398     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1399 
1400     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1401 
1402     // Allocate a small texture
1403     glBindTexture(GL_TEXTURE_2D, texture);
1404     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
1405                  GL_UNSIGNED_BYTE, nullptr);
1406     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1407     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1408     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1409     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1410 
1411     // Draw to FBO backed by the large texture
1412     glUseProgram(blueProgram);
1413     drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1414     ASSERT_GL_NO_ERROR();
1415     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1416     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::blue);
1417 
1418     // Grow the texture
1419     glBindTexture(GL_TEXTURE_2D, texture);
1420     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1421                  GL_UNSIGNED_BYTE, nullptr);
1422     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1423     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1424     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1425     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1426 
1427     // Draw to FBO backed by the small texture
1428     glUseProgram(greenProgram);
1429     drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1430     ASSERT_GL_NO_ERROR();
1431     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1432     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
1433 }
1434 
1435 // Test that fewer outputs than framebuffer attachments doesn't crash.  This causes a Vulkan
1436 // validation warning, but should not be fatal.
TEST_P(FramebufferTest_ES3,FewerShaderOutputsThanAttachments)1437 TEST_P(FramebufferTest_ES3, FewerShaderOutputsThanAttachments)
1438 {
1439     constexpr char kFS[] = R"(#version 300 es
1440 precision highp float;
1441 
1442 layout(location = 0) out vec4 color0;
1443 layout(location = 1) out vec4 color1;
1444 layout(location = 2) out vec4 color2;
1445 
1446 void main()
1447 {
1448     color0 = vec4(1.0, 0.0, 0.0, 1.0);
1449     color1 = vec4(0.0, 1.0, 0.0, 1.0);
1450     color2 = vec4(0.0, 0.0, 1.0, 1.0);
1451 }
1452 )";
1453 
1454     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1455 
1456     constexpr GLint kDrawBufferCount = 4;
1457 
1458     GLint maxDrawBuffers;
1459     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1460     ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
1461 
1462     GLTexture textures[kDrawBufferCount];
1463 
1464     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
1465     {
1466         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
1467         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1468                      GL_UNSIGNED_BYTE, nullptr);
1469     }
1470 
1471     GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,
1472                                         GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
1473 
1474     GLFramebuffer fbo;
1475     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1476 
1477     // Enable all draw buffers.
1478     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
1479     {
1480         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
1481         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
1482                                textures[texIndex], 0);
1483     }
1484     glDrawBuffers(kDrawBufferCount, allBufs);
1485 
1486     // Draw with simple program.
1487     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1488     ASSERT_GL_NO_ERROR();
1489 }
1490 
1491 // Test that GL_RGB9_E5 is renderable with the extension.
TEST_P(FramebufferTest_ES3,RenderSharedExponent)1492 TEST_P(FramebufferTest_ES3, RenderSharedExponent)
1493 {
1494     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_render_shared_exponent"));
1495 
1496     GLTexture tex;
1497     glBindTexture(GL_TEXTURE_2D, tex);
1498     const uint32_t data = 0x80000100;  // Red
1499     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB9_E5, 1, 1, 0, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, &data);
1500     ASSERT_GL_NO_ERROR();
1501 
1502     GLFramebuffer readFbo;
1503     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1504     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1505     ASSERT_GL_NO_ERROR();
1506 
1507     EXPECT_PIXEL_COLOR32F_EQ(0, 0, kFloatRed);
1508 
1509     GLRenderbuffer rbo;
1510     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1511     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB9_E5, 1, 1);
1512     ASSERT_GL_NO_ERROR();
1513 
1514     GLFramebuffer drawFbo;
1515     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
1516     glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1517     ASSERT_GL_NO_ERROR();
1518 
1519     glClearColor(0.0, 1.0, 0.0, 1.0);
1520     glClear(GL_COLOR_BUFFER_BIT);
1521     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo);
1522     EXPECT_PIXEL_COLOR32F_EQ(0, 0, kFloatGreen);
1523 
1524     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1525     glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1526     ASSERT_GL_NO_ERROR();
1527 
1528     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo);
1529     EXPECT_PIXEL_COLOR32F_EQ(0, 0, kFloatRed);
1530 }
1531 
1532 // Test color write masks with GL_RGB9_E5 color buffers.
TEST_P(FramebufferTest_ES3,RenderSharedExponentWithMask)1533 TEST_P(FramebufferTest_ES3, RenderSharedExponentWithMask)
1534 {
1535     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_QCOM_render_shared_exponent"));
1536 
1537     constexpr char kFS[] = R"(#version 300 es
1538 precision highp float;
1539 layout(location = 0) out vec4 color0;
1540 layout(location = 1) out vec4 color1;
1541 void main()
1542 {
1543     color0 = vec4(1.0, 0.0, 0.0, 1.0);
1544     color1 = vec4(0.0, 1.0, 0.0, 1.0);
1545 })";
1546 
1547     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1548 
1549     GLFramebuffer fbo;
1550     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1551 
1552     GLRenderbuffer rb0;
1553     glBindRenderbuffer(GL_RENDERBUFFER, rb0);
1554     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB9_E5, 4, 4);
1555     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb0);
1556 
1557     GLRenderbuffer rb1;
1558     glBindRenderbuffer(GL_RENDERBUFFER, rb1);
1559     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 4, 4);
1560     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rb1);
1561 
1562     ASSERT_GL_NO_ERROR();
1563     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1564 
1565     for (int mask = 0; mask < 16; mask++)
1566     {
1567         glColorMask(mask & 1, mask & 2, mask & 4, mask & 8);
1568         for (const bool enableSharedExponentAttachment : {false, true})
1569         {
1570             GLenum bufs[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
1571             bufs[0]        = enableSharedExponentAttachment ? GL_COLOR_ATTACHMENT0 : GL_NONE;
1572             glDrawBuffers(2, bufs);
1573 
1574             auto expectError = [](bool enabled, int mask) {
1575                 if (!enabled || mask == 0 || mask == 8 || mask == 7 || mask == 15)
1576                 {
1577                     EXPECT_GL_NO_ERROR();
1578                 }
1579                 else
1580                 {
1581                     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1582                 }
1583             };
1584 
1585             drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
1586             expectError(enableSharedExponentAttachment, mask);
1587 
1588             glClear(GL_COLOR_BUFFER_BIT);
1589             expectError(enableSharedExponentAttachment, mask);
1590 
1591             GLfloat clearValuef[4] = {};
1592             glClearBufferfv(GL_COLOR, 0, clearValuef);
1593             expectError(enableSharedExponentAttachment, mask);
1594             glClearBufferfv(GL_COLOR, 1, clearValuef);
1595             EXPECT_GL_NO_ERROR();
1596         }
1597     }
1598 }
1599 
1600 // Test that R8_SNORM, RG8_SNORM, and RGBA8_SNORM are renderable with the extension.
TEST_P(FramebufferTest_ES3,RenderSnorm8)1601 TEST_P(FramebufferTest_ES3, RenderSnorm8)
1602 {
1603     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_render_snorm"));
1604 
1605     auto test = [&](GLenum format) {
1606         GLRenderbuffer rbo;
1607         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1608         glRenderbufferStorage(GL_RENDERBUFFER, format, 4, 4);
1609         ASSERT_GL_NO_ERROR();
1610 
1611         GLFramebuffer fbo;
1612         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1613         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1614         ASSERT_GL_NO_ERROR();
1615 
1616         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1617 
1618         ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1619         glUseProgram(program);
1620         GLint colorLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1621         glUniform4f(colorLocation, -1.0f, -0.5f, -0.25f, -0.125f);
1622         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
1623         ASSERT_GL_NO_ERROR();
1624 
1625         if (format == GL_R8_SNORM)
1626         {
1627             EXPECT_PIXEL_8S_NEAR(0, 0, -127, 0, 0, 127, 2);
1628         }
1629         else if (format == GL_RG8_SNORM)
1630         {
1631             EXPECT_PIXEL_8S_NEAR(0, 0, -127, -64, 0, 127, 2);
1632         }
1633         else if (format == GL_RGBA8_SNORM)
1634         {
1635             EXPECT_PIXEL_8S_NEAR(0, 0, -127, -64, -32, -16, 2);
1636         }
1637     };
1638 
1639     test(GL_R8_SNORM);
1640     test(GL_RG8_SNORM);
1641     test(GL_RGBA8_SNORM);
1642 }
1643 
1644 // Test that non-trivial, e.g., reversed, blits are supported for signed normalized formats.
TEST_P(FramebufferTest_ES3,BlitReversedSnorm8)1645 TEST_P(FramebufferTest_ES3, BlitReversedSnorm8)
1646 {
1647     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_render_snorm"));
1648 
1649     auto test = [&](GLenum format) {
1650         GLRenderbuffer rbo1;
1651         glBindRenderbuffer(GL_RENDERBUFFER, rbo1);
1652         glRenderbufferStorage(GL_RENDERBUFFER, format, 4, 4);
1653         ASSERT_GL_NO_ERROR();
1654 
1655         GLFramebuffer fbo1;
1656         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo1);
1657         glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo1);
1658         ASSERT_GL_NO_ERROR();
1659 
1660         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1661 
1662         ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1663         glUseProgram(program);
1664         GLint colorLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1665         glUniform4f(colorLocation, -1.0f, -0.5f, -0.25f, -0.125f);
1666         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
1667         ASSERT_GL_NO_ERROR();
1668 
1669         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo1);
1670 
1671         GLRenderbuffer rbo2;
1672         glBindRenderbuffer(GL_RENDERBUFFER, rbo2);
1673         glRenderbufferStorage(GL_RENDERBUFFER, format, 4, 4);
1674         ASSERT_GL_NO_ERROR();
1675 
1676         GLFramebuffer fbo2;
1677         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo2);
1678         glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo2);
1679         ASSERT_GL_NO_ERROR();
1680 
1681         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1682 
1683         glBlitFramebuffer(0, 0, 4, 4, 4, 4, 0, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1684         ASSERT_GL_NO_ERROR();
1685 
1686         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo2);
1687 
1688         if (format == GL_R8_SNORM)
1689         {
1690             EXPECT_PIXEL_8S_NEAR(0, 0, -127, 0, 0, 127, 2);
1691         }
1692         else if (format == GL_RG8_SNORM)
1693         {
1694             EXPECT_PIXEL_8S_NEAR(0, 0, -127, -64, 0, 127, 2);
1695         }
1696         else if (format == GL_RGBA8_SNORM)
1697         {
1698             EXPECT_PIXEL_8S_NEAR(0, 0, -127, -64, -32, -16, 2);
1699         }
1700     };
1701 
1702     test(GL_R8_SNORM);
1703     test(GL_RG8_SNORM);
1704     test(GL_RGBA8_SNORM);
1705 }
1706 
1707 // Test that R16_SNORM, RG16_SNORM, and RGBA16_SNORM are renderable with the extension.
TEST_P(FramebufferTest_ES3,RenderSnorm16)1708 TEST_P(FramebufferTest_ES3, RenderSnorm16)
1709 {
1710     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_render_snorm"));
1711     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16"));
1712 
1713     auto test = [&](GLenum format) {
1714         GLRenderbuffer rbo;
1715         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1716         glRenderbufferStorage(GL_RENDERBUFFER, format, 4, 4);
1717         ASSERT_GL_NO_ERROR();
1718 
1719         GLFramebuffer fbo;
1720         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1721         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1722         ASSERT_GL_NO_ERROR();
1723 
1724         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1725 
1726         ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1727         glUseProgram(program);
1728         GLint colorLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1729         glUniform4f(colorLocation, -1.0f, -0.5f, -0.25f, -0.125f);
1730         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
1731         ASSERT_GL_NO_ERROR();
1732 
1733         if (format == GL_R16_SNORM_EXT)
1734         {
1735             EXPECT_PIXEL_16S_NEAR(0, 0, -32767, 0, 0, 32767, 2);
1736         }
1737         else if (format == GL_RG16_SNORM_EXT)
1738         {
1739             EXPECT_PIXEL_16S_NEAR(0, 0, -32767, -16383, 0, 32767, 2);
1740         }
1741         else if (format == GL_RGBA16_SNORM_EXT)
1742         {
1743             EXPECT_PIXEL_16S_NEAR(0, 0, -32767, -16383, -8191, -4095, 2);
1744         }
1745     };
1746 
1747     test(GL_R16_SNORM_EXT);
1748     test(GL_RG16_SNORM_EXT);
1749     test(GL_RGBA16_SNORM_EXT);
1750 }
1751 
1752 class FramebufferTest_ES3Metal : public FramebufferTest_ES3
1753 {};
1754 
1755 // Metal, iOS has a limit of the number of bits that can be output
1756 // to color attachments. Test we're enforcing that limit.
TEST_P(FramebufferTest_ES3Metal,TooManyBitsGeneratesFramebufferUnsupported)1757 TEST_P(FramebufferTest_ES3Metal, TooManyBitsGeneratesFramebufferUnsupported)
1758 {
1759     ANGLE_SKIP_TEST_IF(
1760         !getEGLWindow()->isFeatureEnabled(Feature::LimitMaxColorTargetBitsForTesting));
1761 
1762     GLint maxDrawBuffers;
1763     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1764 
1765     GLFramebuffer framebuffer;
1766 
1767     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1768 
1769     // Test maxDrawBuffers * RGBA8UI works.
1770     {
1771         std::vector<GLTexture> textures(maxDrawBuffers);
1772         for (GLint i = 0; i < maxDrawBuffers; ++i)
1773         {
1774             glBindTexture(GL_TEXTURE_2D, textures[i]);
1775             glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8UI, 1, 1);
1776             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1777             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1778             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
1779                                    textures[i], 0);
1780         }
1781         EXPECT_GL_NO_ERROR();
1782         EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1783     }
1784 
1785     // Test maxDrawBuffers * RGBA32UI does not work.
1786     {
1787         std::vector<GLTexture> textures(maxDrawBuffers);
1788         for (GLint i = 0; i < maxDrawBuffers; ++i)
1789         {
1790             glBindTexture(GL_TEXTURE_2D, textures[i]);
1791             glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, 1, 1);
1792             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1793             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1794             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
1795                                    textures[i], 0);
1796         }
1797         EXPECT_GL_NO_ERROR();
1798         EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_UNSUPPORTED, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1799     }
1800 }
1801 
1802 // Metal, iOS has a limit of the number of bits that can be output
1803 // to color attachments. Test we're enforcing that limit.
1804 // This test is separate from the one above as it's possible
1805 // glCheckFramebufferStatus might cache some calculation so we
1806 // don't call here to ensure we get INVALID_FRAMEBUFFER_OPERATION
1807 // when drawing.
TEST_P(FramebufferTest_ES3Metal,TooManyBitsGeneratesInvalidFramebufferOperation)1808 TEST_P(FramebufferTest_ES3Metal, TooManyBitsGeneratesInvalidFramebufferOperation)
1809 {
1810     ANGLE_SKIP_TEST_IF(
1811         !getEGLWindow()->isFeatureEnabled(Feature::LimitMaxColorTargetBitsForTesting));
1812 
1813     GLint maxDrawBuffers;
1814     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1815 
1816     GLFramebuffer framebuffer;
1817     std::vector<GLTexture> textures(maxDrawBuffers);
1818     std::vector<GLenum> drawBuffers(maxDrawBuffers, GL_NONE);
1819 
1820     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1821 
1822     std::stringstream fs;
1823 
1824     fs << R"(#version 300 es
1825       precision highp float;
1826       out uvec4 fragColor[)"
1827        << maxDrawBuffers << R"(];
1828       void main() {
1829       )";
1830 
1831     for (GLint i = 0; i < maxDrawBuffers; ++i)
1832     {
1833         fs << "  fragColor[" << i << "] = uvec4(" << i << ", " << i * 2 << ", " << i * 4 << ", "
1834            << i * 8 << ");\n";
1835         drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
1836         glBindTexture(GL_TEXTURE_2D, textures[i]);
1837         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
1838                      nullptr);
1839         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1840         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1841         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, textures[i],
1842                                0);
1843     }
1844     EXPECT_GL_NO_ERROR();
1845 
1846     fs << "}";
1847 
1848     constexpr const char vs[] = R"(#version 300 es
1849       void main() {
1850         gl_Position = vec4(0, 0, 0, 1);
1851         gl_PointSize = 1.0;
1852       }
1853     )";
1854 
1855     GLProgram program;
1856     program.makeRaster(vs, fs.str().c_str());
1857     glUseProgram(program);
1858     EXPECT_GL_NO_ERROR();
1859 
1860     // Validate we can draw to maxDrawBuffers attachments
1861     glDrawBuffers(maxDrawBuffers, drawBuffers.data());
1862     glDrawArrays(GL_POINTS, 0, 1);
1863     EXPECT_GL_NO_ERROR();
1864 
1865     for (GLint i = 0; i < maxDrawBuffers; ++i)
1866     {
1867         glBindTexture(GL_TEXTURE_2D, textures[i]);
1868         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32UI, 1, 1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
1869                      nullptr);
1870     }
1871     EXPECT_GL_NO_ERROR();
1872 
1873     glDrawArrays(GL_POINTS, 0, 1);
1874     EXPECT_GLENUM_EQ(GL_INVALID_FRAMEBUFFER_OPERATION, glGetError());
1875 }
1876 
1877 class FramebufferTestWithFormatFallback : public ANGLETest<>
1878 {
1879   protected:
FramebufferTestWithFormatFallback()1880     FramebufferTestWithFormatFallback()
1881     {
1882         setWindowWidth(16);
1883         setWindowHeight(16);
1884         setConfigRedBits(8);
1885         setConfigGreenBits(8);
1886         setConfigBlueBits(8);
1887         setConfigAlphaBits(8);
1888         setConfigDepthBits(24);
1889         setConfigStencilBits(8);
1890     }
1891 
1892     void texImageFollowedByFBORead(GLenum internalFormat, GLenum type);
1893     void blitCopyFollowedByFBORead(GLenum internalFormat, GLenum type);
1894     void copyTexImageFollowedBySampling(GLenum internalFormat, GLenum type);
1895     void cubeTexImageFollowedByFBORead(GLenum internalFormat, GLenum type);
1896     GLushort convertGLColorToUShort(GLenum internalFormat, const GLColor &color);
1897     static constexpr GLsizei kTexWidth  = 16;
1898     static constexpr GLsizei kTexHeight = 16;
1899     static constexpr GLsizei kMaxLevel  = 4;
1900 };
1901 
convertGLColorToUShort(GLenum internalFormat,const GLColor & color)1902 GLushort FramebufferTestWithFormatFallback::convertGLColorToUShort(GLenum internalFormat,
1903                                                                    const GLColor &color)
1904 {
1905     GLushort r, g, b, a;
1906     switch (internalFormat)
1907     {
1908         case GL_RGB5_A1:
1909             r = (color.R >> 3) << 11;
1910             g = (color.G >> 3) << 6;
1911             b = (color.B >> 3) << 1;
1912             a = color.A >> 7;
1913             break;
1914         case GL_RGBA4:
1915             r = (color.R >> 4) << 12;
1916             g = (color.G >> 4) << 8;
1917             b = (color.B >> 4) << 4;
1918             a = color.A >> 4;
1919             break;
1920         default:
1921             UNREACHABLE();
1922             r = 0;
1923             g = 0;
1924             b = 0;
1925             a = 0;
1926             break;
1927     }
1928     return r | g | b | a;
1929 }
1930 
1931 // Test texture format fallback while it has staged updates.
texImageFollowedByFBORead(GLenum internalFormat,GLenum type)1932 void FramebufferTestWithFormatFallback::texImageFollowedByFBORead(GLenum internalFormat,
1933                                                                   GLenum type)
1934 {
1935     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
1936     GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1937     ASSERT_NE(-1, textureLocation);
1938     GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1939     ASSERT_NE(-1, lodLocation);
1940 
1941     const GLColor kColor = GLColor::blue;
1942 
1943     for (int loop = 0; loop < 4; loop++)
1944     {
1945         GLTexture texture;
1946         glBindTexture(GL_TEXTURE_2D, texture);
1947         const GLushort u16Color = convertGLColorToUShort(internalFormat, kColor);
1948         std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1949         if (loop == 0 || loop == 2)
1950         {
1951             glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1952                          pixels.data());
1953         }
1954         else
1955         {
1956             glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, kTexWidth, kTexHeight);
1957             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, type,
1958                             pixels.data());
1959         }
1960         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1961         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1962 
1963         if (loop >= 2)
1964         {
1965             // Draw quad using texture
1966             glUseProgram(program);
1967             glActiveTexture(GL_TEXTURE0);
1968             glBindTexture(GL_TEXTURE_2D, texture);
1969             glClearColor(0, 0, 0, 1);
1970             glClear(GL_COLOR_BUFFER_BIT);
1971             glUniform1f(lodLocation, 0);
1972             drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1973             EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
1974             ASSERT_GL_NO_ERROR();
1975         }
1976 
1977         // attach blue texture to FBO
1978         GLFramebuffer fbo;
1979         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1980         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1981         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1982         EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, kColor.R, kColor.G, kColor.B, kColor.A);
1983         ASSERT_GL_NO_ERROR();
1984     }
1985 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_TexImage)1986 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_TexImage)
1987 {
1988     texImageFollowedByFBORead(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
1989 }
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_TexImage)1990 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_TexImage)
1991 {
1992     texImageFollowedByFBORead(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
1993 }
1994 
1995 // Test texture format fallback while it has staged updates and then do copyTexImage2D and followed
1996 // by sampling.
copyTexImageFollowedBySampling(GLenum internalFormat,GLenum type)1997 void FramebufferTestWithFormatFallback::copyTexImageFollowedBySampling(GLenum internalFormat,
1998                                                                        GLenum type)
1999 {
2000     const GLColor kColor = GLColor::blue;
2001     // Create blue texture
2002     GLTexture blueTex2D;
2003     glBindTexture(GL_TEXTURE_2D, blueTex2D);
2004     const GLushort u16Color = convertGLColorToUShort(internalFormat, kColor);
2005     std::vector<GLushort> bluePixels(kTexWidth * kTexHeight, u16Color);
2006     glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
2007                  bluePixels.data());
2008     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2009     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2010 
2011     // attach blue texture to FBO and read back to verify. This should trigger format conversion
2012     GLFramebuffer blueFbo;
2013     glBindFramebuffer(GL_FRAMEBUFFER, blueFbo);
2014     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blueTex2D, 0);
2015     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2016     EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 0, 0, 255, 255);
2017     ASSERT_GL_NO_ERROR();
2018 
2019     // Create red texture
2020     GLTexture copyTex2D;
2021     glBindTexture(GL_TEXTURE_2D, copyTex2D);
2022     std::vector<GLushort> redPixels(kTexWidth * kTexHeight, 0xF801);
2023     glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
2024                  redPixels.data());
2025     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2026     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2027 
2028     // CopyTexImage from blue to red
2029     glCopyTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 0, 0, kTexWidth, kTexHeight, 0);
2030     ASSERT_GL_NO_ERROR();
2031 
2032     // Draw with copyTex2D
2033     glBindFramebuffer(GL_FRAMEBUFFER, 0);
2034     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
2035     glUseProgram(program);
2036     GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
2037     ASSERT_NE(-1, textureLocation);
2038     GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
2039     ASSERT_NE(-1, lodLocation);
2040     glActiveTexture(GL_TEXTURE0);
2041     glBindTexture(GL_TEXTURE_2D, copyTex2D);
2042     glClearColor(0, 1, 0, 1);
2043     glClear(GL_COLOR_BUFFER_BIT);
2044     glUniform1f(lodLocation, 0);
2045     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2046     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, kColor.R, kColor.G, kColor.B,
2047                     kColor.A);
2048     ASSERT_GL_NO_ERROR();
2049 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_CopyTexImage)2050 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_CopyTexImage)
2051 {
2052     copyTexImageFollowedBySampling(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
2053 }
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_CopyTexImage)2054 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_CopyTexImage)
2055 {
2056     copyTexImageFollowedBySampling(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
2057 }
2058 
2059 // Test texture format fallback while it has staged updates and then do FBO blit and followed by
2060 // copyTexImage2D.
blitCopyFollowedByFBORead(GLenum internalFormat,GLenum type)2061 void FramebufferTestWithFormatFallback::blitCopyFollowedByFBORead(GLenum internalFormat,
2062                                                                   GLenum type)
2063 {
2064     for (int loop = 0; loop < 2; loop++)
2065     {
2066         // Create blue texture
2067         GLTexture blueTex2D;
2068         glBindTexture(GL_TEXTURE_2D, blueTex2D);
2069         GLushort u16Color = convertGLColorToUShort(internalFormat, GLColor::blue);
2070         std::vector<GLushort> bluePixels(kTexWidth * kTexHeight, u16Color);
2071         glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
2072                      bluePixels.data());
2073         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2074         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2075 
2076         // attach blue texture to FBO
2077         GLFramebuffer readFbo;
2078         glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
2079         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blueTex2D,
2080                                0);
2081         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2082 
2083         GLTexture redTex2D;
2084         GLRenderbuffer renderBuffer;
2085         GLFramebuffer drawFbo;
2086         if (loop == 0)
2087         {
2088             glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
2089             glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, kTexWidth, kTexHeight);
2090 
2091             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
2092             glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2093                                       renderBuffer);
2094             EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2095             glClearColor(1.0, 0.0, 0.0, 1.0);
2096             glClear(GL_COLOR_BUFFER_BIT);
2097         }
2098         else
2099         {
2100             glBindTexture(GL_TEXTURE_2D, redTex2D);
2101             u16Color = convertGLColorToUShort(internalFormat, GLColor::red);
2102             std::vector<GLushort> redPixels(kTexWidth * kTexHeight, u16Color);
2103             glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
2104                          redPixels.data());
2105             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2106             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2107 
2108             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
2109             glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
2110                                    redTex2D, 0);
2111             EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2112         }
2113 
2114         // Blit
2115         glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
2116         glBlitFramebuffer(0, 0, kTexWidth, kTexHeight, 0, 0, kTexWidth, kTexHeight,
2117                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
2118         ASSERT_GL_NO_ERROR();
2119 
2120         GLFramebuffer readFbo2;
2121         if (loop == 0)
2122         {
2123             // CopyTexImage from renderBuffer to copyTex2D
2124             glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo2);
2125             glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2126                                       renderBuffer);
2127         }
2128         else
2129         {
2130 
2131             // CopyTexImage from redTex2D to copyTex2D
2132             glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo2);
2133             glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
2134                                    redTex2D, 0);
2135         }
2136         GLTexture copyTex2D;
2137         glBindTexture(GL_TEXTURE_2D, copyTex2D);
2138         glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, kTexWidth, kTexHeight, 0);
2139         ASSERT_GL_NO_ERROR();
2140         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2141         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2142         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2143         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2144         glBindTexture(GL_TEXTURE_2D, 0);
2145 
2146         // Read out red texture
2147         GLFramebuffer readFbo3;
2148         glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo3);
2149         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTex2D,
2150                                0);
2151         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2152         EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 0, 0, 255, 255);
2153         ASSERT_GL_NO_ERROR();
2154     }
2155 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_BlitCopyTexImage)2156 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_BlitCopyTexImage)
2157 {
2158     blitCopyFollowedByFBORead(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
2159 }
TEST_P(FramebufferTestWithFormatFallback,RGBA4444_BlitCopyTexImage)2160 TEST_P(FramebufferTestWithFormatFallback, RGBA4444_BlitCopyTexImage)
2161 {
2162     blitCopyFollowedByFBORead(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
2163 }
2164 
2165 // Test texture format fallback while it has staged updates, specially for cubemap target.
cubeTexImageFollowedByFBORead(GLenum internalFormat,GLenum type)2166 void FramebufferTestWithFormatFallback::cubeTexImageFollowedByFBORead(GLenum internalFormat,
2167                                                                       GLenum type)
2168 {
2169     const GLColor kColors[6] = {GLColor::red,  GLColor::green,  GLColor::blue,
2170                                 GLColor::cyan, GLColor::yellow, GLColor::magenta};
2171     GLTexture cubeTex2D;
2172     glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex2D);
2173     for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
2174          target++)
2175     {
2176         int j                   = target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2177         const GLushort u16Color = convertGLColorToUShort(internalFormat, kColors[j]);
2178         std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
2179         glTexImage2D(target, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
2180                      pixels.data());
2181     }
2182     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2183     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2184 
2185     // attach blue texture to FBO
2186     GLFramebuffer fbo;
2187     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2188     for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
2189          target++)
2190     {
2191         GLint j = target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
2192         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, cubeTex2D, 0);
2193         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2194         EXPECT_PIXEL_COLOR_EQ(kTexWidth / 2, kTexHeight / 2, kColors[j]) << "face " << j;
2195     }
2196     ASSERT_GL_NO_ERROR();
2197 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_CubeTexImage)2198 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_CubeTexImage)
2199 {
2200     cubeTexImageFollowedByFBORead(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
2201 }
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_CubeTexImage)2202 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_CubeTexImage)
2203 {
2204     cubeTexImageFollowedByFBORead(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
2205 }
2206 
2207 // Tests that the out-of-range staged update is reformatted when mipmapping is enabled, but not
2208 // before it.
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_OutOfRangeStagedUpdateReformated)2209 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_OutOfRangeStagedUpdateReformated)
2210 {
2211     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
2212     glUseProgram(program);
2213     GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
2214     ASSERT_NE(-1, textureLocation);
2215     GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
2216     ASSERT_NE(-1, lodLocation);
2217 
2218     GLTexture texture;
2219     glBindTexture(GL_TEXTURE_2D, texture);
2220     GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
2221     std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
2222     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
2223                  GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
2224     u16Color = convertGLColorToUShort(GL_RGB5_A1, GLColor::green);
2225     pixels.assign(kTexWidth * kTexHeight, u16Color);
2226     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth / 2, kTexHeight / 2, 0, GL_RGBA,
2227                  GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
2228     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2229     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2230 
2231     // Draw quad
2232     glActiveTexture(GL_TEXTURE0);
2233     glBindTexture(GL_TEXTURE_2D, texture);
2234     glUniform1f(lodLocation, 0);
2235     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2236     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
2237 
2238     // Now trigger format conversion
2239     GLFramebuffer readFbo;
2240     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
2241     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2242     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2243     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowWidth() / 2, 255, 0, 0, 255);
2244 
2245     // update level0 with compatible data and enable mipmap
2246     u16Color = convertGLColorToUShort(GL_RGB5_A1, GLColor::blue);
2247     pixels.assign(kTexWidth * kTexHeight, u16Color);
2248     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
2249                  GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
2250     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
2251     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2252     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
2253 
2254     // Draw quad with lod0 and lod1 and verify color
2255     glUniform1f(lodLocation, 0);
2256     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2257     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
2258     glUniform1f(lodLocation, 1);
2259     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2260     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
2261     ASSERT_GL_NO_ERROR();
2262 }
2263 
2264 // Tests that the texture is reformatted when the clear is done through the draw path.
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_MaskedClear)2265 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_MaskedClear)
2266 {
2267     for (int loop = 0; loop < 2; loop++)
2268     {
2269         GLTexture texture;
2270         glBindTexture(GL_TEXTURE_2D, texture);
2271         GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
2272         std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
2273         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
2274                      GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
2275         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2276         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2277 
2278         if (loop == 0)
2279         {
2280             // Draw quad
2281             ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(),
2282                              essl3_shaders::fs::Texture2DLod());
2283             glUseProgram(program);
2284             GLint textureLocation =
2285                 glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
2286             ASSERT_NE(-1, textureLocation);
2287             GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
2288             ASSERT_NE(-1, lodLocation);
2289             glActiveTexture(GL_TEXTURE0);
2290             glBindTexture(GL_TEXTURE_2D, texture);
2291             glClearColor(0, 0, 0, 1);
2292             glClear(GL_COLOR_BUFFER_BIT);
2293             glUniform1f(lodLocation, 0);
2294             drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2295             EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
2296             ASSERT_GL_NO_ERROR();
2297         }
2298 
2299         // Now trigger format conversion with masked clear
2300         GLFramebuffer fbo;
2301         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2302         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2303         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2304         glClearColor(0, 1, 1, 1);
2305         glColorMask(false, true, false, false);
2306         glClear(GL_COLOR_BUFFER_BIT);
2307         EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 255, 255, 0, 255);
2308         ASSERT_GL_NO_ERROR();
2309     }
2310 }
2311 
2312 // Tests that glGenerateMipmap works when the format is converted to renderable..
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_GenerateMipmap)2313 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_GenerateMipmap)
2314 {
2315     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
2316     glUseProgram(program);
2317     GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
2318     ASSERT_NE(-1, textureLocation);
2319     GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
2320     ASSERT_NE(-1, lodLocation);
2321 
2322     for (int loop = 0; loop < 4; loop++)
2323     {
2324         GLTexture texture;
2325         glBindTexture(GL_TEXTURE_2D, texture);
2326         GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
2327         std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
2328         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
2329                      GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
2330         u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::green);
2331         pixels.assign(kTexWidth * kTexHeight, u16Color);
2332         glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth / 2, kTexHeight / 2, 0, GL_RGBA,
2333                      GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
2334         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2335         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2336 
2337         if (loop == 0 || loop == 2)
2338         {
2339             // Draw quad
2340             glUniform1f(lodLocation, 0);
2341             drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2342             EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
2343             ASSERT_GL_NO_ERROR();
2344         }
2345 
2346         if (loop > 2)
2347         {
2348             // Now trigger format conversion
2349             GLFramebuffer readFbo;
2350             glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
2351             glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
2352                                    texture, 0);
2353             EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2354         }
2355 
2356         // GenerateMipmap
2357         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
2358         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2359         glGenerateMipmap(GL_TEXTURE_2D);
2360 
2361         // Verify each lod
2362         for (int lod = 0; lod <= kMaxLevel; lod++)
2363         {
2364             glUniform1f(lodLocation, lod);
2365             drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2366             EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
2367         }
2368         ASSERT_GL_NO_ERROR();
2369     }
2370 }
2371 
2372 // Tests that when reformatting the image, incompatible updates don't cause a problem.
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_InCompatibleFormat)2373 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_InCompatibleFormat)
2374 {
2375     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
2376     glUseProgram(program);
2377     GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
2378     ASSERT_NE(-1, textureLocation);
2379     GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
2380     ASSERT_NE(-1, lodLocation);
2381 
2382     for (int loop = 0; loop < 4; loop++)
2383     {
2384         GLTexture texture;
2385         glBindTexture(GL_TEXTURE_2D, texture);
2386         // Define a texture with lod0 and lod1 with two different effective internal formats or size
2387         GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
2388         std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
2389         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
2390                      GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
2391         if (loop < 2)
2392         {
2393             u16Color = convertGLColorToUShort(GL_RGB5_A1, GLColor::green);
2394             pixels.assign(kTexWidth * kTexHeight, u16Color);
2395             // bad effective internal format
2396             glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth / 2, kTexHeight / 2, 0, GL_RGBA,
2397                          GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
2398         }
2399         else
2400         {
2401             u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::green);
2402             pixels.assign(kTexWidth * kTexHeight, u16Color);
2403             // bad size
2404             glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
2405                          GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
2406         }
2407         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
2408         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2409 
2410         // Now trigger format conversion and verify lod0
2411         GLFramebuffer readFbo;
2412         glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
2413         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture,
2414                                0);
2415         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2416         EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 255, 0, 0, 255);
2417 
2418         if (loop == 1 || loop == 3)
2419         {
2420             // Disable mipmap and sample from lod0 and verify
2421             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2422             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2423             glUniform1f(lodLocation, 0);
2424             drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
2425             EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
2426         }
2427     }
2428 }
2429 
2430 class FramebufferTest_ES31 : public ANGLETest<>
2431 {
2432   protected:
validateSamplePass(GLQuery & query,GLint width,GLint height)2433     void validateSamplePass(GLQuery &query, GLint width, GLint height)
2434     {
2435         GLuint passedCount;
2436 
2437         glUniform2i(0, width - 1, height - 1);
2438         glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
2439         glDrawArrays(GL_TRIANGLES, 0, 6);
2440         glEndQuery(GL_ANY_SAMPLES_PASSED);
2441         glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
2442         EXPECT_GT(static_cast<GLint>(passedCount), 0);
2443 
2444         glUniform2i(0, width - 1, height);
2445         glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
2446         glDrawArrays(GL_TRIANGLES, 0, 6);
2447         glEndQuery(GL_ANY_SAMPLES_PASSED);
2448         glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
2449         EXPECT_EQ(static_cast<GLint>(passedCount), 0);
2450 
2451         glUniform2i(0, width, height - 1);
2452         glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
2453         glDrawArrays(GL_TRIANGLES, 0, 6);
2454         glEndQuery(GL_ANY_SAMPLES_PASSED);
2455         glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
2456         EXPECT_EQ(static_cast<GLint>(passedCount), 0);
2457     }
2458 
verifyDepth(GLuint framebuffer,int width,int height,float depthValue)2459     void verifyDepth(GLuint framebuffer, int width, int height, float depthValue)
2460     {
2461         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
2462 
2463         GLint colorAttachment = GL_NONE;
2464         glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2465                                               GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
2466                                               &colorAttachment);
2467 
2468         // If no color attachment add a temp one for verification.
2469         GLTexture tempColor;
2470         if (colorAttachment == GL_NONE)
2471         {
2472             glBindTexture(GL_TEXTURE_2D, tempColor);
2473             glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2474             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tempColor,
2475                                    0);
2476         }
2477 
2478         // Use a small shader to verify depth.
2479         ANGLE_GL_PROGRAM(depthTestProgram, essl1_shaders::vs::Passthrough(),
2480                          essl1_shaders::fs::Blue());
2481         ANGLE_GL_PROGRAM(depthTestProgramFail, essl1_shaders::vs::Passthrough(),
2482                          essl1_shaders::fs::Red());
2483 
2484         GLboolean hasDepthTest   = GL_FALSE;
2485         GLboolean hasDepthWrite  = GL_TRUE;
2486         GLint prevDepthFunc      = GL_ALWAYS;
2487         GLboolean hasStencilTest = GL_FALSE;
2488 
2489         glGetBooleanv(GL_DEPTH_TEST, &hasDepthTest);
2490         glGetBooleanv(GL_DEPTH_WRITEMASK, &hasDepthWrite);
2491         glGetIntegerv(GL_DEPTH_FUNC, &prevDepthFunc);
2492         glGetBooleanv(GL_STENCIL_TEST, &hasStencilTest);
2493 
2494         if (!hasDepthTest)
2495         {
2496             glEnable(GL_DEPTH_TEST);
2497         }
2498         if (hasDepthWrite)
2499         {
2500             glDepthMask(GL_FALSE);
2501         }
2502         if (hasStencilTest)
2503         {
2504             glDisable(GL_STENCIL_TEST);
2505         }
2506         glDepthFunc(GL_LESS);
2507         drawQuad(depthTestProgram, essl1_shaders::PositionAttrib(), depthValue - 0.01f);
2508         drawQuad(depthTestProgramFail, essl1_shaders::PositionAttrib(), depthValue + 0.01f);
2509         if (!hasDepthTest)
2510         {
2511             glDisable(GL_DEPTH_TEST);
2512         }
2513         if (hasDepthWrite)
2514         {
2515             glDepthMask(GL_TRUE);
2516         }
2517         glDepthFunc(prevDepthFunc);
2518         if (hasStencilTest)
2519         {
2520             glEnable(GL_STENCIL_TEST);
2521         }
2522         ASSERT_GL_NO_ERROR();
2523 
2524         EXPECT_PIXEL_RECT_EQ(0, 0, width, height, GLColor::blue);
2525 
2526         if (colorAttachment == GL_NONE)
2527         {
2528             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
2529         }
2530     }
2531 
verifyStencil(GLuint framebuffer,int width,int height,uint32_t stencilValue)2532     void verifyStencil(GLuint framebuffer, int width, int height, uint32_t stencilValue)
2533     {
2534         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
2535 
2536         GLint colorAttachment = GL_NONE;
2537         glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2538                                               GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
2539                                               &colorAttachment);
2540 
2541         // If no color attachment add a temp one for verification.
2542         GLTexture tempColor;
2543         if (colorAttachment == GL_NONE)
2544         {
2545             glBindTexture(GL_TEXTURE_2D, tempColor);
2546             glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2547             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tempColor,
2548                                    0);
2549         }
2550 
2551         // Use another small shader to verify stencil.
2552         ANGLE_GL_PROGRAM(stencilTestProgram, essl1_shaders::vs::Passthrough(),
2553                          essl1_shaders::fs::Green());
2554         GLboolean hasStencilTest   = GL_FALSE;
2555         GLint prevStencilFunc      = GL_ALWAYS;
2556         GLint prevStencilValue     = 0xFF;
2557         GLint prevStencilRef       = 0xFF;
2558         GLint prevStencilFail      = GL_KEEP;
2559         GLint prevStencilDepthFail = GL_KEEP;
2560         GLint prevStencilDepthPass = GL_KEEP;
2561         GLboolean hasDepthTest     = GL_FALSE;
2562 
2563         glGetBooleanv(GL_STENCIL_TEST, &hasStencilTest);
2564         glGetIntegerv(GL_STENCIL_FUNC, &prevStencilFunc);
2565         glGetIntegerv(GL_STENCIL_VALUE_MASK, &prevStencilValue);
2566         glGetIntegerv(GL_STENCIL_REF, &prevStencilRef);
2567         glGetIntegerv(GL_STENCIL_FAIL, &prevStencilFail);
2568         glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &prevStencilDepthFail);
2569         glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &prevStencilDepthPass);
2570         glGetBooleanv(GL_DEPTH_TEST, &hasDepthTest);
2571 
2572         if (!hasStencilTest)
2573         {
2574             glEnable(GL_STENCIL_TEST);
2575         }
2576         glStencilFunc(GL_EQUAL, stencilValue, 0xFF);
2577         glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2578         if (hasDepthTest)
2579         {
2580             glDisable(GL_DEPTH_TEST);
2581         }
2582         drawQuad(stencilTestProgram, essl1_shaders::PositionAttrib(), 0.0f);
2583         if (!hasStencilTest)
2584         {
2585             glDisable(GL_STENCIL_TEST);
2586         }
2587         glStencilFunc(prevStencilFunc, prevStencilValue, prevStencilRef);
2588         glStencilOp(prevStencilFail, prevStencilDepthFail, prevStencilDepthPass);
2589         if (hasDepthTest)
2590         {
2591             glEnable(GL_DEPTH_TEST);
2592         }
2593         ASSERT_GL_NO_ERROR();
2594 
2595         EXPECT_PIXEL_RECT_EQ(0, 0, width, height, GLColor::green);
2596 
2597         if (colorAttachment == GL_NONE)
2598         {
2599             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
2600         }
2601     }
2602 
2603     static constexpr char kFSWriteRedGreen[] = R"(#extension GL_EXT_draw_buffers : enable
2604 precision highp float;
2605 void main()
2606 {
2607     gl_FragData[0] = vec4(1.0, 0.0, 0.0, 1.0);  // attachment 0: red
2608     gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0);  // attachment 1: green
2609 })";
2610 };
2611 
2612 // Test that without attachment, if either the value of FRAMEBUFFER_DEFAULT_WIDTH or
2613 // FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is incomplete.
TEST_P(FramebufferTest_ES31,IncompleteMissingAttachmentDefaultParam)2614 TEST_P(FramebufferTest_ES31, IncompleteMissingAttachmentDefaultParam)
2615 {
2616     GLFramebuffer mFramebuffer;
2617     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
2618 
2619     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
2620     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
2621     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2622 
2623     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
2624     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
2625     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
2626                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
2627 
2628     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
2629     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
2630     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
2631                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
2632 
2633     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
2634     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
2635     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
2636                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
2637 
2638     ASSERT_GL_NO_ERROR();
2639 }
2640 
2641 // Test that the sample count of a mix of texture and renderbuffer should be same.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleSampleCountMix)2642 TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix)
2643 {
2644     GLFramebuffer mFramebuffer;
2645     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
2646 
2647     // Lookup the supported number of sample counts (rely on fact that ANGLE uses the same set of
2648     // sample counts for textures and renderbuffers)
2649     GLint numSampleCounts = 0;
2650     std::vector<GLint> sampleCounts;
2651     GLsizei queryBufferSize = 1;
2652     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
2653                           queryBufferSize, &numSampleCounts);
2654     ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
2655     sampleCounts.resize(numSampleCounts);
2656     queryBufferSize = numSampleCounts;
2657     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
2658                           sampleCounts.data());
2659 
2660     GLTexture mTexture;
2661     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
2662     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
2663 
2664     GLRenderbuffer mRenderbuffer;
2665     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
2666     glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCounts[1], GL_RGBA8, 1, 1);
2667     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2668                            mTexture, 0);
2669     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, mRenderbuffer);
2670     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
2671                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
2672 
2673     ASSERT_GL_NO_ERROR();
2674 }
2675 
2676 // Test that the sample count of texture attachments should be same.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleSampleCountTex)2677 TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex)
2678 {
2679     GLFramebuffer mFramebuffer;
2680     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
2681 
2682     // Lookup the supported number of sample counts
2683     GLint numSampleCounts = 0;
2684     std::vector<GLint> sampleCounts;
2685     GLsizei queryBufferSize = 1;
2686     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
2687                           queryBufferSize, &numSampleCounts);
2688     ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
2689     sampleCounts.resize(numSampleCounts);
2690     queryBufferSize = numSampleCounts;
2691     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
2692                           sampleCounts.data());
2693 
2694     GLTexture mTextures[2];
2695     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0]);
2696     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
2697     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1]);
2698     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[1], GL_RGBA8, 1, 1, true);
2699     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2700                            mTextures[0], 0);
2701     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
2702                            mTextures[1], 0);
2703     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
2704                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
2705 
2706     ASSERT_GL_NO_ERROR();
2707 }
2708 
2709 // Test that if the attached images are a mix of renderbuffers and textures, the value of
2710 // TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleFixedSampleLocationsMix)2711 TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsMix)
2712 {
2713     GLFramebuffer mFramebuffer;
2714     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
2715 
2716     GLTexture mTexture;
2717     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture);
2718     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
2719 
2720     GLRenderbuffer mRenderbuffer;
2721     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
2722     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
2723     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2724                            mTexture, 0);
2725     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, mRenderbuffer);
2726     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
2727                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
2728 
2729     ASSERT_GL_NO_ERROR();
2730 }
2731 
2732 // Test that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleFixedSampleLocationsTex)2733 TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsTex)
2734 {
2735     GLFramebuffer mFramebuffer;
2736     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
2737 
2738     GLTexture mTextures[2];
2739     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0]);
2740     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
2741     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2742                            mTextures[0], 0);
2743     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1]);
2744     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGB8, 1, 1, true);
2745     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
2746                            mTextures[1], 0);
2747     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
2748                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
2749 
2750     ASSERT_GL_NO_ERROR();
2751 }
2752 
2753 // Tests that draw to Y-flipped FBO results in correct pixels.
TEST_P(FramebufferTest_ES31,BasicDrawToYFlippedFBO)2754 TEST_P(FramebufferTest_ES31, BasicDrawToYFlippedFBO)
2755 {
2756     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
2757 
2758     constexpr int kSize = 16;
2759     glViewport(0, 0, kSize, kSize);
2760 
2761     GLFramebuffer fbo;
2762     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2763 
2764     glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
2765 
2766     GLTexture texture;
2767     glBindTexture(GL_TEXTURE_2D, texture);
2768     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
2769     ASSERT_GL_NO_ERROR();
2770     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2771     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2772 
2773     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2774                      essl31_shaders::fs::RedGreenGradient());
2775     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2776     ASSERT_GL_NO_ERROR();
2777 
2778     // Remove the flag so that glReadPixels do not implicitly use that.
2779     glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
2780 
2781     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2782     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2783     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255,
2784                       1.0);
2785     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2786     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255,
2787                       1.0);
2788 }
2789 
2790 // Test resolving a multisampled texture with blit
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlit)2791 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlit)
2792 {
2793     constexpr int kSize = 16;
2794     glViewport(0, 0, kSize, kSize);
2795 
2796     GLFramebuffer msaaFBO;
2797     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
2798 
2799     GLTexture texture;
2800     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
2801     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2802     ASSERT_GL_NO_ERROR();
2803     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
2804                            0);
2805     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2806 
2807     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2808                      essl31_shaders::fs::RedGreenGradient());
2809     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2810     ASSERT_GL_NO_ERROR();
2811 
2812     // Create another FBO to resolve the multisample buffer into.
2813     GLTexture resolveTexture;
2814     GLFramebuffer resolveFBO;
2815     glBindTexture(GL_TEXTURE_2D, resolveTexture);
2816     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2817     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2818     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2819     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2820 
2821     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2822     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2823     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2824     ASSERT_GL_NO_ERROR();
2825 
2826     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2827     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2828     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2829     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2830     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2831     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2832                       255, 1.0);
2833 }
2834 
2835 // Test resolving a multisampled texture with blit to a different format
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitDifferentFormats)2836 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitDifferentFormats)
2837 {
2838     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888"));
2839 
2840     constexpr int kSize = 16;
2841     glViewport(0, 0, kSize, kSize);
2842 
2843     GLFramebuffer msaaFBO;
2844     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
2845 
2846     GLTexture texture;
2847     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
2848     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2849     ASSERT_GL_NO_ERROR();
2850     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
2851                            0);
2852     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2853 
2854     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2855                      essl31_shaders::fs::RedGreenGradient());
2856     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2857     ASSERT_GL_NO_ERROR();
2858 
2859     // Create another FBO to resolve the multisample buffer into.
2860     GLTexture resolveTexture;
2861     GLFramebuffer resolveFBO;
2862     glBindTexture(GL_TEXTURE_2D, resolveTexture);
2863     glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA8_EXT, kSize, kSize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
2864                  nullptr);
2865     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2866     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2867 
2868     // Another attachment of the same format as the blit source
2869     // to ensure that it does not confuse the backend.
2870     GLTexture resolveTexture2;
2871     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
2872     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2873     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, resolveTexture2, 0);
2874 
2875     GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
2876     glDrawBuffers(2, drawBuffers);
2877 
2878     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2879 
2880     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2881     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2882     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2883     ASSERT_GL_NO_ERROR();
2884 
2885     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2886     for (const GLenum buffer : {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1})
2887     {
2888         glReadBuffer(buffer);
2889         constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2890         EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2891         EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2892         EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2893         EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient,
2894                           0, 255, 1.0);
2895     }
2896 }
2897 
2898 // Test resolving a multisampled texture with blit after drawing to mulitiple FBOs.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitMultipleFBOs)2899 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitMultipleFBOs)
2900 {
2901     // FBO 1 -> multisample draw (red)
2902     // FBO 2 -> multisample draw (green)
2903     // Bind FBO 1 as read
2904     // Bind FBO 3 as draw
2905     // Resolve
2906 
2907     constexpr int kSize = 16;
2908     glViewport(0, 0, kSize, kSize);
2909 
2910     GLFramebuffer msaaFBORed;
2911     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBORed);
2912 
2913     GLTexture textureRed;
2914     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureRed);
2915     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2916     ASSERT_GL_NO_ERROR();
2917     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2918                            textureRed, 0);
2919     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2920 
2921     ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
2922     drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2923     ASSERT_GL_NO_ERROR();
2924 
2925     GLFramebuffer msaaFBOGreen;
2926     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBOGreen);
2927 
2928     GLTexture textureGreen;
2929     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureGreen);
2930     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2931     ASSERT_GL_NO_ERROR();
2932     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2933                            textureGreen, 0);
2934     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2935 
2936     ANGLE_GL_PROGRAM(greenProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Green());
2937     drawQuad(greenProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2938     ASSERT_GL_NO_ERROR();
2939 
2940     // Create another FBO to resolve the multisample buffer into.
2941     GLTexture resolveTexture;
2942     GLFramebuffer resolveFBO;
2943     glBindTexture(GL_TEXTURE_2D, resolveTexture);
2944     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2945     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2946     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2947     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2948 
2949     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
2950     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2951     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2952     ASSERT_GL_NO_ERROR();
2953 
2954     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2955     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2956 }
2957 
2958 // Test resolving a multisampled texture with blit after drawing to mulitiple FBOs.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitMultipleResolves)2959 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitMultipleResolves)
2960 {
2961     // Draw multisampled in FBO 1
2962     // Bind FBO 1 as read
2963     // Bind FBO 2 as draw
2964     // Resolve
2965     // Bind FBO 3 as draw
2966     // Resolve
2967 
2968     constexpr int kSize = 16;
2969     glViewport(0, 0, kSize, kSize);
2970 
2971     GLFramebuffer msaaFBORed;
2972     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBORed);
2973 
2974     GLTexture textureRed;
2975     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureRed);
2976     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2977     ASSERT_GL_NO_ERROR();
2978     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2979                            textureRed, 0);
2980     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2981 
2982     ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
2983     drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2984     ASSERT_GL_NO_ERROR();
2985 
2986     // Create another FBO to resolve the multisample buffer into.
2987     GLTexture resolveTexture1;
2988     GLFramebuffer resolveFBO1;
2989     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
2990     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2991     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
2992     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
2993     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2994 
2995     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
2996     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
2997     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2998     ASSERT_GL_NO_ERROR();
2999 
3000     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
3001     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3002 
3003     // Create another FBO to resolve the multisample buffer into.
3004     GLTexture resolveTexture2;
3005     GLFramebuffer resolveFBO2;
3006     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
3007     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3008     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
3009     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
3010     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3011 
3012     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
3013     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
3014     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3015     ASSERT_GL_NO_ERROR();
3016 
3017     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
3018     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3019 }
3020 
3021 // Test resolving a multisampled texture with blit into an FBO with different read and draw
3022 // attachments.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitDifferentReadDrawBuffers)3023 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitDifferentReadDrawBuffers)
3024 {
3025     constexpr int kSize = 16;
3026     glViewport(0, 0, kSize, kSize);
3027 
3028     GLFramebuffer msaaFBO;
3029     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3030 
3031     GLTexture texture;
3032     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
3033     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3034     ASSERT_GL_NO_ERROR();
3035     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
3036                            0);
3037     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3038 
3039     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
3040                      essl31_shaders::fs::RedGreenGradient());
3041     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3042     ASSERT_GL_NO_ERROR();
3043 
3044     // Create another FBO to resolve the multisample buffer into.
3045     GLFramebuffer resolveFBO;
3046     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
3047 
3048     // Bind both read and draw textures as separate attachments.
3049     const std::vector<GLColor> blueColors(kSize * kSize, GLColor::blue);
3050     GLTexture resolveReadTexture;
3051     glBindTexture(GL_TEXTURE_2D, resolveReadTexture);
3052     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3053                  blueColors.data());
3054     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveReadTexture,
3055                            0);
3056     glReadBuffer(GL_COLOR_ATTACHMENT0);
3057     ASSERT_GL_NO_ERROR();
3058 
3059     GLTexture resolveDrawTexture;
3060     glBindTexture(GL_TEXTURE_2D, resolveDrawTexture);
3061     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3062     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, resolveDrawTexture,
3063                            0);
3064     // Only enable color attachment 1 to be drawn to, since the Vulkan back end (currently) only
3065     // supports using resolve attachments when there is a single draw attachment enabled. This
3066     // ensures that the read and draw images are treated separately, including their layouts.
3067     GLenum drawBuffers[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
3068     glDrawBuffers(2, drawBuffers);
3069     ASSERT_GL_NO_ERROR();
3070     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3071 
3072     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3073     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3074     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3075     ASSERT_GL_NO_ERROR();
3076 
3077     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3078     glReadBuffer(GL_COLOR_ATTACHMENT1);
3079     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
3080     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3081     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3082     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3083     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3084                       255, 1.0);
3085 }
3086 
3087 // Test resolving a multisampled texture into a mipmaped texture with blit
TEST_P(FramebufferTest_ES31,MultisampleResolveIntoMipMapWithBlit)3088 TEST_P(FramebufferTest_ES31, MultisampleResolveIntoMipMapWithBlit)
3089 {
3090     // FBO 1 is attached to a 64x64 texture
3091     // FBO 2 attached to level 1 of a 128x128 texture
3092 
3093     constexpr int kSize = 64;
3094     glViewport(0, 0, kSize, kSize);
3095 
3096     // Create the textures early and call glGenerateMipmap() so it doesn't break the render pass
3097     // between the drawQuad() and glBlitFramebuffer(), so we can test the resolve with subpass path
3098     // in the Vulkan back end.
3099     GLTexture texture;
3100     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
3101     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3102     ASSERT_GL_NO_ERROR();
3103 
3104     GLTexture resolveTexture;
3105     glBindTexture(GL_TEXTURE_2D, resolveTexture);
3106     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3107     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
3108     ASSERT_GL_NO_ERROR();
3109 
3110     GLFramebuffer msaaFBO;
3111     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3112     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
3113                            0);
3114     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3115 
3116     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
3117                      essl31_shaders::fs::RedGreenGradient());
3118     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3119     ASSERT_GL_NO_ERROR();
3120 
3121     // Create another FBO to resolve the multisample buffer into.
3122     GLFramebuffer resolveFBO;
3123     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
3124     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
3125     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3126 
3127     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3128     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3129     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3130     ASSERT_GL_NO_ERROR();
3131 
3132     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3133     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
3134     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3135     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3136     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3137     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3138                       255, 1.0);
3139 }
3140 
3141 // Test resolving a multisampled texture with blit after drawing to multiple FBOs.
TEST_P(FramebufferTest_ES31,MultipleTextureMultisampleResolveWithBlitMultipleResolves)3142 TEST_P(FramebufferTest_ES31, MultipleTextureMultisampleResolveWithBlitMultipleResolves)
3143 {
3144     // Attach two MSAA textures to FBO1
3145     // Set read buffer 0
3146     // Resolve into FBO2
3147     // Set read buffer 1
3148     // Resolve into FBO3
3149 
3150     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
3151 
3152     constexpr int kSize = 16;
3153     glViewport(0, 0, kSize, kSize);
3154 
3155     GLFramebuffer msaaFBO;
3156     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3157 
3158     GLTexture msaaTextureRed;
3159     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed);
3160     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3161     ASSERT_GL_NO_ERROR();
3162     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
3163                            msaaTextureRed, 0);
3164     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3165 
3166     GLTexture msaaTextureGreen;
3167     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen);
3168     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3169     ASSERT_GL_NO_ERROR();
3170     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
3171                            msaaTextureGreen, 0);
3172     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3173 
3174     // Setup program to render red into attachment 0 and green into attachment 1.
3175     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
3176     glUseProgram(program);
3177     constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
3178     glDrawBuffers(2, kDrawBuffers);
3179 
3180     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3181     ASSERT_GL_NO_ERROR();
3182 
3183     // Create another FBO to resolve the multisample buffer into.
3184     GLTexture resolveTexture1;
3185     GLFramebuffer resolveFBO1;
3186     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
3187     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3188     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
3189     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
3190     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3191 
3192     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3193     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
3194     glReadBuffer(GL_COLOR_ATTACHMENT0);  // Red
3195     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3196     ASSERT_GL_NO_ERROR();
3197 
3198     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
3199     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3200 
3201     // Create another FBO to resolve the multisample buffer into.
3202     GLTexture resolveTexture2;
3203     GLFramebuffer resolveFBO2;
3204     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
3205     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3206     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
3207     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
3208     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3209 
3210     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3211     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
3212     glReadBuffer(GL_COLOR_ATTACHMENT1);  // Green
3213     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3214     ASSERT_GL_NO_ERROR();
3215 
3216     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
3217     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3218 }
3219 
3220 // Test resolving a multisampled texture with blit after drawing to multiple FBOs, with color
3221 // attachment 1 resolved first.
TEST_P(FramebufferTest_ES31,MultipleTextureMultisampleResolveWithBlitMultipleResolvesAttachment1First)3222 TEST_P(FramebufferTest_ES31,
3223        MultipleTextureMultisampleResolveWithBlitMultipleResolvesAttachment1First)
3224 {
3225     // Attach two MSAA textures to FBO1
3226     // Set read buffer 1
3227     // Resolve into FBO2
3228     // Set read buffer 0
3229     // Resolve into FBO3
3230 
3231     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
3232 
3233     constexpr int kSize = 16;
3234     glViewport(0, 0, kSize, kSize);
3235 
3236     GLFramebuffer msaaFBO;
3237     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3238 
3239     GLTexture msaaTextureRed;
3240     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed);
3241     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3242     ASSERT_GL_NO_ERROR();
3243     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
3244                            msaaTextureRed, 0);
3245     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3246 
3247     GLTexture msaaTextureGreen;
3248     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen);
3249     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3250     ASSERT_GL_NO_ERROR();
3251     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
3252                            msaaTextureGreen, 0);
3253     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3254 
3255     // Setup program to render red into attachment 0 and green into attachment 1.
3256     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
3257     glUseProgram(program);
3258     constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
3259     glDrawBuffers(2, kDrawBuffers);
3260 
3261     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3262     ASSERT_GL_NO_ERROR();
3263 
3264     // Create another FBO to resolve the multisample buffer into.
3265     GLTexture resolveTexture1;
3266     GLFramebuffer resolveFBO1;
3267     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
3268     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3269     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
3270     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
3271     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3272 
3273     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3274     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
3275     glReadBuffer(GL_COLOR_ATTACHMENT1);  // Green
3276     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3277     ASSERT_GL_NO_ERROR();
3278 
3279     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
3280     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3281 
3282     // Create another FBO to resolve the multisample buffer into.
3283     GLTexture resolveTexture2;
3284     GLFramebuffer resolveFBO2;
3285     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
3286     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3287     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
3288     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
3289     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3290 
3291     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3292     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
3293     glReadBuffer(GL_COLOR_ATTACHMENT0);  // Red
3294     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3295     ASSERT_GL_NO_ERROR();
3296 
3297     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
3298     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3299 }
3300 
3301 // Test resolving a multisampled texture with blit, then drawing multisampled again.  The latter
3302 // should not get re-resolved automatically.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDraw)3303 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDraw)
3304 {
3305     constexpr int kSize = 16;
3306     glViewport(0, 0, kSize, kSize);
3307 
3308     GLFramebuffer msaaFBO;
3309     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3310 
3311     GLTexture texture;
3312     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
3313     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3314     ASSERT_GL_NO_ERROR();
3315     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
3316                            0);
3317     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3318 
3319     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
3320                      essl31_shaders::fs::RedGreenGradient());
3321     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3322     ASSERT_GL_NO_ERROR();
3323 
3324     // Create another FBO to resolve the multisample buffer into.
3325     GLTexture resolveTexture;
3326     GLFramebuffer resolveFBO;
3327     glBindTexture(GL_TEXTURE_2D, resolveTexture);
3328     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3329     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
3330     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
3331     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3332 
3333     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3334     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3335     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3336     ASSERT_GL_NO_ERROR();
3337 
3338     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3339     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
3340     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3341     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3342     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3343     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3344                       255, 1.0);
3345 
3346     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
3347     ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
3348     drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3349     ASSERT_GL_NO_ERROR();
3350 
3351     // The resolved FBO should be unaffected by the last draw call.
3352     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3353     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3354     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3355     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3356                       255, 1.0);
3357 }
3358 
3359 // Test resolving a multisampled texture with blit, then drawing multisampled again.  The latter
3360 // should not get re-resolved automatically.  Resoloves color attachment 1.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDrawAttachment1)3361 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawAttachment1)
3362 {
3363     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
3364 
3365     constexpr int kSize = 16;
3366     glViewport(0, 0, kSize, kSize);
3367 
3368     GLFramebuffer msaaFBO;
3369     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3370 
3371     GLTexture msaaTextureRed;
3372     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed);
3373     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3374     ASSERT_GL_NO_ERROR();
3375     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
3376                            msaaTextureRed, 0);
3377     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3378 
3379     GLTexture msaaTextureGreen;
3380     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen);
3381     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3382     ASSERT_GL_NO_ERROR();
3383     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
3384                            msaaTextureGreen, 0);
3385     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3386 
3387     // Setup program to render red into attachment 0 and green into attachment 1.
3388     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
3389     glUseProgram(program);
3390     constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
3391     glDrawBuffers(2, kDrawBuffers);
3392 
3393     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3394     ASSERT_GL_NO_ERROR();
3395 
3396     // Create another FBO to resolve the multisample buffer into.
3397     GLTexture resolveTexture;
3398     GLFramebuffer resolveFBO;
3399     glBindTexture(GL_TEXTURE_2D, resolveTexture);
3400     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3401     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
3402     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
3403     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3404 
3405     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3406     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3407     glReadBuffer(GL_COLOR_ATTACHMENT1);  // Green
3408     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3409     ASSERT_GL_NO_ERROR();
3410 
3411     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3412     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3413     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
3414     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
3415     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
3416 
3417     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
3418     ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
3419     drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3420     ASSERT_GL_NO_ERROR();
3421 
3422     // The resolved FBO should be unaffected by the last draw call.
3423     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3424     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
3425     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
3426     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
3427 }
3428 
3429 // Test resolving a multisampled texture with blit, then drawing multisampled again and resolving to
3430 // same framebuffer.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDrawThenResolveAgain)3431 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawThenResolveAgain)
3432 {
3433     constexpr int kSize = 16;
3434     glViewport(0, 0, kSize, kSize);
3435 
3436     GLFramebuffer msaaFBO;
3437     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3438 
3439     GLTexture texture;
3440     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
3441     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3442     ASSERT_GL_NO_ERROR();
3443     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
3444                            0);
3445     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3446 
3447     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
3448                      essl31_shaders::fs::RedGreenGradient());
3449     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3450     ASSERT_GL_NO_ERROR();
3451 
3452     // Create another FBO to resolve the multisample buffer into.
3453     GLTexture resolveTexture;
3454     GLFramebuffer resolveFBO;
3455     glBindTexture(GL_TEXTURE_2D, resolveTexture);
3456     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3457     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
3458     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
3459     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3460 
3461     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3462     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3463     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3464     ASSERT_GL_NO_ERROR();
3465 
3466     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3467     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
3468     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3469     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3470     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3471     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3472                       255, 1.0);
3473 
3474     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
3475     ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
3476     drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3477     ASSERT_GL_NO_ERROR();
3478 
3479     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3480     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3481     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3482     ASSERT_GL_NO_ERROR();
3483 
3484     // Verify that the resolve happened correctly
3485     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3486     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3487     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
3488     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
3489     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
3490 }
3491 
3492 // Test resolving a multisampled texture with blit, then drawing multisampled again and resolving to
3493 // another framebuffer.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDrawThenResolveAgainToDifferentFBO)3494 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawThenResolveAgainToDifferentFBO)
3495 {
3496     constexpr int kSize = 16;
3497     glViewport(0, 0, kSize, kSize);
3498 
3499     GLFramebuffer msaaFBO;
3500     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3501 
3502     GLTexture texture;
3503     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
3504     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
3505     ASSERT_GL_NO_ERROR();
3506     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
3507                            0);
3508     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3509 
3510     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
3511                      essl31_shaders::fs::RedGreenGradient());
3512     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3513     ASSERT_GL_NO_ERROR();
3514 
3515     // Create another FBO to resolve the multisample buffer into.
3516     GLTexture resolveTexture1;
3517     GLFramebuffer resolveFBO1;
3518     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
3519     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3520     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
3521     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
3522     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3523 
3524     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3525     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
3526     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3527     ASSERT_GL_NO_ERROR();
3528 
3529     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
3530     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
3531     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3532     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3533     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3534     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3535                       255, 1.0);
3536 
3537     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
3538     ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
3539     drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3540     ASSERT_GL_NO_ERROR();
3541 
3542     // Create another FBO to resolve the multisample buffer into.
3543     GLTexture resolveTexture2;
3544     GLFramebuffer resolveFBO2;
3545     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
3546     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3547     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
3548     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
3549     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3550 
3551     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3552     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
3553     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
3554     ASSERT_GL_NO_ERROR();
3555 
3556     // Verify that the resolve happened to the correct FBO
3557     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
3558     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3559     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
3560     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
3561     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
3562 
3563     // The first resolve FBO should be untouched.
3564     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
3565     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3566     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
3567     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
3568     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
3569                       255, 1.0);
3570 }
3571 
3572 // Test resolving a multisampled texture with blit to a non-zero level.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitNonZeroLevel)3573 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitNonZeroLevel)
3574 {
3575     constexpr int kWidth  = 16;
3576     constexpr int kHeight = 20;
3577     glViewport(0, 0, kWidth, kHeight);
3578 
3579     GLFramebuffer msaaFBO;
3580     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
3581 
3582     GLTexture texture;
3583     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
3584     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
3585     ASSERT_GL_NO_ERROR();
3586     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
3587                            0);
3588     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3589 
3590     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
3591                      essl31_shaders::fs::RedGreenGradient());
3592     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3593     ASSERT_GL_NO_ERROR();
3594 
3595     // Create a resolve FBO and texture. The multisample buffer will be resolved into level 1 of the
3596     // bound texture, which has the same dimensions as the multisampled texture.
3597     GLTexture resolveTexture;
3598     glBindTexture(GL_TEXTURE_2D, resolveTexture);
3599     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kWidth * 2, kHeight * 2);
3600 
3601     GLFramebuffer resolveFBO;
3602     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
3603     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
3604     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3605 
3606     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
3607     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
3608     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
3609                       GL_NEAREST);
3610     ASSERT_GL_NO_ERROR();
3611 
3612     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
3613     constexpr uint8_t kWidthHalfPixelGradient  = 256 / kWidth / 2;
3614     constexpr uint8_t kHeightHalfPixelGradient = 256 / kHeight / 2;
3615     EXPECT_PIXEL_NEAR(0, 0, kWidthHalfPixelGradient, kHeightHalfPixelGradient, 0, 255, 1.0);
3616     EXPECT_PIXEL_NEAR(kWidth - 1, 0, 255 - kWidthHalfPixelGradient, kHeightHalfPixelGradient, 0,
3617                       255, 1.0);
3618     EXPECT_PIXEL_NEAR(0, kHeight - 1, kWidthHalfPixelGradient, 255 - kHeightHalfPixelGradient, 0,
3619                       255, 1.0);
3620     EXPECT_PIXEL_NEAR(kWidth - 1, kHeight - 1, 255 - kWidthHalfPixelGradient,
3621                       255 - kHeightHalfPixelGradient, 0, 255, 1.0);
3622 }
3623 
3624 // If there are no attachments, rendering will be limited to a rectangle having a lower left of
3625 // (0, 0) and an upper right of(width, height), where width and height are the framebuffer
3626 // object's default width and height.
TEST_P(FramebufferTest_ES31,RenderingLimitToDefaultFBOSizeWithNoAttachments)3627 TEST_P(FramebufferTest_ES31, RenderingLimitToDefaultFBOSizeWithNoAttachments)
3628 {
3629     // anglebug.com/2253
3630     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
3631 
3632     constexpr char kVS1[] = R"(#version 310 es
3633 in layout(location = 0) highp vec2 a_position;
3634 void main()
3635 {
3636     gl_Position = vec4(a_position, 0.0, 1.0);
3637 })";
3638 
3639     constexpr char kFS1[] = R"(#version 310 es
3640 uniform layout(location = 0) highp ivec2 u_expectedSize;
3641 out layout(location = 3) mediump vec4 f_color;
3642 void main()
3643 {
3644     if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
3645     f_color = vec4(1.0, 0.5, 0.25, 1.0);
3646 })";
3647 
3648     constexpr char kVS2[] = R"(#version 310 es
3649 in layout(location = 0) highp vec2 a_position;
3650 void main()
3651 {
3652     gl_Position = vec4(a_position, 0.0, 1.0);
3653 })";
3654 
3655     constexpr char kFS2[] = R"(#version 310 es
3656 uniform layout(location = 0) highp ivec2 u_expectedSize;
3657 out layout(location = 2) mediump vec4 f_color;
3658 void main()
3659 {
3660     if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
3661     f_color = vec4(1.0, 0.5, 0.25, 1.0);
3662 })";
3663 
3664     ANGLE_GL_PROGRAM(program1, kVS1, kFS1);
3665     ANGLE_GL_PROGRAM(program2, kVS2, kFS2);
3666 
3667     glUseProgram(program1);
3668 
3669     GLFramebuffer mFramebuffer;
3670     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
3671     GLuint defaultWidth  = 1;
3672     GLuint defaultHeight = 1;
3673 
3674     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3675     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3676     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3677 
3678     const float data[] = {
3679         1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
3680     };
3681 
3682     GLQuery query;
3683 
3684     GLVertexArray vertexArray;
3685     glBindVertexArray(vertexArray);
3686 
3687     GLBuffer vertexBuffer;
3688     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3689     glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
3690 
3691     glEnableVertexAttribArray(0);
3692     glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
3693     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3694 
3695     validateSamplePass(query, defaultWidth, defaultHeight);
3696 
3697     glUseProgram(program2);
3698     validateSamplePass(query, defaultWidth, defaultHeight);
3699 
3700     glUseProgram(program1);
3701     // If fbo has attachments, the rendering size should be the same as its attachment.
3702     GLTexture mTexture;
3703     GLuint width  = 2;
3704     GLuint height = 2;
3705     glBindTexture(GL_TEXTURE_2D, mTexture);
3706     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
3707 
3708     const GLenum bufs[] = {GL_NONE, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT3};
3709 
3710     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, mTexture, 0);
3711     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3712     glDrawBuffers(4, bufs);
3713 
3714     validateSamplePass(query, width, height);
3715 
3716     // If fbo's attachment has been removed, the rendering size should be the same as framebuffer
3717     // default size.
3718     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, 0, 0, 0);
3719     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3720 
3721     validateSamplePass(query, defaultWidth, defaultHeight);
3722     ASSERT_GL_NO_ERROR();
3723 }
3724 
3725 // Creating two attachmentless framebuffers should work without vvl error.
TEST_P(FramebufferTest_ES31,CreateNoAttachmentFBOWithDifferentSize)3726 TEST_P(FramebufferTest_ES31, CreateNoAttachmentFBOWithDifferentSize)
3727 {
3728     constexpr char kVS1[] = R"(#version 310 es
3729 in layout(location = 0) highp vec2 a_position;
3730 void main()
3731 {
3732     gl_Position = vec4(a_position, 0.0, 1.0);
3733 })";
3734 
3735     constexpr char kFS1[] = R"(#version 310 es
3736 uniform layout(location = 0) highp ivec2 u_expectedSize;
3737 out layout(location = 3) mediump vec4 f_color;
3738 void main()
3739 {
3740     if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
3741     f_color = vec4(1.0, 0.5, 0.25, 1.0);
3742 })";
3743     ANGLE_GL_PROGRAM(program1, kVS1, kFS1);
3744     glUseProgram(program1);
3745 
3746     GLBuffer vertexBuffer;
3747     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3748     const float data[] = {
3749         1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
3750     };
3751     glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
3752     glEnableVertexAttribArray(0);
3753     glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
3754 
3755     GLQuery query;
3756 
3757     // Test that:
3758     // 1. create 1st no-attachment framebuffer with size 1*1, draw, delete framebuffer
3759     // 2. create 2nd no-attachment framebuffer with size 2*2, draw, delete framebuffer
3760     // works properly
3761     for (int loop = 0; loop < 2; loop++)
3762     {
3763         GLFramebuffer framebuffer;
3764         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
3765         GLuint defaultWidth  = 1 << loop;
3766         GLuint defaultHeight = 1 << loop;
3767         glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3768         glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3769         EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3770 
3771         // Draw and check the FBO size
3772         validateSamplePass(query, defaultWidth, defaultHeight);
3773     }
3774 
3775     ASSERT_GL_NO_ERROR();
3776 
3777     // Test that:
3778     // 1. create 1st no-attachment framebuffer with size 2*2, draw, delete framebuffer
3779     // 2. create 2nd no-attachment framebuffer with size 1*1, draw, delete framebuffer
3780     // works properly
3781     for (int loop = 1; loop >= 0; loop--)
3782     {
3783         GLFramebuffer framebuffer;
3784         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
3785         GLuint defaultWidth  = 1 << loop;
3786         GLuint defaultHeight = 1 << loop;
3787         glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3788         glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3789         EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3790 
3791         // Draw and check the FBO size
3792         validateSamplePass(query, defaultWidth, defaultHeight);
3793     }
3794 
3795     ASSERT_GL_NO_ERROR();
3796 }
3797 
3798 // Altering the default width and height of attachmentless framebuffer should work fine
TEST_P(FramebufferTest_ES31,ChangeFBOSizeWithNoAttachments)3799 TEST_P(FramebufferTest_ES31, ChangeFBOSizeWithNoAttachments)
3800 {
3801     constexpr char kVS1[] = R"(#version 310 es
3802 in layout(location = 0) highp vec2 a_position;
3803 void main()
3804 {
3805     gl_Position = vec4(a_position, 0.0, 1.0);
3806 })";
3807 
3808     constexpr char kFS1[] = R"(#version 310 es
3809 uniform layout(location = 0) highp ivec2 u_expectedSize;
3810 out layout(location = 3) mediump vec4 f_color;
3811 void main()
3812 {
3813     if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
3814     f_color = vec4(1.0, 0.5, 0.25, 1.0);
3815 })";
3816     ANGLE_GL_PROGRAM(program1, kVS1, kFS1);
3817     glUseProgram(program1);
3818 
3819     GLBuffer vertexBuffer;
3820     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3821     const float data[] = {
3822         1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
3823     };
3824     glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
3825     glEnableVertexAttribArray(0);
3826     glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
3827 
3828     GLQuery query;
3829 
3830     // Test that:
3831     // 1. create a no-attachment framebuffer with size 1*1, draw
3832     // 2. change the no-attachment framebuffer size to 2*2, draw
3833     // works properly
3834     GLFramebuffer framebufferWithVariousSizeGrow;
3835     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferWithVariousSizeGrow);
3836     for (int loop = 0; loop < 2; loop++)
3837     {
3838         GLuint defaultWidth  = 1 << loop;
3839         GLuint defaultHeight = 1 << loop;
3840         glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3841         glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3842         EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3843 
3844         // Draw and check the FBO size
3845         validateSamplePass(query, defaultWidth, defaultHeight);
3846     }
3847 
3848     ASSERT_GL_NO_ERROR();
3849 
3850     // Test that:
3851     // 1. create a no-attachment framebuffer with size 2*2, draw
3852     // 2. change the no-attachment framebuffer size to 1*1, draw
3853     // works properly
3854     GLFramebuffer framebufferWithVariousSizeShrink;
3855     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferWithVariousSizeShrink);
3856     for (int loop = 1; loop >= 0; loop--)
3857     {
3858         GLuint defaultWidth  = 1 << loop;
3859         GLuint defaultHeight = 1 << loop;
3860         glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3861         glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3862         EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3863 
3864         // Draw and check the FBO size
3865         validateSamplePass(query, defaultWidth, defaultHeight);
3866     }
3867 
3868     ASSERT_GL_NO_ERROR();
3869 }
3870 
3871 // Test that changing framebuffer attachment count and its' default width and height work properly
TEST_P(FramebufferTest_ES31,ChangeFBOSizeAndAttachmentsCount)3872 TEST_P(FramebufferTest_ES31, ChangeFBOSizeAndAttachmentsCount)
3873 {
3874     constexpr char kVS1[] = R"(#version 310 es
3875 in layout(location = 0) highp vec2 a_position;
3876 void main()
3877 {
3878     gl_Position = vec4(a_position, 0.0, 1.0);
3879 })";
3880 
3881     constexpr char kFS1[] = R"(#version 310 es
3882 uniform layout(location = 0) highp ivec2 u_expectedSize;
3883 out layout(location = 3) mediump vec4 f_color;
3884 void main()
3885 {
3886     if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
3887     f_color = vec4(1.0, 0.5, 0.25, 1.0);
3888 })";
3889     ANGLE_GL_PROGRAM(program1, kVS1, kFS1);
3890     glUseProgram(program1);
3891 
3892     GLBuffer vertexBuffer;
3893     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3894     const float data[] = {
3895         1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
3896     };
3897     glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
3898     glEnableVertexAttribArray(0);
3899     glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
3900 
3901     GLQuery query;
3902 
3903     // 1. create a no-attachment framebuffer with default size 1*1, draw
3904     // 2. give the fbo with 1 color attachment with size 2*2, draw
3905     // 3. change the fbo default size to 3*3, draw
3906     // 4. remove the fbo attachment, draw
3907     // works properly
3908     GLFramebuffer framebufferWithVariousSizeAndAttachmentGrow;
3909     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferWithVariousSizeAndAttachmentGrow);
3910     GLuint defaultWidth  = 1;
3911     GLuint defaultHeight = 1;
3912     glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3913     glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3914     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3915     validateSamplePass(query, defaultWidth, defaultHeight);
3916 
3917     GLTexture mTexture;
3918     glBindTexture(GL_TEXTURE_2D, mTexture);
3919     GLuint attachmentWidth  = 2;
3920     GLuint attachmentHeight = 2;
3921     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, attachmentWidth, attachmentHeight);
3922     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
3923     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3924     validateSamplePass(query, attachmentWidth, attachmentWidth);
3925 
3926     defaultWidth  = 3;
3927     defaultHeight = 3;
3928     glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3929     glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3930     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3931     validateSamplePass(query, attachmentWidth, attachmentHeight);
3932 
3933     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0);
3934     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3935     validateSamplePass(query, defaultWidth, defaultHeight);
3936 
3937     ASSERT_GL_NO_ERROR();
3938 
3939     // 1. create a no-attachment framebuffer with default size 3*3, draw
3940     // 2. give the fbo with 1 color attachment with size 2*2, draw
3941     // 3. change the fbo default size to 1*1, draw
3942     // 4. remove the fbo attachment, draw
3943     // works properly
3944     GLFramebuffer framebufferWithVariousSizeAndAttachmentShrink;
3945     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferWithVariousSizeAndAttachmentShrink);
3946     glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3947     glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3948     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3949     validateSamplePass(query, defaultWidth, defaultHeight);
3950 
3951     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
3952     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3953     validateSamplePass(query, attachmentWidth, attachmentHeight);
3954 
3955     defaultWidth  = 1;
3956     defaultHeight = 1;
3957     glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
3958     glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
3959     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3960     validateSamplePass(query, attachmentWidth, attachmentHeight);
3961 
3962     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0);
3963     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
3964     validateSamplePass(query, defaultWidth, defaultHeight);
3965 
3966     ASSERT_GL_NO_ERROR();
3967 }
3968 
3969 // Test binding two textures with different widths to an FBO and drawing to it.
TEST_P(FramebufferTest_ES31,BindTexturesOfDifferentWidthsToFBOAndDraw)3970 TEST_P(FramebufferTest_ES31, BindTexturesOfDifferentWidthsToFBOAndDraw)
3971 {
3972     constexpr GLuint kSize = 2;
3973 
3974     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
3975 
3976     GLTexture colorTexture;
3977     glBindTexture(GL_TEXTURE_2D, colorTexture);
3978     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3979 
3980     GLFramebuffer fbo;
3981     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3982     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3983     ASSERT_GL_NO_ERROR();
3984     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3985 
3986     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3987     ASSERT_GL_NO_ERROR();
3988     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
3989 
3990     // The second texture is defined with double the width as the first.
3991     GLTexture colorTexture2;
3992     glBindTexture(GL_TEXTURE_2D, colorTexture2);
3993     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize * 2, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3994                  nullptr);
3995 
3996     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3997     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture2, 0);
3998     ASSERT_GL_NO_ERROR();
3999     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4000 
4001     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4002     ASSERT_GL_NO_ERROR();
4003     EXPECT_PIXEL_RECT_EQ(0, 0, kSize * 2, kSize, GLColor::green);
4004 }
4005 
4006 // Test binding two textures with different heights to an FBO and drawing to it.
TEST_P(FramebufferTest_ES31,BindTexturesOfDifferentHeightsToFBOAndDraw)4007 TEST_P(FramebufferTest_ES31, BindTexturesOfDifferentHeightsToFBOAndDraw)
4008 {
4009     constexpr GLuint kSize = 2;
4010 
4011     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4012 
4013     GLTexture colorTexture;
4014     glBindTexture(GL_TEXTURE_2D, colorTexture);
4015     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4016 
4017     GLFramebuffer fbo;
4018     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4019     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4020     ASSERT_GL_NO_ERROR();
4021     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4022 
4023     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4024     ASSERT_GL_NO_ERROR();
4025     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4026 
4027     // The second texture is defined with double the height as the first.
4028     GLTexture colorTexture2;
4029     glBindTexture(GL_TEXTURE_2D, colorTexture2);
4030     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize * 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4031                  nullptr);
4032 
4033     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4034     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture2, 0);
4035     ASSERT_GL_NO_ERROR();
4036     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4037 
4038     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4039     ASSERT_GL_NO_ERROR();
4040     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize * 2, GLColor::green);
4041 }
4042 
4043 // Test binding two textures with different formats to an FBO and drawing to it.
TEST_P(FramebufferTest_ES31,BindTexturesOfDifferentFormatsToFBOAndDraw)4044 TEST_P(FramebufferTest_ES31, BindTexturesOfDifferentFormatsToFBOAndDraw)
4045 {
4046     constexpr GLuint kSize = 2;
4047 
4048     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
4049 
4050     GLTexture colorTexture;
4051     glBindTexture(GL_TEXTURE_2D, colorTexture);
4052     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4053 
4054     GLFramebuffer fbo;
4055     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4056     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4057     ASSERT_GL_NO_ERROR();
4058     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4059 
4060     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4061     ASSERT_GL_NO_ERROR();
4062     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
4063 
4064     // The second texture is defined with R8 as its format.
4065     GLTexture colorTexture2;
4066     glBindTexture(GL_TEXTURE_2D, colorTexture2);
4067     glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, kSize, kSize, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
4068 
4069     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4070     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture2, 0);
4071     ASSERT_GL_NO_ERROR();
4072     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4073 
4074     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4075     ASSERT_GL_NO_ERROR();
4076     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
4077 }
4078 
4079 // Test binding two textures with different attachments to an FBO and drawing to it.
TEST_P(FramebufferTest_ES31,BindTexturesOfDifferentAttachmentsToFBOAndDraw)4080 TEST_P(FramebufferTest_ES31, BindTexturesOfDifferentAttachmentsToFBOAndDraw)
4081 {
4082     constexpr GLuint kSize = 2;
4083 
4084     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4085 
4086     GLTexture colorTexture;
4087     glBindTexture(GL_TEXTURE_2D, colorTexture);
4088     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4089 
4090     GLFramebuffer fbo;
4091     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4092     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4093     ASSERT_GL_NO_ERROR();
4094     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4095 
4096     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4097     ASSERT_GL_NO_ERROR();
4098     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4099 
4100     // The second texture has an additional depth attachment.
4101     GLTexture colorTexture2;
4102     glBindTexture(GL_TEXTURE_2D, colorTexture2);
4103     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4104     ASSERT_GL_NO_ERROR();
4105 
4106     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4107     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture2, 0);
4108 
4109     GLRenderbuffer depthBuffer;
4110     glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
4111     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kSize, kSize);
4112     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
4113 
4114     ASSERT_GL_NO_ERROR();
4115     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4116 
4117     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4118     ASSERT_GL_NO_ERROR();
4119     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4120 }
4121 
4122 // Test binding two textures with different create flags to an FBO and drawing to it.
TEST_P(FramebufferTest_ES31,BindTexturesOfDifferentCreateFlagsToFBOAndDraw)4123 TEST_P(FramebufferTest_ES31, BindTexturesOfDifferentCreateFlagsToFBOAndDraw)
4124 {
4125     constexpr GLuint kSize = 2;
4126 
4127     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4128 
4129     GLTexture colorTexture;
4130     glBindTexture(GL_TEXTURE_2D, colorTexture);
4131     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4132 
4133     GLFramebuffer fbo;
4134     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4135     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4136     ASSERT_GL_NO_ERROR();
4137     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4138 
4139     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4140     ASSERT_GL_NO_ERROR();
4141     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4142 
4143     // The second texture is defined as a cubemap, changing its create flags.
4144     GLTexture colorTexture2;
4145     glBindTexture(GL_TEXTURE_CUBE_MAP, colorTexture2);
4146 
4147     for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
4148     {
4149         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, 0, GL_RGBA8, kSize, kSize, 0,
4150                      GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4151     }
4152     ASSERT_GL_NO_ERROR();
4153 
4154     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4155     for (size_t faceIndex = 0; faceIndex < 6; ++faceIndex)
4156     {
4157         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4158                                GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, colorTexture2, 0);
4159     }
4160     ASSERT_GL_NO_ERROR();
4161 
4162     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4163 
4164     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4165     ASSERT_GL_NO_ERROR();
4166     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4167 }
4168 
4169 // Test binding two textures with different usage flags to an FBO and drawing to it.
TEST_P(FramebufferTest_ES31,BindTexturesOfDifferentUsageFlagsToFBOAndDraw)4170 TEST_P(FramebufferTest_ES31, BindTexturesOfDifferentUsageFlagsToFBOAndDraw)
4171 {
4172     constexpr GLuint kSize = 2;
4173 
4174     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4175 
4176     GLTexture colorTexture;
4177     glBindTexture(GL_TEXTURE_2D, colorTexture);
4178     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4179 
4180     GLFramebuffer fbo;
4181     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4182     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4183     ASSERT_GL_NO_ERROR();
4184     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4185 
4186     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4187     ASSERT_GL_NO_ERROR();
4188     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4189 
4190     // The second texture is used in a compute shader before the original shader, adding the storage
4191     // bit to its usage bits.
4192     GLTexture colorTexture2;
4193     glBindTexture(GL_TEXTURE_2D, colorTexture2);
4194     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4195     ASSERT_GL_NO_ERROR();
4196 
4197     constexpr char kCS[] = R"(#version 310 es
4198 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4199 uniform vec4 data;
4200 layout(rgba8, binding = 0) writeonly uniform highp image2D image;
4201 
4202 void main()
4203 {
4204     imageStore(image, ivec2(gl_LocalInvocationID.xy), data);
4205 })";
4206 
4207     GLuint computeProgram = CompileComputeProgram(kCS);
4208     ASSERT_NE(computeProgram, 0u);
4209     glUseProgram(computeProgram);
4210 
4211     glBindImageTexture(0, colorTexture2, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
4212 
4213     GLint uniformLoc = glGetUniformLocation(computeProgram, "data");
4214     ASSERT_NE(uniformLoc, -1);
4215     glUniform4f(uniformLoc, 0.0f, 0.0f, 1.0f, 1.0f);
4216 
4217     glDispatchCompute(1, 1, 1);
4218     EXPECT_GL_NO_ERROR();
4219 
4220     glUseProgram(program);
4221     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4222     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture2, 0);
4223     ASSERT_GL_NO_ERROR();
4224     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4225 
4226     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4227     ASSERT_GL_NO_ERROR();
4228     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
4229 }
4230 
4231 // Test that clear with color masks on framebuffer texture with internal format GL_RGB5_A1 works
4232 // This is a simplified version of below two deqp tests:
4233 // KHR-GLES31.core.draw_buffers_indexed.color_masks
4234 // KHR-GLES32.core.draw_buffers_indexed.color_masks
TEST_P(FramebufferTest_ES31,ClearWithColorMasksRGB5A1)4235 TEST_P(FramebufferTest_ES31, ClearWithColorMasksRGB5A1)
4236 {
4237     constexpr int kSize  = 4;
4238     GLint maxDrawBuffers = 0;
4239     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
4240     GLFramebuffer fbo;
4241     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4242 
4243     std::vector<GLenum> bufs(maxDrawBuffers);
4244     for (int i = 0; i < maxDrawBuffers; ++i)
4245     {
4246         bufs[i] = GL_COLOR_ATTACHMENT0 + i;
4247     }
4248 
4249     // Specifies a list of color buffers to be drawn into
4250     glDrawBuffers(maxDrawBuffers, &bufs[0]);
4251 
4252     glDisable(GL_DITHER);
4253 
4254     // Attach textures with internal format GL_RGB5_A1 to each framebuffer color attachment
4255     GLTexture textures[maxDrawBuffers];
4256     std::vector<unsigned char> pixelData(kSize * kSize * 4, 255);
4257     for (int i = 0; i < maxDrawBuffers; ++i)
4258     {
4259         glBindTexture(GL_TEXTURE_2D, textures[i]);
4260         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4261                      pixelData.data());
4262         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, textures[i],
4263                                0);
4264     }
4265 
4266     ASSERT_GL_NO_ERROR();
4267     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4268 
4269     // Clear all buffers with clear color (0.15f, 0.3f, 0.45f, 0.6f)
4270     angle::Vector4 clearColor(0.15f, 0.3f, 0.45f, 0.6f);
4271     for (int i = 0; i < maxDrawBuffers; ++i)
4272     {
4273         glClearBufferfv(GL_COLOR, i, clearColor.data());
4274     }
4275 
4276     ASSERT_GL_NO_ERROR();
4277 
4278     // Set color masks
4279     for (int i = 0; i < maxDrawBuffers; ++i)
4280     {
4281         if (i % 4 == 0)
4282         {
4283             glColorMaski(i, GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
4284         }
4285 
4286         if (i % 4 == 1)
4287         {
4288             glColorMaski(i, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
4289         }
4290 
4291         if (i % 4 == 2)
4292         {
4293             glColorMaski(i, GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
4294         }
4295 
4296         if (i % 4 == 3)
4297         {
4298             glColorMaski(i, GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
4299         }
4300     }
4301 
4302     ASSERT_GL_NO_ERROR();
4303 
4304     // Clear buffers again with a new clear color (0.85f, 0.85f, 0.85f, 0.85f)
4305     // Only the channel with color mask set to GL_TRUE is cleared with the new color.
4306     clearColor = {0.85f, 0.85f, 0.85f, 0.85f};
4307     for (int i = 0; i < maxDrawBuffers; ++i)
4308     {
4309         glClearBufferfv(GL_COLOR, i, &clearColor[0]);
4310     }
4311 
4312     ASSERT_GL_NO_ERROR();
4313 
4314     // Read and Verify
4315     // calculate the comparison epsilon based on the number of bits
4316     std::vector<int> bits        = {0, 0, 0, 0};
4317     std::vector<uint8_t> epsilon = {0, 0, 0, 0};
4318     for (int i = 0; i < 4; ++i)
4319     {
4320         glGetIntegerv(GL_RED_BITS + i, bits.data() + i);
4321         epsilon[i] =
4322             std::min(255u, static_cast<unsigned int>(
4323                                ceil(1.0 + 255.0 * (1.0 / pow(2.0, static_cast<double>(bits[i]))))));
4324 
4325         ASSERT(epsilon[i] >= 0 && epsilon[i] <= 255u);
4326     }
4327 
4328     std::vector<GLColor> rendered(kSize * kSize, GLColor::green);
4329 
4330     for (int i = 0; i < maxDrawBuffers; ++i)
4331     {
4332         std::vector<uint8_t> expected = {
4333             static_cast<uint8_t>(0.15f * 255), static_cast<uint8_t>(0.30f * 255),
4334             static_cast<uint8_t>(0.45f * 255), static_cast<uint8_t>(0.60f * 255)};
4335         expected[i % 4] = static_cast<uint8_t>(0.85f * 255);
4336 
4337         glReadBuffer(GL_COLOR_ATTACHMENT0 + i);
4338         glReadPixels(0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, rendered.data());
4339 
4340         for (int y = 0; y < kSize; ++y)
4341         {
4342             for (int x = 0; x < kSize; ++x)
4343             {
4344                 GLColor readBackData = rendered[y * kSize + x];
4345 
4346                 bool exactMatch = readBackData.R == expected[0] && readBackData.G == expected[1] &&
4347                                   readBackData.B == expected[2] && readBackData.A == expected[3];
4348 
4349                 bool matchWithinEpsilon =
4350                     abs(static_cast<int>(readBackData.R) - static_cast<int>(expected[0])) <=
4351                         static_cast<int>(epsilon[0]) &&
4352                     abs(static_cast<int>(readBackData.G) - static_cast<int>(expected[1])) <=
4353                         static_cast<int>(epsilon[1]) &&
4354                     abs(static_cast<int>(readBackData.B) - static_cast<int>(expected[2])) <=
4355                         static_cast<int>(epsilon[2]) &&
4356                     abs(static_cast<int>(readBackData.A) - static_cast<int>(expected[3])) <=
4357                         static_cast<int>(epsilon[3]);
4358 
4359                 ASSERT(exactMatch || matchWithinEpsilon);
4360             }
4361         }
4362     }
4363 
4364     // Set the framebuffer color mask back to default values
4365     for (int i = 0; i < maxDrawBuffers; ++i)
4366     {
4367         glColorMaski(i, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4368     }
4369 
4370     ASSERT_GL_NO_ERROR();
4371 }
4372 
clearColorMorePrecisionThanFBOFormatNoDithering(const GLint & fboInternalFormat)4373 void clearColorMorePrecisionThanFBOFormatNoDithering(const GLint &fboInternalFormat)
4374 {
4375     constexpr int kSize = 4;
4376     GLFramebuffer fbo;
4377     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4378 
4379     glDisable(GL_DITHER);
4380 
4381     // Attach texture with internal format GL_RGB5_A1 to each framebuffer color attachment
4382     std::vector<unsigned char> pixelData(kSize * kSize * 4, 255);
4383     GLTexture texture;
4384     glBindTexture(GL_TEXTURE_2D, texture);
4385     glTexImage2D(GL_TEXTURE_2D, 0, fboInternalFormat, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4386                  pixelData.data());
4387     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4388     ASSERT_GL_NO_ERROR();
4389     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4390 
4391     // Clear FBO color attachment with clear color (0.15f, 0.3f, 0.45f, 0.6f)
4392     glClearColor(0.15f, 0.3f, 0.45f, 0.6f);
4393     glClear(GL_COLOR_BUFFER_BIT);
4394     ASSERT_GL_NO_ERROR();
4395 
4396     // Read and Verify
4397     // calculate the comparison epsilon based on the number of bits
4398     std::vector<int> bits        = {0, 0, 0, 0};
4399     std::vector<uint8_t> epsilon = {0, 0, 0, 0};
4400     for (int i = 0; i < 4; ++i)
4401     {
4402         glGetIntegerv(GL_RED_BITS + i, bits.data() + i);
4403         epsilon[i] =
4404             std::min(255u, static_cast<unsigned int>(
4405                                ceil(1.0 + 255.0 * (1.0 / pow(2.0, static_cast<double>(bits[i]))))));
4406 
4407         ASSERT(epsilon[i] >= 0 && epsilon[i] <= 255u);
4408     }
4409 
4410     std::vector<GLColor> rendered(kSize * kSize, GLColor::green);
4411 
4412     std::vector<uint8_t> expected = {
4413         static_cast<uint8_t>(0.15f * 255), static_cast<uint8_t>(0.30f * 255),
4414         static_cast<uint8_t>(0.45f * 255), static_cast<uint8_t>(0.60f * 255)};
4415 
4416     glReadPixels(0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, rendered.data());
4417     ASSERT_GL_NO_ERROR();
4418 
4419     // Every pixel should have the same rendered result color. No dithering should be applied.
4420     GLColor clearedResultAtFirstPixel = rendered[0];
4421 
4422     for (int y = 0; y < kSize; ++y)
4423     {
4424         for (int x = 0; x < kSize; ++x)
4425         {
4426             GLColor readBackData = rendered[y * kSize + x];
4427 
4428             // Firstly check the rendered result is rational
4429             bool exactMatch = readBackData.R == expected[0] && readBackData.G == expected[1] &&
4430                               readBackData.B == expected[2] && readBackData.A == expected[3];
4431 
4432             bool matchWithinEpsilon =
4433                 abs(static_cast<int>(readBackData.R) - static_cast<int>(expected[0])) <=
4434                     static_cast<int>(epsilon[0]) &&
4435                 abs(static_cast<int>(readBackData.G) - static_cast<int>(expected[1])) <=
4436                     static_cast<int>(epsilon[1]) &&
4437                 abs(static_cast<int>(readBackData.B) - static_cast<int>(expected[2])) <=
4438                     static_cast<int>(epsilon[2]) &&
4439                 abs(static_cast<int>(readBackData.A) - static_cast<int>(expected[3])) <=
4440                     static_cast<int>(epsilon[3]);
4441 
4442             ASSERT(exactMatch || matchWithinEpsilon);
4443 
4444             // Secondly check no dithering is applied
4445             bool sameClearResultAsFirstPixel = readBackData.R == clearedResultAtFirstPixel.R &&
4446                                                readBackData.G == clearedResultAtFirstPixel.G &&
4447                                                readBackData.B == clearedResultAtFirstPixel.B &&
4448                                                readBackData.A == clearedResultAtFirstPixel.A;
4449             ASSERT(sameClearResultAsFirstPixel);
4450         }
4451     }
4452 }
4453 
4454 // Verify that when clear color has more precision than FBO color attachment format can hold,
4455 // dithering is not automatically applied.
4456 // https://issuetracker.google.com/292282210
TEST_P(FramebufferTest_ES31,ClearColorMorePrecisionThanFBOFormatShouldNotApplyDithering)4457 TEST_P(FramebufferTest_ES31, ClearColorMorePrecisionThanFBOFormatShouldNotApplyDithering)
4458 {
4459     clearColorMorePrecisionThanFBOFormatNoDithering(GL_RGB5_A1);
4460 }
4461 
4462 // Validates both MESA and standard functions can be used on OpenGL ES >=3.1
TEST_P(FramebufferTest_ES31,ValidateFramebufferFlipYMesaExtension)4463 TEST_P(FramebufferTest_ES31, ValidateFramebufferFlipYMesaExtension)
4464 {
4465     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
4466 
4467     GLFramebuffer mFramebuffer;
4468     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
4469 
4470     glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
4471     ASSERT_GL_NO_ERROR();
4472 
4473     GLint flip_y = -1;
4474 
4475     glGetFramebufferParameterivMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
4476     ASSERT_GL_NO_ERROR();
4477     EXPECT_EQ(flip_y, 1);
4478 
4479     glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
4480     ASSERT_GL_NO_ERROR();
4481 
4482     flip_y = -1;
4483     glGetFramebufferParameterivMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
4484     ASSERT_GL_NO_ERROR();
4485     EXPECT_EQ(flip_y, 0);
4486 
4487     // Also using non-MESA functions should work.
4488     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
4489     ASSERT_GL_NO_ERROR();
4490 
4491     flip_y = -1;
4492     glGetFramebufferParameteriv(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
4493     ASSERT_GL_NO_ERROR();
4494     EXPECT_EQ(flip_y, 1);
4495 
4496     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
4497     ASSERT_GL_NO_ERROR();
4498 
4499     flip_y = -1;
4500     glGetFramebufferParameteriv(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
4501     ASSERT_GL_NO_ERROR();
4502     EXPECT_EQ(flip_y, 0);
4503 }
4504 
4505 class AddMockTextureNoRenderTargetTest : public ANGLETest<>
4506 {
4507   public:
AddMockTextureNoRenderTargetTest()4508     AddMockTextureNoRenderTargetTest()
4509     {
4510         setWindowWidth(512);
4511         setWindowHeight(512);
4512         setConfigRedBits(8);
4513         setConfigGreenBits(8);
4514         setConfigBlueBits(8);
4515         setConfigAlphaBits(8);
4516     }
4517 };
4518 
4519 // Test to verify workaround succeeds when no program outputs exist http://anglebug.com/2283
TEST_P(AddMockTextureNoRenderTargetTest,NoProgramOutputWorkaround)4520 TEST_P(AddMockTextureNoRenderTargetTest, NoProgramOutputWorkaround)
4521 {
4522     constexpr char kVS[] = "void main() {}";
4523     constexpr char kFS[] = "void main() {}";
4524 
4525     ANGLE_GL_PROGRAM(drawProgram, kVS, kFS);
4526 
4527     glUseProgram(drawProgram);
4528 
4529     glDrawArrays(GL_TRIANGLES, 0, 6);
4530 
4531     ASSERT_GL_NO_ERROR();
4532 }
4533 
4534 // Covers a bug in ANGLE's Vulkan back-end framebuffer cache which ignored depth/stencil after
4535 // calls to DrawBuffers.
TEST_P(FramebufferTest_ES3,AttachmentStateChange)4536 TEST_P(FramebufferTest_ES3, AttachmentStateChange)
4537 {
4538     constexpr GLuint kSize = 2;
4539 
4540     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
4541 
4542     GLTexture colorTexture;
4543     glBindTexture(GL_TEXTURE_2D, colorTexture);
4544     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
4545 
4546     GLFramebuffer fbo;
4547     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4548     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4549 
4550     ASSERT_GL_NO_ERROR();
4551     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4552 
4553     // First draw without a depth buffer.
4554     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4555 
4556     GLRenderbuffer depthBuffer;
4557     glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
4558     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kSize, kSize);
4559 
4560     // Bind just a renderbuffer and draw.
4561     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
4562 
4563     ASSERT_GL_NO_ERROR();
4564     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4565 
4566     glDrawBuffers(0, nullptr);
4567     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4568 
4569     // Re-enable color buffer and draw one final time. This previously triggered a crash.
4570     GLenum drawBuffs = {GL_COLOR_ATTACHMENT0};
4571     glDrawBuffers(1, &drawBuffs);
4572 
4573     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
4574     ASSERT_GL_NO_ERROR();
4575     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4576 }
4577 
4578 // Tests that we can support a color texture also attached to the color attachment but
4579 // with different LOD. From GLES3.0 spec section 4.4.3.2, if min_filter is GL_NEAREST_MIPMAP_NEAREST
4580 // and the lod is within the [base_level, max_level] range, and it is possible to sample from a LOD
4581 // that is rendering to then it does form a feedback loop. But if it is using textureLOD to
4582 // explicitly fetching texture on different LOD, there is no loop and should still work. Aztec_ruins
4583 // (https://issuetracker.google.com/175584609) is doing exactly this.
TEST_P(FramebufferTest_ES3,SampleFromAttachedTextureWithDifferentLOD)4584 TEST_P(FramebufferTest_ES3, SampleFromAttachedTextureWithDifferentLOD)
4585 {
4586     // TODO: https://anglebug.com/5760
4587     ANGLE_SKIP_TEST_IF(IsD3D());
4588 
4589     constexpr GLuint kLevel0Size = 4;
4590     constexpr GLuint kLevel1Size = kLevel0Size / 2;
4591     constexpr GLuint kLevel2Size = kLevel1Size / 2;
4592     std::array<GLColor, kLevel0Size * kLevel0Size> gData;
4593 
4594     GLTexture colorTexture;
4595     glBindTexture(GL_TEXTURE_2D, colorTexture);
4596     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4597     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4598     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kLevel0Size, kLevel0Size);
4599     gData.fill(GLColor::red);
4600     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
4601                     gData.data());
4602     gData.fill(GLColor::green);
4603     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
4604                     gData.data());
4605     gData.fill(GLColor::blue);
4606     glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, kLevel2Size, kLevel2Size, GL_RGBA, GL_UNSIGNED_BYTE,
4607                     gData.data());
4608 
4609     // Attach level 1 to a FBO
4610     GLFramebuffer framebuffer;
4611     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4612     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
4613     ASSERT_GL_NO_ERROR();
4614     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4615 
4616     // Render to FBO with color texture level 1 and textureLod from level 0.
4617     const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
4618     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
4619     glViewport(0, 0, kLevel1Size, kLevel1Size);
4620     glScissor(0, 0, kLevel1Size, kLevel1Size);
4621     glEnable(GL_CULL_FACE);
4622     glCullFace(GL_BACK);
4623     glDisable(GL_BLEND);
4624     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4625     glActiveTexture(GL_TEXTURE0);
4626     glBindTexture(GL_TEXTURE_2D, colorTexture);
4627 
4628     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
4629     glUseProgram(program);
4630     GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
4631     GLint lodLoc     = glGetUniformLocation(program, essl3_shaders::LodUniform());
4632     ASSERT_NE(-1, textureLoc);
4633     ASSERT_NE(-1, lodLoc);
4634     glUniform1i(textureLoc, 0);  // texture unit 0
4635     glUniform1f(lodLoc, 0);      // with Lod=0
4636     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4637 
4638     glDisable(GL_CULL_FACE);
4639     glDisable(GL_DEPTH_TEST);
4640     glDisable(GL_BLEND);
4641     glDisable(GL_SCISSOR_TEST);
4642     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4643 
4644     ASSERT_GL_NO_ERROR();
4645     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4646 }
4647 
4648 // This extends the test SampleFromAttachedTextureWithDifferentLOD by creating two renderpasses
4649 // without changing texture binding. This is to make sure that sample/render to the same texture
4650 // still function properly when transition from one renderpass to another without texture binding
4651 // change.
TEST_P(FramebufferTest_ES3,SampleFromAttachedTextureWithDifferentLODAndFBOSwitch)4652 TEST_P(FramebufferTest_ES3, SampleFromAttachedTextureWithDifferentLODAndFBOSwitch)
4653 {
4654     // TODO: https://anglebug.com/5760
4655     ANGLE_SKIP_TEST_IF(IsD3D());
4656 
4657     constexpr GLuint kLevel0Size = 4;
4658     constexpr GLuint kLevel1Size = kLevel0Size / 2;
4659     constexpr GLuint kLevel2Size = kLevel1Size / 2;
4660     std::array<GLColor, kLevel0Size * kLevel0Size> gData;
4661 
4662     GLTexture colorTexture;
4663     glBindTexture(GL_TEXTURE_2D, colorTexture);
4664     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4665     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4666     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kLevel0Size, kLevel0Size);
4667     gData.fill(GLColor::red);
4668     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
4669                     gData.data());
4670     gData.fill(GLColor::green);
4671     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
4672                     gData.data());
4673     gData.fill(GLColor::blue);
4674     glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, kLevel2Size, kLevel2Size, GL_RGBA, GL_UNSIGNED_BYTE,
4675                     gData.data());
4676 
4677     // Attach level 1 to two FBOs
4678     GLFramebuffer framebuffer1;
4679     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
4680     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
4681     ASSERT_GL_NO_ERROR();
4682     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4683     GLFramebuffer framebuffer2;
4684     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
4685     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
4686     ASSERT_GL_NO_ERROR();
4687     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4688 
4689     // Render to left half of FBO1 and textureLod from level 0.
4690     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
4691     glViewport(0, 0, kLevel1Size / 2, kLevel1Size);
4692     glScissor(0, 0, kLevel1Size / 2, kLevel1Size);
4693     glActiveTexture(GL_TEXTURE0);
4694     glBindTexture(GL_TEXTURE_2D, colorTexture);
4695     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
4696     glUseProgram(program);
4697     GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
4698     GLint lodLoc     = glGetUniformLocation(program, essl3_shaders::LodUniform());
4699     ASSERT_NE(-1, textureLoc);
4700     ASSERT_NE(-1, lodLoc);
4701     glUniform1i(textureLoc, 0);  // texture unit 0
4702     glUniform1f(lodLoc, 0);      // with Lod=0
4703     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4704     ASSERT_GL_NO_ERROR();
4705 
4706     // Render to right half of FBO2 and textureLod from level 0 without trigger texture binding
4707     // change.
4708     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
4709     glViewport(kLevel1Size / 2, 0, kLevel1Size / 2, kLevel1Size);
4710     glScissor(kLevel1Size / 2, 0, kLevel1Size / 2, kLevel1Size);
4711     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4712     ASSERT_GL_NO_ERROR();
4713     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4714     EXPECT_PIXEL_COLOR_EQ(kLevel1Size - 1, 0, GLColor::red);
4715 }
4716 
4717 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
4718 // renders to an immutable texture at the level that is bigger than GL_TEXTURE_MAX_LEVEL. The
4719 // texture itself has not been initialized with any data before rendering (TexSubImage call may
4720 // initialize a VkImage object).
TEST_P(FramebufferTest_ES3,RenderAndInvalidateImmutableTextureWithBeyondMaxLevel)4721 TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithBeyondMaxLevel)
4722 {
4723     constexpr GLuint kLevel0Size = 4;
4724     constexpr GLuint kLevel1Size = kLevel0Size / 2;
4725 
4726     GLTexture colorTexture;
4727     glBindTexture(GL_TEXTURE_2D, colorTexture);
4728     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4729     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4730     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
4731     // set max_level to 0
4732     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
4733 
4734     // Attach level 1 to a FBO
4735     GLFramebuffer framebuffer;
4736     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4737     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
4738     ASSERT_GL_NO_ERROR();
4739     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4740 
4741     // Render to FBO
4742     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4743     const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
4744     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
4745     glViewport(0, 0, kLevel1Size, kLevel1Size);
4746     glScissor(0, 0, kLevel1Size, kLevel1Size);
4747     glEnable(GL_CULL_FACE);
4748     glCullFace(GL_BACK);
4749     glDisable(GL_BLEND);
4750     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4751     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
4752     glUseProgram(program);
4753     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4754 
4755     glDisable(GL_CULL_FACE);
4756     glDisable(GL_DEPTH_TEST);
4757     glDisable(GL_BLEND);
4758     glDisable(GL_SCISSOR_TEST);
4759     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4760 
4761     ASSERT_GL_NO_ERROR();
4762     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4763 }
4764 
4765 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
4766 // renders to an immutable texture at the level that is bigger than GL_TEXTURE_MAX_LEVEL. The
4767 // texture itself has been initialized with data before rendering.
TEST_P(FramebufferTest_ES3,RenderAndInvalidateImmutableTextureWithSubImageWithBeyondMaxLevel)4768 TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithSubImageWithBeyondMaxLevel)
4769 {
4770     constexpr GLuint kLevel0Size = 4;
4771     constexpr GLuint kLevel1Size = kLevel0Size / 2;
4772     std::array<GLColor, kLevel0Size * kLevel0Size> gData;
4773 
4774     GLTexture colorTexture;
4775     glBindTexture(GL_TEXTURE_2D, colorTexture);
4776     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4777     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4778     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
4779     // set max_level to 0
4780     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
4781     // Initialize with TexSubImage call
4782     gData.fill(GLColor::blue);
4783     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
4784                     gData.data());
4785 
4786     // Attach level 1 to a FBO
4787     GLFramebuffer framebuffer;
4788     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4789     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
4790     ASSERT_GL_NO_ERROR();
4791     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4792 
4793     // Render to FBO
4794     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4795     const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
4796     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
4797     glViewport(0, 0, kLevel1Size, kLevel1Size);
4798     glScissor(0, 0, kLevel1Size, kLevel1Size);
4799     glEnable(GL_CULL_FACE);
4800     glCullFace(GL_BACK);
4801     glDisable(GL_BLEND);
4802     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4803     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
4804     glUseProgram(program);
4805     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4806 
4807     glDisable(GL_CULL_FACE);
4808     glDisable(GL_DEPTH_TEST);
4809     glDisable(GL_BLEND);
4810     glDisable(GL_SCISSOR_TEST);
4811     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4812 
4813     ASSERT_GL_NO_ERROR();
4814     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4815 }
4816 
4817 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
4818 // renders to an immutable texture at the level that is smaller than GL_TEXTURE_BASE_LEVEL. The
4819 // texture itself has been initialized with data before rendering. Filament is using it this way
TEST_P(FramebufferTest_ES3,RenderAndInvalidateImmutableTextureWithBellowBaseLevelLOD)4820 TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithBellowBaseLevelLOD)
4821 {
4822     constexpr GLuint kLevel0Size = 4;
4823     constexpr GLuint kLevel1Size = kLevel0Size / 2;
4824     std::array<GLColor, kLevel0Size * kLevel0Size> gData;
4825 
4826     GLTexture colorTexture;
4827     glBindTexture(GL_TEXTURE_2D, colorTexture);
4828     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4829     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4830     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
4831     // set base_level to 1
4832     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
4833     gData.fill(GLColor::blue);
4834     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
4835                     gData.data());
4836 
4837     // Attach level 0 to a FBO
4838     GLFramebuffer framebuffer;
4839     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4840     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4841     ASSERT_GL_NO_ERROR();
4842     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4843 
4844     // Render to FBO
4845     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4846     const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
4847     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
4848     glViewport(0, 0, kLevel0Size, kLevel0Size);
4849     glScissor(0, 0, kLevel0Size, kLevel0Size);
4850     glEnable(GL_CULL_FACE);
4851     glCullFace(GL_BACK);
4852     glDisable(GL_BLEND);
4853     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4854     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
4855     glUseProgram(program);
4856     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
4857 
4858     glDisable(GL_CULL_FACE);
4859     glDisable(GL_DEPTH_TEST);
4860     glDisable(GL_BLEND);
4861     glDisable(GL_SCISSOR_TEST);
4862     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4863 
4864     ASSERT_GL_NO_ERROR();
4865     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4866 }
4867 
4868 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
4869 // renders to an immutable texture at the level that is bigger than GL_TEXTURE_MAX_LEVEL. The
4870 // texture level that we render to has been initialized with data before rendering. This test if
4871 // render to that level will get flush the level update even though it is outside [base, max]
4872 // levels.
TEST_P(FramebufferTest_ES3,RenderImmutableTextureWithSubImageWithBeyondMaxLevel)4873 TEST_P(FramebufferTest_ES3, RenderImmutableTextureWithSubImageWithBeyondMaxLevel)
4874 {
4875     // Set up program to sample from specific lod level.
4876     GLProgram textureLodProgram;
4877     textureLodProgram.makeRaster(essl3_shaders::vs::Texture2DLod(),
4878                                  essl3_shaders::fs::Texture2DLod());
4879     ASSERT(textureLodProgram.valid());
4880     glUseProgram(textureLodProgram);
4881 
4882     GLint textureLocation =
4883         glGetUniformLocation(textureLodProgram, essl3_shaders::Texture2DUniform());
4884     ASSERT_NE(-1, textureLocation);
4885     GLint lodLocation = glGetUniformLocation(textureLodProgram, essl3_shaders::LodUniform());
4886     ASSERT_NE(-1, lodLocation);
4887 
4888     constexpr GLuint kLevel0Size = 4;
4889     constexpr GLuint kLevel1Size = kLevel0Size / 2;
4890     std::array<GLColor, kLevel0Size * kLevel0Size> gData;
4891 
4892     GLTexture colorTexture;
4893     glBindTexture(GL_TEXTURE_2D, colorTexture);
4894     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4895     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4896     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
4897     // Initialize level 0 with blue
4898     gData.fill(GLColor::blue);
4899     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
4900                     gData.data());
4901     // set max_level to 0
4902     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
4903     // Draw with level 0
4904     glUniform1f(lodLocation, 0);
4905     drawQuad(textureLodProgram, essl3_shaders::PositionAttrib(), 0.5f);
4906     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4907 
4908     // Initalize level 1 with green
4909     gData.fill(GLColor::green);
4910     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
4911                     gData.data());
4912     // Attach level 1 to a FBO
4913     GLFramebuffer framebuffer;
4914     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4915     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
4916     ASSERT_GL_NO_ERROR();
4917     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4918     // Render to FBO (i.e. level 1) with Red and blend with existing texture level data
4919     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4920     glViewport(0, 0, kLevel1Size, kLevel1Size);
4921     glScissor(0, 0, kLevel1Size, kLevel1Size);
4922     glEnable(GL_CULL_FACE);
4923     glCullFace(GL_BACK);
4924     glEnable(GL_BLEND);
4925     glBlendFunc(GL_ONE, GL_ONE);
4926     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4927     ANGLE_GL_PROGRAM(redProgram, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
4928     glUseProgram(redProgram);
4929     drawQuad(redProgram, essl3_shaders::PositionAttrib(), 0.5f);
4930 
4931     glDisable(GL_CULL_FACE);
4932     glDisable(GL_DEPTH_TEST);
4933     glDisable(GL_BLEND);
4934     glDisable(GL_SCISSOR_TEST);
4935     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4936 
4937     ASSERT_GL_NO_ERROR();
4938     // Expect to see Red + Green, which is Yellow
4939     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4940 }
4941 
4942 // Similar to the other RenderImmutableTexture*** tests, but test on depth attachment instead of
4943 // color attachment. This tests render to a depth texture level that is less than
4944 // GL_TEXTURE_BASE_LEVEL and sample from it at the same time.
TEST_P(FramebufferTest_ES3,RenderSampleDepthTextureWithExcludedLevel)4945 TEST_P(FramebufferTest_ES3, RenderSampleDepthTextureWithExcludedLevel)
4946 {
4947     // Set up program to copy depth texture's value to color.red.
4948     constexpr char kVS[] = R"(precision mediump float;
4949 attribute vec4 a_position;
4950 varying vec2 v_texCoord;
4951 void main()
4952 {
4953     gl_Position = a_position;
4954     v_texCoord = a_position.xy * 0.5 + vec2(0.5);
4955 })";
4956     constexpr char kFS[] = R"(precision mediump float;
4957 varying vec2 v_texCoord;
4958 uniform sampler2D depth;
4959 void main()
4960 {
4961     gl_FragColor = vec4(texture2D(depth, v_texCoord).x, 1, 0, 1);
4962 })";
4963     ANGLE_GL_PROGRAM(program, kVS, kFS);
4964 
4965     constexpr GLuint kLevel0Size = 4;
4966     constexpr GLuint kLevel1Size = kLevel0Size / 2;
4967 
4968     GLTexture colorTexture;
4969     glBindTexture(GL_TEXTURE_2D, colorTexture);
4970     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4971     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4972     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kLevel0Size, kLevel0Size);
4973 
4974     GLTexture depthTexture;
4975     glBindTexture(GL_TEXTURE_2D, depthTexture);
4976     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4977     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4978     glTexStorage2D(GL_TEXTURE_2D, 3, GL_DEPTH_COMPONENT32F, kLevel0Size, kLevel0Size);
4979     // Initialize level 1 with known depth value
4980     std::array<GLfloat, kLevel1Size * kLevel1Size> gData = {0.2, 0.4, 0.6, 0.8};
4981     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_DEPTH_COMPONENT, GL_FLOAT,
4982                     gData.data());
4983     // set base_level and max_level to 1, exclude level 0
4984     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
4985     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
4986 
4987     // Attach level 0 to a FBO
4988     GLFramebuffer framebuffer;
4989     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4990     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
4991     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
4992     ASSERT_GL_NO_ERROR();
4993     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4994 
4995     // Render to FBO (LOD 0) with depth texture LOD 1
4996     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
4997     glViewport(0, 0, kLevel0Size, kLevel0Size);
4998     glScissor(0, 0, kLevel0Size, kLevel0Size);
4999     glDepthMask(GL_TRUE);
5000     glEnable(GL_DEPTH_TEST);
5001     glDepthFunc(GL_ALWAYS);
5002     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
5003     ASSERT_GL_NO_ERROR();
5004     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(51u, 255u, 0, 255u), 1);
5005     EXPECT_PIXEL_COLOR_NEAR(kLevel0Size - 1, 0, GLColor(102u, 255u, 0, 255u), 1);
5006     EXPECT_PIXEL_COLOR_NEAR(0, kLevel0Size - 1, GLColor(153u, 255u, 0, 255u), 1);
5007     EXPECT_PIXEL_COLOR_NEAR(kLevel0Size - 1, kLevel0Size - 1, GLColor(204u, 255u, 0, 255u), 1);
5008 
5009     // Now check depth value is 0.5
5010     glDepthFunc(GL_LESS);
5011     glDepthMask(GL_FALSE);
5012     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
5013     glUseProgram(blueProgram);
5014     // should fail depth test
5015     drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.51f);
5016     ASSERT_GL_NO_ERROR();
5017     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(51u, 255u, 0, 255u), 1);
5018     // should pass depth test
5019     drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.49f);
5020     ASSERT_GL_NO_ERROR();
5021     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5022 }
5023 
5024 // Covers a bug in ANGLE's Vulkan back-end. Our VkFramebuffer cache would in some cases forget to
5025 // check the draw states when computing a cache key.
TEST_P(FramebufferTest_ES3,DisabledAttachmentRedefinition)5026 TEST_P(FramebufferTest_ES3, DisabledAttachmentRedefinition)
5027 {
5028     constexpr GLuint kSize = 2;
5029 
5030     // Make a Framebuffer with two attachments with one enabled and one disabled.
5031     GLTexture texA, texB;
5032     glBindTexture(GL_TEXTURE_2D, texA);
5033     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5034     glBindTexture(GL_TEXTURE_2D, texB);
5035     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5036 
5037     GLFramebuffer fbo;
5038     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5039     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
5040     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texB, 0);
5041 
5042     // Mask out the second texture.
5043     constexpr GLenum kOneDrawBuf = GL_COLOR_ATTACHMENT0;
5044     glDrawBuffers(1, &kOneDrawBuf);
5045 
5046     ASSERT_GL_NO_ERROR();
5047     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5048 
5049     // Set up a very simple shader.
5050     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
5051     glViewport(0, 0, kSize, kSize);
5052 
5053     // Draw
5054     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5055     ASSERT_GL_NO_ERROR();
5056     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5057 
5058     // Update the masked out attachment and draw again.
5059     std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
5060     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
5061                     redPixels.data());
5062 
5063     // Draw
5064     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5065     ASSERT_GL_NO_ERROR();
5066     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5067 
5068     glReadBuffer(GL_COLOR_ATTACHMENT1);
5069     ASSERT_GL_NO_ERROR();
5070     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5071 }
5072 
5073 // Test that changing the attachment of a framebuffer then sync'ing both READ and DRAW framebuffer
5074 // (currently possible with glInvalidateFramebuffer) updates the scissor correctly.
TEST_P(FramebufferTest_ES3,ChangeAttachmentThenInvalidateAndDraw)5075 TEST_P(FramebufferTest_ES3, ChangeAttachmentThenInvalidateAndDraw)
5076 {
5077     constexpr GLsizei kSizeLarge = 32;
5078     constexpr GLsizei kSizeSmall = 16;
5079 
5080     GLTexture color1;
5081     glBindTexture(GL_TEXTURE_2D, color1);
5082     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeSmall, kSizeSmall, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5083                  nullptr);
5084 
5085     GLTexture color2;
5086     glBindTexture(GL_TEXTURE_2D, color2);
5087     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeLarge, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5088                  nullptr);
5089 
5090     GLFramebuffer fbo;
5091     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5092     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
5093 
5094     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5095     glUseProgram(drawColor);
5096     GLint colorUniformLocation =
5097         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
5098     ASSERT_NE(colorUniformLocation, -1);
5099 
5100     glViewport(0, 0, kSizeLarge, kSizeLarge);
5101 
5102     // Draw red into the framebuffer.
5103     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
5104     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
5105     ASSERT_GL_NO_ERROR();
5106 
5107     // Change the attachment, invalidate it and draw green.
5108     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color2, 0);
5109     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5110 
5111     std::array<GLenum, 1> attachments = {GL_COLOR_ATTACHMENT0};
5112     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
5113     ASSERT_GL_NO_ERROR();
5114 
5115     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
5116     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
5117     ASSERT_GL_NO_ERROR();
5118 
5119     // Validate the result.
5120     EXPECT_PIXEL_RECT_EQ(0, 0, kSizeLarge, kSizeLarge, GLColor::green);
5121 
5122     // Do the same, but changing from the large to small attachment.
5123 
5124     // Draw red into the framebuffer.
5125     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
5126     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
5127     ASSERT_GL_NO_ERROR();
5128 
5129     // Change the attachment, invalidate it and draw blue.
5130     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
5131     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5132     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
5133 
5134     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
5135     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
5136     ASSERT_GL_NO_ERROR();
5137 
5138     // Validate the result.
5139     EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::blue);
5140 }
5141 
5142 // Test Framebuffer object with two attachments that have unequal size. In OpenGLES3.0, this is
5143 // a supported config. The common intersection area should be correctly rendered. The contents
5144 // outside common intersection area are undefined.
TEST_P(FramebufferTest_ES3,AttachmentsWithUnequalDimensions)5145 TEST_P(FramebufferTest_ES3, AttachmentsWithUnequalDimensions)
5146 {
5147     ANGLE_SKIP_TEST_IF(IsD3D());
5148 
5149     constexpr GLsizei kSizeLarge = 32;
5150     constexpr GLsizei kSizeSmall = 16;
5151 
5152     GLTexture colorTexture;
5153     glBindTexture(GL_TEXTURE_2D, colorTexture);
5154     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeSmall, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5155                  nullptr);
5156 
5157     GLRenderbuffer color;
5158     glBindRenderbuffer(GL_RENDERBUFFER, color);
5159     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSizeSmall, kSizeLarge);
5160 
5161     GLRenderbuffer depth;
5162     glBindRenderbuffer(GL_RENDERBUFFER, depth);
5163     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kSizeSmall, kSizeLarge);
5164 
5165     GLRenderbuffer stencil;
5166     glBindRenderbuffer(GL_RENDERBUFFER, stencil);
5167     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSizeSmall, kSizeLarge);
5168 
5169     struct
5170     {
5171         GLenum attachment;
5172         GLuint renderbuffer;
5173     } attachment2[4] = {{GL_COLOR_ATTACHMENT1, 0},
5174                         {GL_COLOR_ATTACHMENT1, color},
5175                         {GL_DEPTH_ATTACHMENT, depth},
5176                         {GL_STENCIL_ATTACHMENT, stencil}};
5177     for (int i = 0; i < 4; i++)
5178     {
5179         GLFramebuffer fbo;
5180         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5181         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture,
5182                                0);
5183         if (attachment2[i].renderbuffer)
5184         {
5185             glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment2[i].attachment, GL_RENDERBUFFER,
5186                                       attachment2[i].renderbuffer);
5187         }
5188         ASSERT_GL_NO_ERROR();
5189         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5190 
5191         ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5192         glUseProgram(drawColor);
5193         GLint colorUniformLocation =
5194             glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
5195         ASSERT_NE(colorUniformLocation, -1);
5196 
5197         glViewport(0, 0, kSizeLarge, kSizeLarge);
5198         const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
5199         glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
5200 
5201         // Draw red into the framebuffer.
5202         glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
5203         drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
5204         ASSERT_GL_NO_ERROR();
5205 
5206         // Validate the result. The intersected common area should be red now
5207         EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::red);
5208     }
5209 }
5210 
5211 // Validates only MESA functions can be used on OpenGL ES <3.1
TEST_P(FramebufferTest_ES3,ValidateFramebufferFlipYMesaExtension)5212 TEST_P(FramebufferTest_ES3, ValidateFramebufferFlipYMesaExtension)
5213 {
5214     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
5215 
5216     GLFramebuffer mFramebuffer;
5217     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
5218 
5219     glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
5220     ASSERT_GL_NO_ERROR();
5221 
5222     GLint flip_y = -1;
5223 
5224     glGetFramebufferParameterivMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
5225     ASSERT_GL_NO_ERROR();
5226     EXPECT_EQ(flip_y, 1);
5227 
5228     glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
5229     ASSERT_GL_NO_ERROR();
5230 
5231     flip_y = -1;
5232     glGetFramebufferParameterivMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
5233     ASSERT_GL_NO_ERROR();
5234     EXPECT_EQ(flip_y, 0);
5235 
5236     // Using non-MESA function should fail.
5237     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
5238     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
5239 
5240     glGetFramebufferParameteriv(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, &flip_y);
5241     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
5242 }
5243 
TEST_P(FramebufferTest_ES3,FramebufferFlipYMesaExtensionIncorrectPname)5244 TEST_P(FramebufferTest_ES3, FramebufferFlipYMesaExtensionIncorrectPname)
5245 {
5246     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
5247 
5248     GLFramebuffer mFramebuffer;
5249     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
5250 
5251     glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
5252     ASSERT_GL_ERROR(GL_INVALID_ENUM);
5253 }
5254 
5255 class FramebufferTest : public ANGLETest<>
5256 {};
5257 
5258 template <typename T>
FillTexture2D(GLuint texture,GLsizei width,GLsizei height,const T & onePixelData,GLint level,GLint internalFormat,GLenum format,GLenum type)5259 void FillTexture2D(GLuint texture,
5260                    GLsizei width,
5261                    GLsizei height,
5262                    const T &onePixelData,
5263                    GLint level,
5264                    GLint internalFormat,
5265                    GLenum format,
5266                    GLenum type)
5267 {
5268     std::vector<T> allPixelsData(width * height, onePixelData);
5269 
5270     glBindTexture(GL_TEXTURE_2D, texture);
5271     glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
5272                  allPixelsData.data());
5273     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5274     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5275     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
5276     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
5277 }
5278 
5279 // Multi-context uses of textures should not cause rendering feedback loops.
TEST_P(FramebufferTest,MultiContextNoRenderingFeedbackLoops)5280 TEST_P(FramebufferTest, MultiContextNoRenderingFeedbackLoops)
5281 {
5282     constexpr char kTextureVS[] =
5283         R"(attribute vec4 a_position;
5284 varying vec2 v_texCoord;
5285 void main() {
5286     gl_Position = a_position;
5287     v_texCoord = (a_position.xy * 0.5) + 0.5;
5288 })";
5289 
5290     constexpr char kTextureFS[] =
5291         R"(precision mediump float;
5292 varying vec2 v_texCoord;
5293 uniform sampler2D u_texture;
5294 void main() {
5295     gl_FragColor = texture2D(u_texture, v_texCoord).rgba;
5296 })";
5297 
5298     ANGLE_GL_PROGRAM(textureProgram, kTextureVS, kTextureFS);
5299 
5300     glUseProgram(textureProgram);
5301     GLint uniformLoc = glGetUniformLocation(textureProgram, "u_texture");
5302     ASSERT_NE(-1, uniformLoc);
5303     glUniform1i(uniformLoc, 0);
5304 
5305     GLTexture texture;
5306     FillTexture2D(texture, 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
5307     glBindTexture(GL_TEXTURE_2D, texture);
5308     // Note that _texture_ is still bound to GL_TEXTURE_2D in this context at this point.
5309 
5310     EGLWindow *window          = getEGLWindow();
5311     EGLDisplay display         = window->getDisplay();
5312     EGLConfig config           = window->getConfig();
5313     EGLSurface surface         = window->getSurface();
5314     EGLint contextAttributes[] = {
5315         EGL_CONTEXT_MAJOR_VERSION_KHR,
5316         GetParam().majorVersion,
5317         EGL_CONTEXT_MINOR_VERSION_KHR,
5318         GetParam().minorVersion,
5319         EGL_NONE,
5320     };
5321     EGLContext context1 = eglGetCurrentContext();
5322     // Create context2, sharing resources with context1.
5323     EGLContext context2 = eglCreateContext(display, config, context1, contextAttributes);
5324     ASSERT_NE(context2, EGL_NO_CONTEXT);
5325     eglMakeCurrent(display, surface, surface, context2);
5326 
5327     constexpr char kVS[] =
5328         R"(attribute vec4 a_position;
5329 void main() {
5330     gl_Position = a_position;
5331 })";
5332 
5333     constexpr char kFS[] =
5334         R"(precision mediump float;
5335 void main() {
5336     gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
5337 })";
5338 
5339     ANGLE_GL_PROGRAM(program, kVS, kFS);
5340     glUseProgram(program);
5341 
5342     ASSERT_GL_NO_ERROR();
5343 
5344     // Render to the texture in context2.
5345     GLFramebuffer framebuffer;
5346     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5347     // Texture is still a valid name in context2.
5348     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
5349     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5350     // There is no rendering feedback loop at this point.
5351 
5352     glDisable(GL_BLEND);
5353     glDisable(GL_DEPTH_TEST);
5354     ASSERT_GL_NO_ERROR();
5355 
5356     // If draw is no-op'ed, texture will not be filled appropriately.
5357     drawQuad(program, "a_position", 0.5f, 1.0f, true);
5358     ASSERT_GL_NO_ERROR();
5359     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5360 
5361     // Make context1 current again.
5362     eglMakeCurrent(display, surface, surface, context1);
5363 
5364     // Render texture to screen.
5365     drawQuad(textureProgram, "a_position", 0.5f, 1.0f, true);
5366     ASSERT_GL_NO_ERROR();
5367     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5368 
5369     eglDestroyContext(display, context2);
5370 }
5371 
5372 // Ensure cube-incomplete attachments cause incomplete Framebuffers.
TEST_P(FramebufferTest,IncompleteCubeMap)5373 TEST_P(FramebufferTest, IncompleteCubeMap)
5374 {
5375     constexpr GLuint kSize = 2;
5376 
5377     GLTexture srcTex;
5378     glBindTexture(GL_TEXTURE_CUBE_MAP, srcTex);
5379     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
5380                  GL_UNSIGNED_BYTE, nullptr);
5381 
5382     GLFramebuffer fbo;
5383     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5384     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
5385                            srcTex, 0);
5386 
5387     ASSERT_GL_NO_ERROR();
5388     ASSERT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
5389                      GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
5390 }
5391 
5392 // Test FBOs with different sizes are drawn correctly
TEST_P(FramebufferTest,BindAndDrawDifferentSizedFBOs)5393 TEST_P(FramebufferTest, BindAndDrawDifferentSizedFBOs)
5394 {
5395     // 1. Create FBO 1 with dimensions 16x16
5396     // 2. Draw red into FBO 1 (note, FramebufferVk::syncState is called)
5397     // 3. Create FBO 2 with dimensions 8x8
5398     // 4. Draw green into FBO 2 (note, FramebufferVk::syncState is called)
5399     // 5. Bind FBO 1 (note, it's not dirty)
5400     // 6. Draw blue into FBO 1
5401     // 7. Verify FBO 1 is entirely blue
5402 
5403     GLFramebuffer smallFbo;
5404     GLFramebuffer largeFbo;
5405     GLTexture smallTexture;
5406     GLTexture largeTexture;
5407     constexpr GLsizei kLargeWidth  = 16;
5408     constexpr GLsizei kLargeHeight = 16;
5409     constexpr GLsizei kSmallWidth  = 8;
5410     constexpr GLsizei kSmallHeight = 8;
5411 
5412     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
5413     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
5414     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
5415 
5416     // 1. Create FBO 1 with dimensions 16x16
5417     glBindFramebuffer(GL_FRAMEBUFFER, largeFbo);
5418     glBindTexture(GL_TEXTURE_2D, largeTexture);
5419     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kLargeWidth, kLargeHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5420                  nullptr);
5421     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5422     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5423     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
5424     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5425 
5426     // 2. Draw red into FBO 1 (note, FramebufferVk::syncState is called)
5427     glUseProgram(redProgram);
5428     drawQuad(redProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
5429     ASSERT_GL_NO_ERROR();
5430 
5431     // 3. Create FBO 2 with dimensions 8x8
5432     glBindFramebuffer(GL_FRAMEBUFFER, smallFbo);
5433     glBindTexture(GL_TEXTURE_2D, smallTexture);
5434     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallWidth, kSmallHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5435                  nullptr);
5436     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5437     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5438     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
5439     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5440 
5441     // 4. Draw green into FBO 2 (note, FramebufferVk::syncState is called)
5442     glUseProgram(greenProgram);
5443     drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
5444     ASSERT_GL_NO_ERROR();
5445 
5446     // 5. Bind FBO 1 (note, it's not dirty)
5447     glBindFramebuffer(GL_FRAMEBUFFER, largeFbo);
5448 
5449     // 6. Draw blue into FBO 1
5450     glUseProgram(blueProgram);
5451     drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
5452     ASSERT_GL_NO_ERROR();
5453 
5454     // 7. Verify FBO 1 is entirely blue
5455     EXPECT_PIXEL_RECT_EQ(0, 0, kLargeWidth, kLargeHeight, GLColor::blue);
5456 }
5457 
5458 // Test FBOs with same attachments. Destroy one framebuffer should not affect the other framebuffer
5459 // (chromium:1351170).
TEST_P(FramebufferTest_ES3,TwoFramebuffersWithSameAttachments)5460 TEST_P(FramebufferTest_ES3, TwoFramebuffersWithSameAttachments)
5461 {
5462     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
5463     glUseProgram(redProgram);
5464 
5465     GLRenderbuffer rb;
5466     glBindRenderbuffer(GL_RENDERBUFFER, rb);
5467     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
5468 
5469     GLuint fbs[2];
5470     glGenFramebuffers(2, fbs);
5471     // Create fbos[0]
5472     glBindFramebuffer(GL_FRAMEBUFFER, fbs[0]);
5473     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
5474     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5475     const GLenum colorAttachment0 = {GL_COLOR_ATTACHMENT0};
5476     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &colorAttachment0);
5477     // Create fbos[1] with same attachment as fbos[0]
5478     glBindFramebuffer(GL_FRAMEBUFFER, fbs[1]);
5479     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
5480     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5481     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &colorAttachment0);
5482     // Destroy fbos[0]
5483     glDeleteFramebuffers(1, &fbs[0]);
5484     // fbos[1] should still work, not crash.
5485     GLuint data;
5486     glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &data);
5487     drawQuad(redProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
5488     ASSERT_GL_NO_ERROR();
5489 }
5490 
5491 // Regression test based on a fuzzer failure.  A crash was encountered in the following situation:
5492 //
5493 // - Texture bound as sampler with MAX_LEVEL 0
5494 // - Framebuffer bound to level 0
5495 // - Draw
5496 // - Texture MAX_LEVEL changed to 1
5497 // - Framebuffer bound to level 1
5498 // - Draw
5499 //
5500 // Notes: Removing the first half removed the crash.  MIN_FILTERING of LINEAR vs
5501 // LINEAR_MIPMAP_LINEAR did not make any changes.
TEST_P(FramebufferTest_ES3,FramebufferBindToNewLevelAfterMaxIncreaseShouldntCrash)5502 TEST_P(FramebufferTest_ES3, FramebufferBindToNewLevelAfterMaxIncreaseShouldntCrash)
5503 {
5504     constexpr char kFS[] = R"(precision mediump float;
5505 uniform sampler2D u_tex0;
5506 void main() {
5507     gl_FragColor = texture2D(u_tex0, vec2(0));
5508 })";
5509 
5510     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), kFS);
5511     glUseProgram(program);
5512 
5513     GLTexture mutTex;
5514     glBindTexture(GL_TEXTURE_2D, mutTex);
5515     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5516     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5517 
5518     GLFramebuffer fb;
5519     glBindFramebuffer(GL_FRAMEBUFFER, fb);
5520 
5521     // Attempt a draw with level 0 (feedback loop)
5522     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
5523     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5524 
5525     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mutTex, 0);
5526     glDrawArrays(GL_POINTS, 0, 1);
5527 
5528     // Attempt another draw with level 1.
5529     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
5530 
5531     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mutTex, 1);
5532 
5533     // This shouldn't crash.
5534     glDrawArrays(GL_POINTS, 0, 1);
5535     ASSERT_GL_NO_ERROR();
5536 }
5537 
5538 // Modify renderbuffer attachment samples after bind
TEST_P(FramebufferTest_ES3,BindRenderbufferThenModifySamples)5539 TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySamples)
5540 {
5541     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5542     glUseProgram(program);
5543     GLint colorUniformLocation =
5544         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
5545     ASSERT_NE(colorUniformLocation, -1);
5546 
5547     GLFramebuffer fbo;
5548     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5549 
5550     GLsizei size = 16;
5551     glViewport(0, 0, size, size);
5552 
5553     GLRenderbuffer color;
5554     glBindRenderbuffer(GL_RENDERBUFFER, color);
5555 
5556     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, size, size);
5557     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
5558     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
5559 
5560     glUniform4f(colorUniformLocation, 1, 0, 0, 1);
5561     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
5562 
5563     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5564     ASSERT_GL_NO_ERROR();
5565 }
5566 
5567 // Modify renderbuffer attachment size after bind
TEST_P(FramebufferTest_ES3,BindRenderbufferThenModifySize)5568 TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySize)
5569 {
5570     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5571     glUseProgram(program);
5572     GLint colorUniformLocation =
5573         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
5574     ASSERT_NE(colorUniformLocation, -1);
5575 
5576     GLFramebuffer fbo;
5577     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5578 
5579     GLsizei size = 16;
5580     glViewport(0, 0, size, size);
5581 
5582     GLRenderbuffer color;
5583     glBindRenderbuffer(GL_RENDERBUFFER, color);
5584 
5585     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
5586     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
5587     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size / 2, size * 2);
5588 
5589     glUniform4f(colorUniformLocation, 1, 0, 0, 1);
5590     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
5591 
5592     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5593     ASSERT_GL_NO_ERROR();
5594 }
5595 
5596 // Tests redefining a layered framebuffer attachment.
TEST_P(FramebufferTest_ES3,RedefineLayerAttachment)5597 TEST_P(FramebufferTest_ES3, RedefineLayerAttachment)
5598 {
5599     GLTexture texture;
5600     glBindTexture(GL_TEXTURE_3D, texture);
5601     std::vector<uint8_t> imgData(20480, 0);
5602     glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, 8, 8, 8, 0, GL_RED, GL_UNSIGNED_BYTE, imgData.data());
5603 
5604     GLFramebuffer fbo;
5605     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5606     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 8);
5607     glGenerateMipmap(GL_TEXTURE_3D);
5608 
5609     glTexImage3D(GL_TEXTURE_3D, 0, GL_R8UI, 16, 16, 16, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
5610                  imgData.data());
5611     glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 2, 2, 15, 16, 16);
5612     ASSERT_GL_NO_ERROR();
5613 }
5614 
5615 // Covers a bug when changing a base level of a texture bound to a FBO.
TEST_P(FramebufferTest_ES3,ReattachToInvalidBaseLevel)5616 TEST_P(FramebufferTest_ES3, ReattachToInvalidBaseLevel)
5617 {
5618     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
5619     glUseProgram(testProgram);
5620 
5621     GLTexture tex;
5622     glBindTexture(GL_TEXTURE_2D, tex);
5623     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5624 
5625     for (int mip = 0; mip <= 2; ++mip)
5626     {
5627         int size = 10 >> mip;
5628         glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5629                      nullptr);
5630     }
5631 
5632     GLFramebuffer fb;
5633     glBindFramebuffer(GL_FRAMEBUFFER, fb);
5634     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 1);
5635     EXPECT_GL_NO_ERROR();
5636 
5637     // Set base level 1 and draw.
5638     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
5639     glDrawArrays(GL_POINTS, 0, 1);
5640     EXPECT_GL_NO_ERROR();
5641     // Set base level 0. The FBO is incomplete because the FBO attachment binds to level 1.
5642     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
5643     glDrawArrays(GL_POINTS, 0, 1);
5644     EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
5645 }
5646 
5647 // Ensure that clear color is correctly applied after invalidate
TEST_P(FramebufferTest_ES3,InvalidateClearDraw)5648 TEST_P(FramebufferTest_ES3, InvalidateClearDraw)
5649 {
5650     constexpr GLsizei kSize = 2;
5651 
5652     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
5653 
5654     GLTexture tex;
5655     glBindTexture(GL_TEXTURE_2D, tex);
5656     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5657 
5658     GLFramebuffer fbo;
5659     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5660     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5661 
5662     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5663 
5664     // Clear the image, and make sure the clear is flushed outside the render pass.
5665     glClearColor(1, 0, 0, 1);
5666     glClear(GL_COLOR_BUFFER_BIT);
5667     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5668 
5669     // Invalidate it such that the contents are marked as undefined. Note that
5670     // regardless of the marking, the image is cleared nevertheless.
5671     const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
5672     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
5673 
5674     // Clear it again to the same color, and make sure the clear is flushed outside the render pass,
5675     // which may be optimized out.
5676     glClear(GL_COLOR_BUFFER_BIT);
5677     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5678 
5679     // Draw with blend.  If the second clear is dropped and the image continues to be marked as
5680     // invalidated, loadOp=DONT_CARE would be used instead of loadOp=LOAD.
5681     glEnable(GL_BLEND);
5682     glBlendFunc(GL_ONE, GL_ONE);
5683 
5684     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
5685     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
5686 }
5687 
5688 // Produces VUID-VkImageMemoryBarrier-oldLayout-01197 VVL error with a "Render pass closed due to
5689 // framebuffer change" command buffer label. As seen in Black Desert Mobile.
5690 // The application draws 2 passes to produce the issue. First pass draws to a depth only frame
5691 // buffer, the second one to a different color+depth frame buffer. The second pass samples the first
5692 // passes frame buffer in two draw calls. First draw call samples it in the fragment stage, second
5693 // in the the vertex stage.
TEST_P(FramebufferTest_ES3,FramebufferChangeTest)5694 TEST_P(FramebufferTest_ES3, FramebufferChangeTest)
5695 {
5696     // Init depth frame buffer
5697     GLFramebuffer depthFramebuffer;
5698     glBindFramebuffer(GL_FRAMEBUFFER, depthFramebuffer);
5699 
5700     GLTexture depthAttachment;
5701     glBindTexture(GL_TEXTURE_2D, depthAttachment);
5702     // When using a color attachment instead, the issue does not occur.
5703     // The issue seems to occur for all GL_DEPTH_COMPONENT formats.
5704     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, kWidth, kHeight, 0, GL_DEPTH_COMPONENT,
5705                  GL_UNSIGNED_INT, nullptr);
5706 
5707     // If filtering the depth attachment to GL_NEAREST is not set, the issue does not occur.
5708     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5709     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5710 
5711     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthAttachment, 0);
5712 
5713     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5714     ASSERT_GL_NO_ERROR();
5715 
5716     // Depth only pass
5717     {
5718         ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
5719         glUseProgram(program);
5720 
5721         glClear(GL_DEPTH_BUFFER_BIT);
5722 
5723         glDrawArrays(GL_TRIANGLES, 0, 6);
5724         ASSERT_GL_NO_ERROR();
5725     }
5726 
5727     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5728 
5729     // Color pass
5730     // The depth texture from the first pass is sampled from in both draw calls.
5731     // Skipping any of the two depth texture binds makes the issue not occur.
5732     // Changing the order of the draw calls makes the issue not occur.
5733     // This pass does not need to draw into a frame buffer.
5734 
5735     // Draw 1
5736     // The depth texture from the first pass is sampled from in the frament stage.
5737     {
5738         constexpr char kFS[] = {
5739             R"(#version 300 es
5740 precision mediump float;
5741 
5742 uniform mediump sampler2D samp;
5743 
5744 layout(location = 0) out highp vec4 color;
5745 
5746 void main()
5747 {
5748     color = texture(samp, vec2(0));
5749 })",
5750         };
5751         ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5752         glUseProgram(program);
5753 
5754         GLint textureLoc = glGetUniformLocation(program, "samp");
5755         glUniform1i(textureLoc, 1);
5756 
5757         // Skipping this bind makes the issue not occur
5758         glActiveTexture(GL_TEXTURE1);
5759         glBindTexture(GL_TEXTURE_2D, depthAttachment);
5760 
5761         glDrawArrays(GL_TRIANGLES, 0, 6);
5762         ASSERT_GL_NO_ERROR();
5763     }
5764 
5765     // Draw 2
5766     // Here the depth attachment from the first pass is used in the vertex stage. The VVL error
5767     // occurs in this draw. The sampler has to be attached to the vertex stage, otherwise the issue
5768     // does not occur.
5769     {
5770         constexpr char kVS[] = {
5771             R"(#version 300 es
5772 
5773 uniform mediump sampler2D samp;
5774 
5775 layout(location = 0) in mediump vec4 pos;
5776 
5777 void main()
5778 {
5779     gl_Position = pos + texture(samp, vec2(0));
5780 })",
5781         };
5782 
5783         ANGLE_GL_PROGRAM(program, kVS, essl3_shaders::fs::Red());
5784         glUseProgram(program);
5785 
5786         GLint textureLoc = glGetUniformLocation(program, "samp");
5787         glUniform1i(textureLoc, 2);
5788 
5789         // Skipping this bind makes the issue not occur
5790         glActiveTexture(GL_TEXTURE2);
5791         glBindTexture(GL_TEXTURE_2D, depthAttachment);
5792 
5793         glDrawArrays(GL_TRIANGLES, 0, 6);
5794         ASSERT_GL_NO_ERROR();
5795     }
5796 }
5797 
5798 // Regression test for a bug in the Vulkan backend where the application produces a conditional
5799 // framebuffer feedback loop which results in VUID-VkDescriptorImageInfo-imageLayout-00344 and
5800 // VUID-vkCmdDraw-None-02699 (or VUID-vkCmdDrawIndexed-None-02699 when a different draw call is
5801 // used). The application samples from the frame buffer it renders to depending on a uniform
5802 // condition.
TEST_P(FramebufferTest_ES3,FramebufferConditionalFeedbackLoop)5803 TEST_P(FramebufferTest_ES3, FramebufferConditionalFeedbackLoop)
5804 {
5805     GLTexture colorAttachment;
5806     glBindTexture(GL_TEXTURE_2D, colorAttachment);
5807     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
5808 
5809     glActiveTexture(GL_TEXTURE13);
5810     glBindTexture(GL_TEXTURE_2D, colorAttachment);
5811 
5812     ASSERT_GL_NO_ERROR();
5813 
5814     GLFramebuffer framebuffer;
5815     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5816     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorAttachment, 0);
5817 
5818     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5819 
5820     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5821 
5822     constexpr char kFS[] = {
5823         R"(#version 300 es
5824 precision mediump float;
5825 
5826 uniform mediump sampler2D samp;
5827 uniform vec4 sampleCondition;
5828 out vec4 color;
5829 
5830 void main()
5831 {
5832     if (sampleCondition.x > 0.0)
5833     {
5834         color = texture(samp, vec2(0.0));
5835     }
5836 })",
5837     };
5838 
5839     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5840     glUseProgram(program);
5841 
5842     GLint textureLoc = glGetUniformLocation(program, "samp");
5843     glUniform1i(textureLoc, 13);
5844 
5845     // This draw is required for the issue to occur. The application does multiple draws to
5846     // different framebuffers at this point, but drawing without a framebuffer bound also does
5847     // reproduce it.
5848     glDrawArrays(GL_TRIANGLES, 0, 6);
5849     ASSERT_GL_NO_ERROR();
5850 
5851     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5852 
5853     // This draw triggers the issue.
5854     glDrawArrays(GL_TRIANGLES, 0, 6);
5855     ASSERT_GL_NO_ERROR();
5856 }
5857 
5858 // Regression test for a bug in the Vulkan backend where sampling from a
5859 // texture previously involved in a framebuffer feedback loop would produce
5860 // VUID-VkDescriptorImageInfo-imageLayout-00344 and VUID-vkCmdDraw-None-02699
5861 // because of an incorrect cached descriptor set.
TEST_P(FramebufferTest_ES3,FeedbackLoopTextureBindings)5862 TEST_P(FramebufferTest_ES3, FeedbackLoopTextureBindings)
5863 {
5864     constexpr char kVS[] = R"(#version 300 es
5865 precision highp float;
5866 out vec2 texCoord;
5867 const vec2 kVertices[4] = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));
5868 void main()
5869 {
5870     gl_Position = vec4(kVertices[gl_VertexID], 0.0, 1.0);
5871     texCoord = (kVertices[gl_VertexID] * 0.5) + 0.5;
5872 })";
5873 
5874     constexpr char kFS[] = R"(#version 300 es
5875 precision highp float;
5876 uniform sampler2D sampler;
5877 uniform int sampleCondition;
5878 in vec2 texCoord;
5879 out vec4 colorOut;
5880 const vec4 kGreen = vec4(0, 1, 0, 1);
5881 void main()
5882 {
5883     if (sampleCondition == 0) {
5884         colorOut = kGreen;
5885     } else {
5886         colorOut = texture(sampler, texCoord);
5887     }
5888 })";
5889 
5890     ANGLE_GL_PROGRAM(program, kVS, kFS);
5891     GLint sampleCondition = glGetUniformLocation(program, "sampleCondition");
5892     glUseProgram(program);
5893 
5894     GLTexture tex;
5895     glActiveTexture(GL_TEXTURE0);
5896     glBindTexture(GL_TEXTURE_2D, tex);
5897     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
5898     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
5899 
5900     // Render to tex with tex bound but not sampled
5901     GLFramebuffer framebuffer;
5902     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5903     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
5904     const GLenum buffers[]{GL_COLOR_ATTACHMENT0};
5905     glDrawBuffers(1, buffers);
5906     glUniform1i(sampleCondition, 0);
5907     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5908     ASSERT_GL_NO_ERROR();
5909 
5910     // Render to default framebuffer with tex bound and sampled
5911     glBindFramebuffer(GL_FRAMEBUFFER, 0);
5912     glUniform1i(sampleCondition, 1);
5913     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5914     ASSERT_GL_NO_ERROR();
5915 }
5916 
5917 // Tests change of framebuffer dimensions vs gl_FragCoord.
TEST_P(FramebufferTest_ES3,FramebufferDimensionsChangeAndFragCoord)5918 TEST_P(FramebufferTest_ES3, FramebufferDimensionsChangeAndFragCoord)
5919 {
5920     constexpr char kVS[] = R"(#version 300 es
5921 precision highp float;
5922 uniform float height;
5923 void main()
5924 {
5925     // gl_VertexID    x    y
5926     //      0        -1   -1
5927     //      1         1   -1
5928     //      2        -1    1
5929     //      3         1    1
5930     int bit0 = gl_VertexID & 1;
5931     int bit1 = gl_VertexID >> 1;
5932     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
5933 })";
5934 
5935     constexpr char kFS[] = R"(#version 300 es
5936 precision mediump float;
5937 out vec4 colorOut;
5938 void main()
5939 {
5940     float red = gl_FragCoord.x < 10. ? 1.0 : 0.0;
5941     float green = gl_FragCoord.y < 25. ? 1.0 : 0.0;
5942     colorOut = vec4(red, green, 0, 1);
5943 })";
5944 
5945     ANGLE_GL_PROGRAM(program, kVS, kFS);
5946 
5947     constexpr GLuint kWidth1       = 99;
5948     constexpr GLuint kHeight1      = 142;
5949     constexpr GLuint kWidth2       = 75;
5950     constexpr GLuint kHeight2      = 167;
5951     constexpr GLuint kRenderSplitX = 10;
5952     constexpr GLuint kRenderSplitY = 25;
5953 
5954     glViewport(0, 0, std::max(kWidth1, kWidth2), std::max(kHeight1, kHeight2));
5955 
5956     GLTexture tex1, tex2;
5957     glBindTexture(GL_TEXTURE_2D, tex1);
5958     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth1, kHeight1);
5959     glBindTexture(GL_TEXTURE_2D, tex2);
5960     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth2, kHeight2);
5961 
5962     GLFramebuffer fbo;
5963     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5964 
5965     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex1, 0);
5966     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5967 
5968     glUseProgram(program);
5969     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5970 
5971     // Verify results
5972     EXPECT_PIXEL_RECT_EQ(0, 0, kRenderSplitX, kRenderSplitY, GLColor::yellow);
5973     EXPECT_PIXEL_RECT_EQ(0, kRenderSplitY, kRenderSplitX, kHeight1 - kRenderSplitY, GLColor::red);
5974     EXPECT_PIXEL_RECT_EQ(kRenderSplitX, 0, kWidth1 - kRenderSplitX, kRenderSplitY, GLColor::green);
5975     EXPECT_PIXEL_RECT_EQ(kRenderSplitX, kRenderSplitY, kWidth1 - kRenderSplitX,
5976                          kHeight1 - kRenderSplitY, GLColor::black);
5977 
5978     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2, 0);
5979     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5980 
5981     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5982 
5983     // Verify results
5984     EXPECT_PIXEL_RECT_EQ(0, 0, kRenderSplitX, kRenderSplitY, GLColor::yellow);
5985     EXPECT_PIXEL_RECT_EQ(0, kRenderSplitY, kRenderSplitX, kHeight2 - kRenderSplitY, GLColor::red);
5986     EXPECT_PIXEL_RECT_EQ(kRenderSplitX, 0, kWidth2 - kRenderSplitX, kRenderSplitY, GLColor::green);
5987     EXPECT_PIXEL_RECT_EQ(kRenderSplitX, kRenderSplitY, kWidth2 - kRenderSplitX,
5988                          kHeight2 - kRenderSplitY, GLColor::black);
5989 
5990     ASSERT_GL_NO_ERROR();
5991 }
5992 
5993 // Tests change of surface dimensions vs gl_FragCoord.
TEST_P(FramebufferTest_ES3,SurfaceDimensionsChangeAndFragCoord)5994 TEST_P(FramebufferTest_ES3, SurfaceDimensionsChangeAndFragCoord)
5995 {
5996     constexpr char kVS[] = R"(#version 300 es
5997 precision highp float;
5998 uniform float height;
5999 void main()
6000 {
6001     // gl_VertexID    x    y
6002     //      0        -1   -1
6003     //      1         1   -1
6004     //      2        -1    1
6005     //      3         1    1
6006     int bit0 = gl_VertexID & 1;
6007     int bit1 = gl_VertexID >> 1;
6008     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
6009 })";
6010 
6011     constexpr char kFS[] = R"(#version 300 es
6012 precision mediump float;
6013 out vec4 colorOut;
6014 void main()
6015 {
6016     float red = gl_FragCoord.x < 10. ? 1.0 : 0.0;
6017     float green = gl_FragCoord.y < 25. ? 1.0 : 0.0;
6018     colorOut = vec4(red, green, 0, 1);
6019 })";
6020 
6021     ANGLE_GL_PROGRAM(program, kVS, kFS);
6022 
6023     constexpr GLuint kWidth1       = 99;
6024     constexpr GLuint kHeight1      = 142;
6025     constexpr GLuint kWidth2       = 75;
6026     constexpr GLuint kHeight2      = 167;
6027     constexpr GLuint kRenderSplitX = 10;
6028     constexpr GLuint kRenderSplitY = 25;
6029 
6030     glViewport(0, 0, std::max(kWidth1, kWidth2), std::max(kHeight1, kHeight2));
6031 
6032     const bool isSwappedDimensions =
6033         getEGLWindow()->isFeatureEnabled(Feature::EmulatedPrerotation90) ||
6034         getEGLWindow()->isFeatureEnabled(Feature::EmulatedPrerotation270);
6035 
6036     auto resizeWindow = [this, isSwappedDimensions](GLuint width, GLuint height) {
6037         if (isSwappedDimensions)
6038         {
6039             getOSWindow()->resize(height, width);
6040         }
6041         else
6042         {
6043             getOSWindow()->resize(width, height);
6044         }
6045         swapBuffers();
6046     };
6047 
6048     resizeWindow(kWidth1, kHeight1);
6049     glUseProgram(program);
6050     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6051 
6052     // Verify results
6053     EXPECT_PIXEL_RECT_EQ(0, 0, kRenderSplitX, kRenderSplitY, GLColor::yellow);
6054     EXPECT_PIXEL_RECT_EQ(0, kRenderSplitY, kRenderSplitX, kHeight1 - kRenderSplitY, GLColor::red);
6055     EXPECT_PIXEL_RECT_EQ(kRenderSplitX, 0, kWidth1 - kRenderSplitX, kRenderSplitY, GLColor::green);
6056     EXPECT_PIXEL_RECT_EQ(kRenderSplitX, kRenderSplitY, kWidth1 - kRenderSplitX,
6057                          kHeight1 - kRenderSplitY, GLColor::black);
6058 
6059     resizeWindow(kWidth2, kHeight2);
6060     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6061 
6062     // Verify results
6063     EXPECT_PIXEL_RECT_EQ(0, 0, kRenderSplitX, kRenderSplitY, GLColor::yellow);
6064     EXPECT_PIXEL_RECT_EQ(0, kRenderSplitY, kRenderSplitX, kHeight2 - kRenderSplitY, GLColor::red);
6065     EXPECT_PIXEL_RECT_EQ(kRenderSplitX, 0, kWidth2 - kRenderSplitX, kRenderSplitY, GLColor::green);
6066     EXPECT_PIXEL_RECT_EQ(kRenderSplitX, kRenderSplitY, kWidth2 - kRenderSplitX,
6067                          kHeight2 - kRenderSplitY, GLColor::black);
6068 
6069     // Reset window to original dimensions
6070     resizeWindow(kWidth, kHeight);
6071 
6072     ASSERT_GL_NO_ERROR();
6073 }
6074 
6075 // Tests blits between draw and read surfaces with different pre-rotation values.
TEST_P(FramebufferTest_ES3,BlitWithDifferentPreRotations)6076 TEST_P(FramebufferTest_ES3, BlitWithDifferentPreRotations)
6077 {
6078     // TODO(anglebug.com/7594): Untriaged bot failures with non-Vulkan backends
6079     ANGLE_SKIP_TEST_IF(!IsVulkan());
6080 
6081     EGLWindow *window = getEGLWindow();
6082     ASSERT(window);
6083     EGLConfig config   = window->getConfig();
6084     EGLContext context = window->getContext();
6085     EGLDisplay dpy     = window->getDisplay();
6086     EGLint surfaceType = 0;
6087 
6088     // Skip if pbuffer surface is not supported
6089     eglGetConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType);
6090     ANGLE_SKIP_TEST_IF((surfaceType & EGL_PBUFFER_BIT) == 0);
6091 
6092     const EGLint surfaceWidth        = static_cast<EGLint>(getWindowWidth());
6093     const EGLint surfaceHeight       = static_cast<EGLint>(getWindowHeight());
6094     const EGLint pBufferAttributes[] = {
6095         EGL_WIDTH, surfaceWidth, EGL_HEIGHT, surfaceHeight, EGL_NONE,
6096     };
6097 
6098     // Create Pbuffer surface
6099     EGLSurface pbufferSurface = eglCreatePbufferSurface(dpy, config, pBufferAttributes);
6100     ASSERT_NE(pbufferSurface, EGL_NO_SURFACE);
6101     ASSERT_EGL_SUCCESS();
6102 
6103     EGLSurface windowSurface = window->getSurface();
6104     ASSERT_NE(windowSurface, EGL_NO_SURFACE);
6105 
6106     // Clear window surface with red color
6107     EXPECT_EGL_TRUE(eglMakeCurrent(dpy, windowSurface, windowSurface, context));
6108     ASSERT_EGL_SUCCESS();
6109     glClearColor(1, 0, 0, 1);
6110     glClear(GL_COLOR_BUFFER_BIT);
6111     EXPECT_PIXEL_RECT_EQ(0, 0, surfaceWidth, surfaceHeight, GLColor::red);
6112 
6113     // Blit from window surface to pbuffer surface and expect red color
6114     EXPECT_EGL_TRUE(eglMakeCurrent(dpy, pbufferSurface, windowSurface, context));
6115     ASSERT_EGL_SUCCESS();
6116 
6117     glBlitFramebuffer(0, 0, surfaceWidth, surfaceHeight, 0, 0, surfaceWidth, surfaceHeight,
6118                       GL_COLOR_BUFFER_BIT, GL_NEAREST);
6119     ASSERT_GL_NO_ERROR();
6120     EXPECT_PIXEL_RECT_EQ(0, 0, surfaceWidth, surfaceHeight, GLColor::red);
6121 
6122     // Clear pbuffer surface with blue color
6123     EXPECT_EGL_TRUE(eglMakeCurrent(dpy, pbufferSurface, pbufferSurface, context));
6124     ASSERT_EGL_SUCCESS();
6125     glClearColor(0, 0, 1, 1);
6126     glClear(GL_COLOR_BUFFER_BIT);
6127     EXPECT_PIXEL_RECT_EQ(0, 0, surfaceWidth, surfaceHeight, GLColor::blue);
6128 
6129     // Blit from pbuffer surface to window surface and expect blue color
6130     EXPECT_EGL_TRUE(eglMakeCurrent(dpy, windowSurface, pbufferSurface, context));
6131     ASSERT_EGL_SUCCESS();
6132 
6133     glBlitFramebuffer(0, 0, surfaceWidth, surfaceHeight, 0, 0, surfaceWidth, surfaceHeight,
6134                       GL_COLOR_BUFFER_BIT, GL_NEAREST);
6135     ASSERT_GL_NO_ERROR();
6136     EXPECT_PIXEL_RECT_EQ(0, 0, surfaceWidth, surfaceHeight, GLColor::blue);
6137 
6138     EXPECT_EGL_TRUE(eglMakeCurrent(dpy, windowSurface, windowSurface, context));
6139     ASSERT_EGL_SUCCESS();
6140 
6141     EXPECT_EGL_TRUE(eglDestroySurface(dpy, pbufferSurface));
6142     ASSERT_EGL_SUCCESS();
6143 }
6144 
6145 // Tests draw to surfaces with different pre-rotation values.
TEST_P(FramebufferTest_ES3,DrawWithDifferentPreRotations)6146 TEST_P(FramebufferTest_ES3, DrawWithDifferentPreRotations)
6147 {
6148     EGLWindow *window = getEGLWindow();
6149     ASSERT(window);
6150     EGLConfig config   = window->getConfig();
6151     EGLContext context = window->getContext();
6152     EGLDisplay dpy     = window->getDisplay();
6153     EGLint surfaceType = 0;
6154 
6155     // Skip if pbuffer surface is not supported
6156     eglGetConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType);
6157     ANGLE_SKIP_TEST_IF((surfaceType & EGL_PBUFFER_BIT) == 0);
6158 
6159     const EGLint surfaceWidth        = static_cast<EGLint>(getWindowWidth());
6160     const EGLint surfaceHeight       = static_cast<EGLint>(getWindowHeight());
6161     const EGLint pBufferAttributes[] = {
6162         EGL_WIDTH, surfaceWidth, EGL_HEIGHT, surfaceHeight, EGL_NONE,
6163     };
6164 
6165     // Create Pbuffer surface
6166     EGLSurface pbufferSurface = eglCreatePbufferSurface(dpy, config, pBufferAttributes);
6167     ASSERT_NE(pbufferSurface, EGL_NO_SURFACE);
6168     ASSERT_EGL_SUCCESS();
6169 
6170     EGLSurface windowSurface = window->getSurface();
6171     ASSERT_NE(windowSurface, EGL_NO_SURFACE);
6172 
6173     constexpr char kCheckered2FS[] = R"(precision highp float;
6174 varying vec4 v_position;
6175 
6176 void main()
6177 {
6178     bool isLeft = v_position.x < 0.0;
6179     bool isTop = v_position.y < 0.0;
6180     if (isLeft)
6181     {
6182         if (isTop)
6183         {
6184             gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
6185         }
6186         else
6187         {
6188             gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0);
6189         }
6190     }
6191     else
6192     {
6193         if (isTop)
6194         {
6195             gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
6196         }
6197         else
6198         {
6199             gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
6200         }
6201     }
6202 })";
6203 
6204     ANGLE_GL_PROGRAM(checkerProgram, essl1_shaders::vs::Passthrough(),
6205                      essl1_shaders::fs::Checkered());
6206     ANGLE_GL_PROGRAM(checkerProgram2, essl1_shaders::vs::Passthrough(), kCheckered2FS);
6207 
6208     // The test does the following:
6209     //
6210     // 1. draw checkered to window (rotated)
6211     // 2. draw checkered to pbuffer (not rotated)
6212     // 3. verify rendering to window, draw checkered2, verify again
6213     // 4. verify rendering to pbuffer, draw checkered2, verify again
6214     //
6215     // Step 2 ensures that the correct state is used after a change to the bound surface (from
6216     // rotated to not). Step 3 ensures the same from not rotated to rotated.  Step 4 is a redundant
6217     // check.
6218 
6219     // Step 1
6220     EXPECT_EGL_TRUE(eglMakeCurrent(dpy, windowSurface, windowSurface, context));
6221     ASSERT_EGL_SUCCESS();
6222 
6223     drawQuad(checkerProgram, essl1_shaders::PositionAttrib(), 0);
6224 
6225     // Step 2
6226     EXPECT_EGL_TRUE(eglMakeCurrent(dpy, pbufferSurface, windowSurface, context));
6227     ASSERT_EGL_SUCCESS();
6228 
6229     drawQuad(checkerProgram, essl1_shaders::PositionAttrib(), 0);
6230 
6231     // Step 3
6232     EXPECT_EGL_TRUE(eglMakeCurrent(dpy, windowSurface, windowSurface, context));
6233     ASSERT_EGL_SUCCESS();
6234 
6235     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6236     EXPECT_PIXEL_COLOR_EQ(0, surfaceHeight - 1, GLColor::green);
6237     EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, 0, GLColor::blue);
6238     EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, surfaceHeight - 1, GLColor::yellow);
6239 
6240     drawQuad(checkerProgram2, essl1_shaders::PositionAttrib(), 0);
6241 
6242     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
6243     EXPECT_PIXEL_COLOR_EQ(0, surfaceHeight - 1, GLColor::cyan);
6244     EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, 0, GLColor::magenta);
6245     EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, surfaceHeight - 1, GLColor::white);
6246 
6247     // Step 4
6248     EXPECT_EGL_TRUE(eglMakeCurrent(dpy, pbufferSurface, pbufferSurface, context));
6249     ASSERT_EGL_SUCCESS();
6250 
6251     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6252     EXPECT_PIXEL_COLOR_EQ(0, surfaceHeight - 1, GLColor::green);
6253     EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, 0, GLColor::blue);
6254     EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, surfaceHeight - 1, GLColor::yellow);
6255 
6256     drawQuad(checkerProgram2, essl1_shaders::PositionAttrib(), 0);
6257 
6258     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
6259     EXPECT_PIXEL_COLOR_EQ(0, surfaceHeight - 1, GLColor::cyan);
6260     EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, 0, GLColor::magenta);
6261     EXPECT_PIXEL_COLOR_EQ(surfaceWidth - 1, surfaceHeight - 1, GLColor::white);
6262 
6263     EXPECT_EGL_TRUE(eglMakeCurrent(dpy, windowSurface, windowSurface, context));
6264     ASSERT_EGL_SUCCESS();
6265 
6266     EXPECT_EGL_TRUE(eglDestroySurface(dpy, pbufferSurface));
6267     ASSERT_EGL_SUCCESS();
6268 }
6269 
6270 class FramebufferExtensionsTest : public FramebufferTest
6271 {
6272   protected:
FramebufferExtensionsTest()6273     FramebufferExtensionsTest() { setExtensionsEnabled(false); }
6274 
checkParameter(GLenum expectedComponentType)6275     void checkParameter(GLenum expectedComponentType)
6276     {
6277         GLint componentType = 0;
6278         glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
6279                                               GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT,
6280                                               &componentType);
6281         EXPECT_EQ(componentType, static_cast<GLint>(expectedComponentType));
6282         if (expectedComponentType)
6283         {
6284             EXPECT_GL_NO_ERROR();
6285         }
6286         else
6287         {
6288             EXPECT_GL_ERROR(GL_INVALID_ENUM);
6289         }
6290     }
6291 
checkTexture(GLenum format,GLenum type,GLenum expectedComponentType)6292     void checkTexture(GLenum format, GLenum type, GLenum expectedComponentType)
6293     {
6294         GLTexture texture;
6295         glBindTexture(GL_TEXTURE_2D, texture);
6296         glTexImage2D(GL_TEXTURE_2D, 0, format, 8, 8, 0, format, type, nullptr);
6297         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
6298         ASSERT_GL_NO_ERROR();
6299         checkParameter(expectedComponentType);
6300     }
6301 
checkRenderbuffer(GLenum format,GLenum expectedComponentType)6302     void checkRenderbuffer(GLenum format, GLenum expectedComponentType)
6303     {
6304         GLRenderbuffer renderbuffer;
6305         glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
6306         glRenderbufferStorage(GL_RENDERBUFFER, format, 8, 8);
6307         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
6308                                   renderbuffer);
6309         ASSERT_GL_NO_ERROR();
6310         checkParameter(expectedComponentType);
6311     }
6312 
test(const char * extensionName,GLenum format,bool supportsRenderbuffer)6313     void test(const char *extensionName, GLenum format, bool supportsRenderbuffer)
6314     {
6315         GLFramebuffer fbo;
6316         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6317         checkTexture(GL_RGBA, GL_UNSIGNED_BYTE, 0);
6318         checkRenderbuffer(GL_RGB565, 0);
6319 
6320         ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled(extensionName));
6321 
6322         checkTexture(GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED_EXT);
6323         checkRenderbuffer(GL_RGB565, GL_UNSIGNED_NORMALIZED_EXT);
6324 
6325         if (supportsRenderbuffer)
6326             checkRenderbuffer(format, GL_FLOAT);
6327     }
6328 };
6329 
6330 // Tests that GL_EXT_color_buffer_half_float enables component type state queries on
6331 // framebuffer attachments.
TEST_P(FramebufferExtensionsTest,ColorBufferHalfFloat)6332 TEST_P(FramebufferExtensionsTest, ColorBufferHalfFloat)
6333 {
6334     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_texture_half_float"));
6335     test("GL_EXT_color_buffer_half_float", GL_RGBA16F_EXT, true);
6336 }
6337 
6338 // Tests that GL_CHROMIUM_color_buffer_float_rgb enables component type state queries on
6339 // framebuffer attachments.
TEST_P(FramebufferExtensionsTest,ColorBufferFloatRgb)6340 TEST_P(FramebufferExtensionsTest, ColorBufferFloatRgb)
6341 {
6342     test("GL_CHROMIUM_color_buffer_float_rgb", GL_RGB32F_EXT, false);
6343 }
6344 
6345 // Tests that GL_CHROMIUM_color_buffer_float_rgba enables component type state queries on
6346 // framebuffer attachments.
TEST_P(FramebufferExtensionsTest,ColorBufferFloatRgba)6347 TEST_P(FramebufferExtensionsTest, ColorBufferFloatRgba)
6348 {
6349     test("GL_CHROMIUM_color_buffer_float_rgba", GL_RGBA32F_EXT, true);
6350 }
6351 
6352 class DefaultFramebufferTest : public ANGLETest<>
6353 {
6354   protected:
DefaultFramebufferTest()6355     DefaultFramebufferTest()
6356     {
6357         setWindowWidth(kWidth);
6358         setWindowHeight(kHeight);
6359     }
6360 
6361     static constexpr GLsizei kWidth  = 16;
6362     static constexpr GLsizei kHeight = 16;
6363 };
6364 
6365 // glReadPixel from default FBO with format and type retrieved from
6366 // GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE
6367 // should work
TEST_P(DefaultFramebufferTest,ReadFromDefaultFBOOnDefaultEGLWindowSurface)6368 TEST_P(DefaultFramebufferTest, ReadFromDefaultFBOOnDefaultEGLWindowSurface)
6369 {
6370     // Bind the default framebuffer
6371     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6372 
6373     // Create shader programs
6374     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6375 
6376     constexpr char kVS1[] = R"(#version 300 es
6377 in highp vec2 a_position;
6378 in highp vec2 a_texcoord;
6379 out highp vec2 texcoord;
6380 void main()
6381 {
6382     gl_Position = vec4(a_position, 0.0, 1.0);
6383     texcoord = a_texcoord;
6384 })";
6385 
6386     constexpr char kFS1[] = R"(#version 300 es
6387 precision highp float;
6388 in highp vec2 texcoord;
6389 out highp vec4 fragColor;
6390 uniform highp sampler2D texSampler;
6391 
6392 void main()
6393 {
6394     fragColor = texture(texSampler, texcoord);
6395 })";
6396 
6397     ANGLE_GL_PROGRAM(program, kVS1, kFS1);
6398     glUseProgram(program);
6399     ASSERT_GL_NO_ERROR();
6400 
6401     // Create Vertex data
6402     const std::vector<float> positions = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f};
6403     GLBuffer vertexBuffer;
6404     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6405     glBufferData(GL_ARRAY_BUFFER, sizeof(positions[0]) * positions.size(), positions.data(),
6406                  GL_STATIC_DRAW);
6407     GLint vertexPosLocation = glGetAttribLocation(program, "a_position");
6408     ASSERT_NE(vertexPosLocation, -1);
6409     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6410     glEnableVertexAttribArray(vertexPosLocation);
6411     glVertexAttribPointer(vertexPosLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
6412 
6413     const std::vector<float> texcoords = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f};
6414     GLBuffer texcoordBuffer;
6415     glBindBuffer(GL_ARRAY_BUFFER, texcoordBuffer);
6416     glBufferData(GL_ARRAY_BUFFER, sizeof(texcoords[0]) * texcoords.size(), texcoords.data(),
6417                  GL_STATIC_DRAW);
6418     GLint texCoordLocation = glGetAttribLocation(program, "a_texcoord");
6419     ASSERT_NE(texCoordLocation, -1);
6420     glBindBuffer(GL_ARRAY_BUFFER, texcoordBuffer);
6421     glEnableVertexAttribArray(texCoordLocation);
6422     glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
6423 
6424     const std::vector<uint16_t> quadIndices = {0, 1, 2, 2, 1, 3};
6425     GLBuffer indexBuffer;
6426     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6427     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices[0]) * quadIndices.size(),
6428                  quadIndices.data(), GL_STATIC_DRAW);
6429     ASSERT_GL_NO_ERROR();
6430 
6431     // Create Texture
6432     GLTexture texture;
6433     glBindTexture(GL_TEXTURE_2D, texture);
6434     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6435     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6436     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
6437     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
6438     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6439 
6440     std::vector<uint8_t> texData;
6441 
6442     constexpr size_t width               = 4;
6443     constexpr size_t height              = 4;
6444     constexpr size_t bytePerColorChannel = 4;
6445     constexpr uint8_t texColorPerChannel = 125;
6446 
6447     texData.resize(width * height * bytePerColorChannel);
6448 
6449     for (size_t i = 0; i < width * height; ++i)
6450     {
6451         texData.push_back(texColorPerChannel);
6452         texData.push_back(texColorPerChannel);
6453         texData.push_back(texColorPerChannel);
6454         texData.push_back(texColorPerChannel);
6455     }
6456 
6457     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6458                  texData.data());
6459     ASSERT_GL_NO_ERROR();
6460 
6461     // Initialize uniform values
6462     GLint uniformTextureSamplerLocation = glGetUniformLocation(program, "texSampler");
6463     glUniform1i(uniformTextureSamplerLocation, 0);
6464     ASSERT_GL_NO_ERROR();
6465 
6466     // Disable Dither
6467     glDisable(GL_DITHER);
6468 
6469     // Draw quad
6470     glDrawElements(GL_TRIANGLES, quadIndices.size(), GL_UNSIGNED_BYTE, 0);
6471 
6472     // Get glReadPixel format and type
6473     GLint readFormat;
6474     glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
6475 
6476     GLint readType;
6477     glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
6478 
6479     // Read Pixel with glReadPixel
6480     std::vector<uint8_t> renderResult;
6481     renderResult.resize(width * height * 4);
6482     glReadPixels(0, 0, width, height, readFormat, readType, renderResult.data());
6483 
6484     // glReadPixel with format and type retrieved from
6485     // GL_IMPLEMENTATION_COLOR_READ_FORMAT &
6486     // GL_IMPLEMENTATION_COLOR_READ_TYPE
6487     // should not trigger errors
6488     ASSERT_GL_NO_ERROR();
6489 }
6490 
6491 // Test resolving the same framebuffer into two different ones
TEST_P(FramebufferTest_ES31,MultisampleResolveMultipleTimes)6492 TEST_P(FramebufferTest_ES31, MultisampleResolveMultipleTimes)
6493 {
6494     constexpr int kWidth  = 16;
6495     constexpr int kHeight = 20;
6496     glViewport(0, 0, kWidth, kHeight);
6497 
6498     GLFramebuffer msaaFBO;
6499     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6500 
6501     GLTexture texture;
6502     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
6503     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
6504     ASSERT_GL_NO_ERROR();
6505     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
6506                            0);
6507     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6508 
6509     // Create two resolve FBOs and textures. Use different texture levels and layers.
6510     GLTexture resolveTexture1;
6511     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
6512     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kWidth * 2, kHeight * 2);
6513 
6514     GLFramebuffer resolveFBO1;
6515     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
6516     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 1);
6517     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6518 
6519     GLTexture resolveTexture2;
6520     glBindTexture(GL_TEXTURE_2D_ARRAY, resolveTexture2);
6521     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kWidth * 4, kHeight * 4, 5);
6522 
6523     GLFramebuffer resolveFBO2;
6524     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
6525     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolveTexture2, 2, 3);
6526     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6527 
6528     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6529     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
6530                      essl31_shaders::fs::RedGreenGradient());
6531     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6532     ASSERT_GL_NO_ERROR();
6533 
6534     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
6535     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
6536                       GL_NEAREST);
6537     ASSERT_GL_NO_ERROR();
6538 
6539     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
6540     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
6541                       GL_NEAREST);
6542     ASSERT_GL_NO_ERROR();
6543 
6544     auto verify = [](GLuint fbo) {
6545         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
6546         constexpr uint8_t kWidthHalfPixelGradient  = 256 / kWidth / 2;
6547         constexpr uint8_t kHeightHalfPixelGradient = 256 / kHeight / 2;
6548         EXPECT_PIXEL_NEAR(0, 0, kWidthHalfPixelGradient, kHeightHalfPixelGradient, 0, 255, 1.0);
6549         EXPECT_PIXEL_NEAR(kWidth - 1, 0, 255 - kWidthHalfPixelGradient, kHeightHalfPixelGradient, 0,
6550                           255, 1.0);
6551         EXPECT_PIXEL_NEAR(0, kHeight - 1, kWidthHalfPixelGradient, 255 - kHeightHalfPixelGradient,
6552                           0, 255, 1.0);
6553         EXPECT_PIXEL_NEAR(kWidth - 1, kHeight - 1, 255 - kWidthHalfPixelGradient,
6554                           255 - kHeightHalfPixelGradient, 0, 255, 1.0);
6555     };
6556 
6557     verify(resolveFBO1);
6558     verify(resolveFBO2);
6559     ASSERT_GL_NO_ERROR();
6560 }
6561 
6562 // Test resolving the same depth/stencil attachment into two different framebuffers
TEST_P(FramebufferTest_ES31,MultisampleDepthStencilResolveMultipleTimes)6563 TEST_P(FramebufferTest_ES31, MultisampleDepthStencilResolveMultipleTimes)
6564 {
6565     enum class DepthStencilResolve
6566     {
6567         Simultaneous,
6568         SeparateAspectsButSameFramebuffer,
6569         SeparateAspectsDifferentFramebuffers,
6570     };
6571 
6572     constexpr int kWidth  = 24;
6573     constexpr int kHeight = 12;
6574     glViewport(0, 0, kWidth, kHeight);
6575 
6576     GLFramebuffer msaaFBO;
6577     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6578 
6579     GLRenderbuffer depthStencil;
6580     glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
6581     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kWidth, kHeight);
6582     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
6583                               depthStencil);
6584     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6585     ASSERT_GL_NO_ERROR();
6586 
6587     // Create two resolve FBOs and textures. Use different texture levels and layers.
6588     GLTexture resolveTexture1;
6589     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
6590     glTexStorage2D(GL_TEXTURE_2D, 4, GL_DEPTH24_STENCIL8, kWidth * 4, kHeight * 4);
6591 
6592     GLFramebuffer resolveFBO1;
6593     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
6594     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
6595                            resolveTexture1, 2);
6596     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6597 
6598     GLTexture resolveTexture2;
6599     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
6600     glTexStorage2D(GL_TEXTURE_2D, 2, GL_DEPTH24_STENCIL8, kWidth * 2, kHeight * 2);
6601 
6602     GLFramebuffer resolveFBO2;
6603     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
6604     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
6605                            resolveTexture2, 1);
6606     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6607 
6608     ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
6609 
6610     auto runTest = [&](float depth, int stencil, DepthStencilResolve resolve) {
6611         glEnable(GL_DEPTH_TEST);
6612         glDepthFunc(GL_ALWAYS);
6613         glDepthMask(GL_TRUE);
6614         glEnable(GL_STENCIL_TEST);
6615         glStencilFunc(GL_ALWAYS, stencil, 0xFF);
6616         glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
6617         glStencilMask(0xFF);
6618 
6619         // Initialize the depth/stencil image
6620         glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6621         drawQuad(red, essl1_shaders::PositionAttrib(), depth);
6622         ASSERT_GL_NO_ERROR();
6623 
6624         // Resolve depth and stencil, then verify the results
6625         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
6626         switch (resolve)
6627         {
6628             case DepthStencilResolve::Simultaneous:
6629                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6630                                   GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6631                 break;
6632             case DepthStencilResolve::SeparateAspectsButSameFramebuffer:
6633                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
6634                                   GL_NEAREST);
6635                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6636                                   GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6637                 break;
6638             case DepthStencilResolve::SeparateAspectsDifferentFramebuffers:
6639                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
6640                                   GL_NEAREST);
6641                 break;
6642         }
6643 
6644         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
6645         switch (resolve)
6646         {
6647             case DepthStencilResolve::Simultaneous:
6648                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6649                                   GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6650                 break;
6651             case DepthStencilResolve::SeparateAspectsButSameFramebuffer:
6652                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
6653                                   GL_NEAREST);
6654                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6655                                   GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6656                 break;
6657             case DepthStencilResolve::SeparateAspectsDifferentFramebuffers:
6658                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6659                                   GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6660                 break;
6661         }
6662         ASSERT_GL_NO_ERROR();
6663 
6664         verifyDepth(resolveFBO1, kWidth, kHeight, depth);
6665         if (resolve != DepthStencilResolve::SeparateAspectsDifferentFramebuffers)
6666         {
6667             verifyStencil(resolveFBO1, kWidth, kHeight, stencil);
6668             verifyDepth(resolveFBO2, kWidth, kHeight, depth);
6669         }
6670         verifyStencil(resolveFBO2, kWidth, kHeight, stencil);
6671     };
6672 
6673     runTest(0.8f, 0x55, DepthStencilResolve::Simultaneous);
6674     runTest(0.2f, 0x3A, DepthStencilResolve::SeparateAspectsButSameFramebuffer);
6675     runTest(0.5f, 0x98, DepthStencilResolve::SeparateAspectsDifferentFramebuffers);
6676     ASSERT_GL_NO_ERROR();
6677 }
6678 
6679 // Test resolving the same framebuffer into two different ones with a draw in between
TEST_P(FramebufferTest_ES31,MultisampleResolveMultipleTimesWithDrawInBetween)6680 TEST_P(FramebufferTest_ES31, MultisampleResolveMultipleTimesWithDrawInBetween)
6681 {
6682     constexpr int kWidth  = 16;
6683     constexpr int kHeight = 20;
6684     glViewport(0, 0, kWidth, kHeight);
6685 
6686     GLFramebuffer msaaFBO;
6687     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6688 
6689     GLTexture texture;
6690     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture);
6691     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
6692     ASSERT_GL_NO_ERROR();
6693     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texture,
6694                            0);
6695     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6696 
6697     // Create two resolve FBOs and textures. Use different texture levels and layers.
6698     GLTexture resolveTexture1;
6699     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
6700     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kWidth * 2, kHeight * 2);
6701 
6702     GLFramebuffer resolveFBO1;
6703     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
6704     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 1);
6705     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6706 
6707     GLTexture resolveTexture2;
6708     glBindTexture(GL_TEXTURE_2D_ARRAY, resolveTexture2);
6709     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kWidth * 4, kHeight * 4, 5);
6710 
6711     GLFramebuffer resolveFBO2;
6712     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
6713     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolveTexture2, 2, 3);
6714     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6715 
6716     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6717     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
6718                      essl31_shaders::fs::RedGreenGradient());
6719     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6720     ASSERT_GL_NO_ERROR();
6721 
6722     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
6723     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
6724                       GL_NEAREST);
6725     ASSERT_GL_NO_ERROR();
6726 
6727     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
6728     ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Passthrough(), essl31_shaders::fs::Red());
6729     drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6730 
6731     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
6732     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
6733                       GL_NEAREST);
6734     ASSERT_GL_NO_ERROR();
6735 
6736     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
6737     constexpr uint8_t kWidthHalfPixelGradient  = 256 / kWidth / 2;
6738     constexpr uint8_t kHeightHalfPixelGradient = 256 / kHeight / 2;
6739     EXPECT_PIXEL_NEAR(0, 0, kWidthHalfPixelGradient, kHeightHalfPixelGradient, 0, 255, 1.0);
6740     EXPECT_PIXEL_NEAR(kWidth - 1, 0, 255 - kWidthHalfPixelGradient, kHeightHalfPixelGradient, 0,
6741                       255, 1.0);
6742     EXPECT_PIXEL_NEAR(0, kHeight - 1, kWidthHalfPixelGradient, 255 - kHeightHalfPixelGradient, 0,
6743                       255, 1.0);
6744     EXPECT_PIXEL_NEAR(kWidth - 1, kHeight - 1, 255 - kWidthHalfPixelGradient,
6745                       255 - kHeightHalfPixelGradient, 0, 255, 1.0);
6746 
6747     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
6748     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
6749     ASSERT_GL_NO_ERROR();
6750 }
6751 
6752 // Test resolving the same depth/stencil framebuffer into two different ones with a draw in between
TEST_P(FramebufferTest_ES31,MultisampleDepthStencilResolveMultipleTimesWithDrawInBetween)6753 TEST_P(FramebufferTest_ES31, MultisampleDepthStencilResolveMultipleTimesWithDrawInBetween)
6754 {
6755     enum class DepthStencilResolve
6756     {
6757         Simultaneous,
6758         SeparateAspectsButSameFramebuffer,
6759         SeparateAspectsDifferentFramebuffers,
6760     };
6761 
6762     constexpr int kWidth  = 16;
6763     constexpr int kHeight = 20;
6764     glViewport(0, 0, kWidth, kHeight);
6765 
6766     GLFramebuffer msaaFBO;
6767     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6768 
6769     GLRenderbuffer depthStencil;
6770     glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
6771     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kWidth, kHeight);
6772     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
6773                               depthStencil);
6774     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6775     ASSERT_GL_NO_ERROR();
6776 
6777     // Create two resolve FBOs and textures. Use different texture levels and layers.
6778     GLTexture resolveTexture1;
6779     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
6780     glTexStorage2D(GL_TEXTURE_2D, 4, GL_DEPTH24_STENCIL8, kWidth * 4, kHeight * 4);
6781 
6782     GLFramebuffer resolveFBO1;
6783     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
6784     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
6785                            resolveTexture1, 2);
6786     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6787 
6788     GLTexture resolveTexture2;
6789     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
6790     glTexStorage2D(GL_TEXTURE_2D, 2, GL_DEPTH24_STENCIL8, kWidth * 2, kHeight * 2);
6791 
6792     GLFramebuffer resolveFBO2;
6793     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
6794     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
6795                            resolveTexture2, 1);
6796     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6797 
6798     ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
6799 
6800     auto runTest = [&](float depth1, int stencil1, float depth2, int stencil2,
6801                        DepthStencilResolve resolve) {
6802         glEnable(GL_DEPTH_TEST);
6803         glDepthFunc(GL_ALWAYS);
6804         glDepthMask(GL_TRUE);
6805         glEnable(GL_STENCIL_TEST);
6806         glStencilFunc(GL_ALWAYS, stencil1, 0xFF);
6807         glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
6808         glStencilMask(0xFF);
6809 
6810         // Initialize the depth/stencil image
6811         glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6812         drawQuad(red, essl1_shaders::PositionAttrib(), depth1);
6813         ASSERT_GL_NO_ERROR();
6814 
6815         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
6816         switch (resolve)
6817         {
6818             case DepthStencilResolve::Simultaneous:
6819                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6820                                   GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6821                 break;
6822             case DepthStencilResolve::SeparateAspectsButSameFramebuffer:
6823                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
6824                                   GL_NEAREST);
6825                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6826                                   GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6827                 break;
6828             case DepthStencilResolve::SeparateAspectsDifferentFramebuffers:
6829                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
6830                                   GL_NEAREST);
6831                 break;
6832         }
6833 
6834         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
6835         glStencilFunc(GL_ALWAYS, stencil2, 0xFF);
6836         drawQuad(red, essl1_shaders::PositionAttrib(), depth2);
6837 
6838         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
6839         switch (resolve)
6840         {
6841             case DepthStencilResolve::Simultaneous:
6842                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6843                                   GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6844                 break;
6845             case DepthStencilResolve::SeparateAspectsButSameFramebuffer:
6846                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
6847                                   GL_NEAREST);
6848                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6849                                   GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6850                 break;
6851             case DepthStencilResolve::SeparateAspectsDifferentFramebuffers:
6852                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
6853                                   GL_STENCIL_BUFFER_BIT, GL_NEAREST);
6854                 break;
6855         }
6856         ASSERT_GL_NO_ERROR();
6857 
6858         verifyDepth(resolveFBO1, kWidth, kHeight, depth1);
6859         if (resolve != DepthStencilResolve::SeparateAspectsDifferentFramebuffers)
6860         {
6861             verifyStencil(resolveFBO1, kWidth, kHeight, stencil1);
6862             verifyDepth(resolveFBO2, kWidth, kHeight, depth2);
6863         }
6864         verifyStencil(resolveFBO2, kWidth, kHeight, stencil2);
6865     };
6866 
6867     runTest(0.4f, 0x3F, 0.1f, 0xA2, DepthStencilResolve::Simultaneous);
6868     runTest(0.9f, 0x2B, 0.3f, 0xDD, DepthStencilResolve::SeparateAspectsButSameFramebuffer);
6869     runTest(0.5f, 0x6C, 0.6f, 0x7E, DepthStencilResolve::SeparateAspectsDifferentFramebuffers);
6870     ASSERT_GL_NO_ERROR();
6871 }
6872 
6873 // Test resolving different attachments of an FBO to separate FBOs
TEST_P(FramebufferTest_ES31,MultisampleResolveBothAttachments)6874 TEST_P(FramebufferTest_ES31, MultisampleResolveBothAttachments)
6875 {
6876     enum class Invalidate
6877     {
6878         None,
6879         AfterEachResolve,
6880         AllAtEnd,
6881     };
6882 
6883     constexpr char kFS[] = R"(#version 300 es
6884 precision highp float;
6885 
6886 uniform vec4 value0;
6887 uniform vec4 value2;
6888 
6889 layout(location = 0) out vec4 color0;
6890 layout(location = 2) out vec4 color2;
6891 
6892 void main()
6893 {
6894     color0 = value0;
6895     color2 = value2;
6896 })";
6897 
6898     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6899     glUseProgram(program);
6900     const GLint color0Loc = glGetUniformLocation(program, "value0");
6901     const GLint color1Loc = glGetUniformLocation(program, "value2");
6902 
6903     constexpr int kWidth  = 16;
6904     constexpr int kHeight = 20;
6905     glViewport(0, 0, kWidth, kHeight);
6906 
6907     GLTexture msaa0, msaa1;
6908     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa0);
6909     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
6910     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa1);
6911     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
6912 
6913     GLFramebuffer msaaFBO;
6914     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6915     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa0,
6916                            0);
6917     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D_MULTISAMPLE, msaa1,
6918                            0);
6919     ASSERT_GL_NO_ERROR();
6920     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6921 
6922     GLenum bufs[3] = {GL_COLOR_ATTACHMENT0, GL_NONE, GL_COLOR_ATTACHMENT2};
6923     glDrawBuffers(3, bufs);
6924 
6925     // Create two resolve FBOs and textures. Use different texture levels and layers.
6926     GLTexture resolveTexture1;
6927     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
6928     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kWidth * 2, kHeight * 2);
6929 
6930     GLFramebuffer resolveFBO1;
6931     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
6932     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 1);
6933     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6934 
6935     GLTexture resolveTexture2;
6936     glBindTexture(GL_TEXTURE_2D_ARRAY, resolveTexture2);
6937     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RGBA8, kWidth * 4, kHeight * 4, 5);
6938 
6939     GLFramebuffer resolveFBO2;
6940     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
6941     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolveTexture2, 2, 3);
6942     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6943 
6944     auto test = [&](GLColor color0, GLColor color1, Invalidate invalidate) {
6945         const GLenum discards[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT2};
6946 
6947         glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
6948         glUniform4fv(color0Loc, 1, color0.toNormalizedVector().data());
6949         glUniform4fv(color1Loc, 1, color1.toNormalizedVector().data());
6950         drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6951         ASSERT_GL_NO_ERROR();
6952 
6953         // Resolve the first attachment
6954         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
6955         glReadBuffer(GL_COLOR_ATTACHMENT0);
6956         glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
6957                           GL_NEAREST);
6958         ASSERT_GL_NO_ERROR();
6959 
6960         if (invalidate == Invalidate::AfterEachResolve)
6961         {
6962             glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, discards);
6963         }
6964 
6965         // Resolve the second attachment
6966         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
6967         glReadBuffer(GL_COLOR_ATTACHMENT2);
6968         glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
6969                           GL_NEAREST);
6970         ASSERT_GL_NO_ERROR();
6971 
6972         if (invalidate == Invalidate::AfterEachResolve)
6973         {
6974             glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, discards + 1);
6975         }
6976         else if (invalidate == Invalidate::AllAtEnd)
6977         {
6978             glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 2, discards);
6979         }
6980 
6981         glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
6982         EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, color0);
6983         glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
6984         EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, color1);
6985         ASSERT_GL_NO_ERROR();
6986     };
6987 
6988     test(GLColor::red, GLColor::green, Invalidate::None);
6989     test(GLColor::blue, GLColor::yellow, Invalidate::AfterEachResolve);
6990     test(GLColor::cyan, GLColor::magenta, Invalidate::AllAtEnd);
6991 }
6992 
6993 // Test resolving a framebuffer once, then drawing to it again without a resolve.  Makes sure there
6994 // is no caching bug that would make the second render pass resolve into the old resolve target
6995 // again.
TEST_P(FramebufferTest_ES31,ResolveThenDrawWithoutResolve)6996 TEST_P(FramebufferTest_ES31, ResolveThenDrawWithoutResolve)
6997 {
6998     enum class Invalidate
6999     {
7000         None,
7001         AfterFirstResolve,
7002         AfterEachResolve,
7003         AtEnd,
7004     };
7005 
7006     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
7007     glUseProgram(program);
7008     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
7009     ASSERT_NE(colorLoc, -1);
7010 
7011     constexpr int kWidth  = 16;
7012     constexpr int kHeight = 20;
7013     glViewport(0, 0, kWidth, kHeight);
7014 
7015     GLTexture msaa;
7016     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa);
7017     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7018 
7019     GLFramebuffer msaaFBO;
7020     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7021     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa,
7022                            0);
7023     ASSERT_GL_NO_ERROR();
7024     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7025 
7026     // Create the resolve FBO and texture.
7027     GLTexture resolveTexture;
7028     glBindTexture(GL_TEXTURE_2D, resolveTexture);
7029     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kWidth * 2 + 1, kHeight * 2 + 1);
7030 
7031     GLFramebuffer resolveFBO;
7032     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
7033     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
7034     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7035 
7036     auto test = [&](GLColor color1, GLColor color2, Invalidate invalidate) {
7037         const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
7038 
7039         glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7040         glUniform4fv(colorLoc, 1, color1.toNormalizedVector().data());
7041         drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7042         ASSERT_GL_NO_ERROR();
7043 
7044         // Resolve
7045         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7046         glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7047                           GL_NEAREST);
7048         ASSERT_GL_NO_ERROR();
7049 
7050         if (invalidate == Invalidate::AfterEachResolve ||
7051             invalidate == Invalidate::AfterFirstResolve)
7052         {
7053             glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, discards);
7054         }
7055 
7056         // Draw again, but don't resolve.
7057         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
7058         glUniform4fv(colorLoc, 1, color2.toNormalizedVector().data());
7059         drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7060 
7061         const bool invalidateAtEnd =
7062             invalidate == Invalidate::AfterEachResolve || invalidate == Invalidate::AtEnd;
7063         if (invalidateAtEnd)
7064         {
7065             glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, discards);
7066         }
7067 
7068         // Make sure the render pass is flushed so if there's a caching bug and the old render pass
7069         // with resolve is used for the second render pass, the contents of the resolve attachment
7070         // is wrong.  Can't rely on glReadPixels doing that because of potential use of
7071         // VK_EXT_host_image_copy.
7072         glFinish();
7073 
7074         // Verify the contents of the resolve attachment
7075         glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
7076         EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, color1);
7077 
7078         if (!invalidateAtEnd)
7079         {
7080             // For completeness, make sure the second draw succeeded.
7081             glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
7082             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7083             glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7084                               GL_NEAREST);
7085             ASSERT_GL_NO_ERROR();
7086 
7087             glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
7088             EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, color2);
7089         }
7090         ASSERT_GL_NO_ERROR();
7091     };
7092 
7093     test(GLColor::red, GLColor::green, Invalidate::None);
7094     test(GLColor::blue, GLColor::yellow, Invalidate::AfterFirstResolve);
7095     test(GLColor::cyan, GLColor::magenta, Invalidate::AfterEachResolve);
7096     test(GLColor::white, GLColor::red, Invalidate::AtEnd);
7097 }
7098 
7099 // Test resolving a depth/stencil framebuffer once, then drawing to it again without a resolve.
7100 // Makes sure there is no caching bug that would make the second render pass resolve into the old
7101 // resolve target again.
TEST_P(FramebufferTest_ES31,DepthStencilResolveThenDrawWithoutResolve)7102 TEST_P(FramebufferTest_ES31, DepthStencilResolveThenDrawWithoutResolve)
7103 {
7104     enum class Invalidate
7105     {
7106         None,
7107         AfterFirstResolve,
7108         AfterEachResolve,
7109         AtEnd,
7110     };
7111     enum class DepthStencilResolve
7112     {
7113         Simultaneous,
7114         SeparateAspects,
7115     };
7116 
7117     ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
7118 
7119     constexpr int kWidth  = 16;
7120     constexpr int kHeight = 20;
7121     glViewport(0, 0, kWidth, kHeight);
7122 
7123     GLFramebuffer msaaFBO;
7124     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7125 
7126     GLRenderbuffer depthStencil;
7127     glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
7128     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kWidth, kHeight);
7129     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7130                               depthStencil);
7131     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7132     ASSERT_GL_NO_ERROR();
7133 
7134     // Create the resolve FBO and texture. Use different texture levels and layers.
7135     GLTexture resolveTexture;
7136     glBindTexture(GL_TEXTURE_2D, resolveTexture);
7137     glTexStorage2D(GL_TEXTURE_2D, 4, GL_DEPTH24_STENCIL8, kWidth * 4, kHeight * 4);
7138 
7139     GLFramebuffer resolveFBO;
7140     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
7141     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
7142                            resolveTexture, 2);
7143     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7144 
7145     auto test = [&](float depth1, int stencil1, float depth2, int stencil2,
7146                     DepthStencilResolve resolve, Invalidate invalidate) {
7147         const GLenum discards[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT,
7148                                    GL_DEPTH_STENCIL_ATTACHMENT};
7149 
7150         glEnable(GL_DEPTH_TEST);
7151         glDepthFunc(GL_ALWAYS);
7152         glDepthMask(GL_TRUE);
7153         glEnable(GL_STENCIL_TEST);
7154         glStencilFunc(GL_ALWAYS, stencil1, 0xFF);
7155         glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
7156         glStencilMask(0xFF);
7157 
7158         // First draw
7159         glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7160         drawQuad(red, essl1_shaders::PositionAttrib(), depth1);
7161         ASSERT_GL_NO_ERROR();
7162 
7163         // Resolve
7164         const bool invalidateAfterFirstResolve = invalidate == Invalidate::AfterEachResolve ||
7165                                                  invalidate == Invalidate::AfterFirstResolve;
7166         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7167         switch (resolve)
7168         {
7169             case DepthStencilResolve::Simultaneous:
7170                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7171                                   GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7172                 if (invalidateAfterFirstResolve)
7173                 {
7174                     glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, &discards[2]);
7175                 }
7176                 break;
7177             case DepthStencilResolve::SeparateAspects:
7178                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
7179                                   GL_NEAREST);
7180                 if (invalidateAfterFirstResolve)
7181                 {
7182                     glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, &discards[0]);
7183                 }
7184                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7185                                   GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7186                 if (invalidateAfterFirstResolve)
7187                 {
7188                     glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, &discards[1]);
7189                 }
7190                 break;
7191         }
7192         ASSERT_GL_NO_ERROR();
7193 
7194         // Draw again, but don't resolve.
7195         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
7196         glStencilFunc(GL_ALWAYS, stencil2, 0xFF);
7197         drawQuad(red, essl1_shaders::PositionAttrib(), depth2);
7198 
7199         const bool invalidateAtEnd =
7200             invalidate == Invalidate::AfterEachResolve || invalidate == Invalidate::AtEnd;
7201         if (invalidateAtEnd)
7202         {
7203             glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, 1, &discards[2]);
7204         }
7205 
7206         // Make sure the render pass is flushed so if there's a caching bug and the old render pass
7207         // with resolve is used for the second render pass, the contents of the resolve attachment
7208         // is wrong.  Can't rely on glReadPixels doing that because of potential use of
7209         // VK_EXT_host_image_copy.
7210         glFinish();
7211 
7212         // Verify the contents of the resolve attachment
7213         verifyDepth(resolveFBO, kWidth, kHeight, depth1);
7214         verifyStencil(resolveFBO, kWidth, kHeight, stencil1);
7215 
7216         if (!invalidateAtEnd)
7217         {
7218             // For completeness, make sure the second draw succeeded.
7219             glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
7220             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7221             glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7222                               GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7223             ASSERT_GL_NO_ERROR();
7224 
7225             verifyDepth(resolveFBO, kWidth, kHeight, depth2);
7226             verifyStencil(resolveFBO, kWidth, kHeight, stencil2);
7227         }
7228         ASSERT_GL_NO_ERROR();
7229     };
7230 
7231     test(0.4f, 0x3F, 0.1f, 0xA2, DepthStencilResolve::Simultaneous, Invalidate::None);
7232     test(0.9f, 0x2B, 0.3f, 0xDD, DepthStencilResolve::Simultaneous, Invalidate::AfterFirstResolve);
7233     test(0.5f, 0x6C, 0.6f, 0x7E, DepthStencilResolve::Simultaneous, Invalidate::AfterEachResolve);
7234     test(0.1f, 0x78, 0.4f, 0x34, DepthStencilResolve::Simultaneous, Invalidate::AtEnd);
7235     test(0.6f, 0x7E, 0.5f, 0x6C, DepthStencilResolve::SeparateAspects, Invalidate::None);
7236     test(0.1f, 0xA2, 0.9f, 0x2B, DepthStencilResolve::SeparateAspects,
7237          Invalidate::AfterFirstResolve);
7238     test(0.4f, 0x3F, 0.3f, 0xDD, DepthStencilResolve::SeparateAspects,
7239          Invalidate::AfterEachResolve);
7240     test(0.9f, 0xF0, 0.7f, 0x8A, DepthStencilResolve::SeparateAspects, Invalidate::AtEnd);
7241 }
7242 
7243 // Test resolving a framebuffer once, then drawing to it again without a complete resolve, and then
7244 // drawing again with a resolve to same or another framebuffer.
TEST_P(FramebufferTest_ES31,ResolveThenDrawWithoutResolveThenDrawWithResolve)7245 TEST_P(FramebufferTest_ES31, ResolveThenDrawWithoutResolveThenDrawWithResolve)
7246 {
7247     enum class SecondResolve
7248     {
7249         SameFramebuffer,
7250         AnotherFramebuffer,
7251     };
7252 
7253     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
7254     glUseProgram(program);
7255     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
7256     ASSERT_NE(colorLoc, -1);
7257 
7258     constexpr int kWidth  = 36;
7259     constexpr int kHeight = 12;
7260     glViewport(0, 0, kWidth, kHeight);
7261 
7262     GLTexture msaa;
7263     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa);
7264     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7265 
7266     GLFramebuffer msaaFBO;
7267     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7268     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa,
7269                            0);
7270     ASSERT_GL_NO_ERROR();
7271     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7272 
7273     // Create two resolve FBOs and textures. Use different texture levels and layers.
7274     GLTexture resolveTexture1;
7275     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
7276     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kWidth * 4, kHeight * 4);
7277 
7278     GLFramebuffer resolveFBO1;
7279     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
7280     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 2);
7281     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7282 
7283     GLTexture resolveTexture2;
7284     glBindTexture(GL_TEXTURE_2D_ARRAY, resolveTexture2);
7285     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kWidth, kHeight, 5);
7286 
7287     GLFramebuffer resolveFBO2;
7288     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
7289     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolveTexture2, 0, 4);
7290     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7291 
7292     auto test = [&](GLColor color1, GLColor color2, GLColor color3, SecondResolve secondResolve) {
7293         glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7294         glUniform4fv(colorLoc, 1, color1.toNormalizedVector().data());
7295         drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7296         ASSERT_GL_NO_ERROR();
7297 
7298         // Resolve
7299         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
7300         glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7301                           GL_NEAREST);
7302         ASSERT_GL_NO_ERROR();
7303 
7304         // Draw again, but don't resolve.
7305         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
7306         glUniform4fv(colorLoc, 1, color2.toNormalizedVector().data());
7307         drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7308 
7309         // Make sure the render pass is flushed.
7310         glFinish();
7311 
7312         // Verify the contents of the resolve attachment
7313         glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
7314         EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, color1);
7315 
7316         // Draw and resolve again
7317         glEnable(GL_BLEND);
7318         glBlendFunc(GL_ONE, GL_ONE);
7319         glUniform4fv(colorLoc, 1, color3.toNormalizedVector().data());
7320         drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7321         glDisable(GL_BLEND);
7322 
7323         GLint fboToResolve =
7324             secondResolve == SecondResolve::SameFramebuffer ? resolveFBO1 : resolveFBO2;
7325         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboToResolve);
7326         glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
7327         glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7328                           GL_NEAREST);
7329 
7330         const GLColor blendedColor = GLColor(
7331             std::clamp(color2.R + color3.R, 0, 255), std::clamp(color2.G + color3.G, 0, 255),
7332             std::clamp(color2.B + color3.B, 0, 255), std::clamp(color2.A + color3.A, 0, 255));
7333         glBindFramebuffer(GL_READ_FRAMEBUFFER, fboToResolve);
7334         EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, blendedColor);
7335     };
7336 
7337     test(GLColor::red, GLColor::green, GLColor::blue, SecondResolve::SameFramebuffer);
7338     test(GLColor::cyan, GLColor(180, 0, 0, 190), GLColor(100, 255, 0, 80),
7339          SecondResolve::AnotherFramebuffer);
7340 }
7341 
7342 // Test resolving a depth/stencil framebuffer once, then drawing to it again without a complete
7343 // resolve, and then drawing again with a resolve to same or another framebuffer.
TEST_P(FramebufferTest_ES31,DepthStencilResolveThenDrawWithoutResolveThenDrawWithResolve)7344 TEST_P(FramebufferTest_ES31, DepthStencilResolveThenDrawWithoutResolveThenDrawWithResolve)
7345 {
7346     enum class SecondResolve
7347     {
7348         SameFramebuffer,
7349         AnotherFramebuffer,
7350     };
7351     enum class DepthStencilResolve
7352     {
7353         Simultaneous,
7354         SeparateAspectsButSameFramebuffer,
7355         SeparateAspectsDifferentFramebuffers,
7356     };
7357 
7358     constexpr int kWidth  = 24;
7359     constexpr int kHeight = 12;
7360     glViewport(0, 0, kWidth, kHeight);
7361 
7362     GLFramebuffer msaaFBO;
7363     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7364 
7365     GLRenderbuffer depthStencil;
7366     glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
7367     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kWidth, kHeight);
7368     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7369                               depthStencil);
7370     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7371     ASSERT_GL_NO_ERROR();
7372 
7373     // Create two resolve FBOs and textures. Use different texture levels and layers.
7374     GLTexture resolveTexture1;
7375     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
7376     glTexStorage2D(GL_TEXTURE_2D, 4, GL_DEPTH24_STENCIL8, kWidth * 4, kHeight * 4);
7377 
7378     GLFramebuffer resolveFBO1;
7379     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
7380     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
7381                            resolveTexture1, 2);
7382     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7383 
7384     GLTexture resolveTexture2;
7385     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
7386     glTexStorage2D(GL_TEXTURE_2D, 2, GL_DEPTH24_STENCIL8, kWidth * 2, kHeight * 2);
7387 
7388     GLFramebuffer resolveFBO2;
7389     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
7390     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
7391                            resolveTexture2, 1);
7392     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7393 
7394     ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
7395 
7396     auto runTest = [&](float depth1, int stencil1, float depth2, int stencil2,
7397                        DepthStencilResolve resolve, SecondResolve secondResolve) {
7398         glEnable(GL_DEPTH_TEST);
7399         glDepthFunc(GL_ALWAYS);
7400         glDepthMask(GL_TRUE);
7401         glEnable(GL_STENCIL_TEST);
7402         glStencilFunc(GL_ALWAYS, stencil1, 0xFF);
7403         glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
7404         glStencilMask(0xFF);
7405 
7406         // Initialize the depth/stencil image
7407         glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7408         drawQuad(red, essl1_shaders::PositionAttrib(), depth1);
7409         ASSERT_GL_NO_ERROR();
7410 
7411         // Resolve depth and stencil, then verify the results
7412         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
7413         switch (resolve)
7414         {
7415             case DepthStencilResolve::Simultaneous:
7416                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7417                                   GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7418                 break;
7419             case DepthStencilResolve::SeparateAspectsButSameFramebuffer:
7420                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
7421                                   GL_NEAREST);
7422                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7423                                   GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7424                 break;
7425             case DepthStencilResolve::SeparateAspectsDifferentFramebuffers:
7426                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
7427                                   GL_NEAREST);
7428                 break;
7429         }
7430 
7431         // Draw again, but don't resolve.
7432         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
7433         drawQuad(red, essl31_shaders::PositionAttrib(), 0);
7434 
7435         // Make sure the render pass is flushed.
7436         glFinish();
7437 
7438         // Draw and resolve again
7439         glStencilFunc(GL_ALWAYS, stencil2, 0xFF);
7440         drawQuad(red, essl31_shaders::PositionAttrib(), depth2);
7441 
7442         GLint fboToResolve =
7443             secondResolve == SecondResolve::SameFramebuffer ? resolveFBO1 : resolveFBO2;
7444         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboToResolve);
7445         switch (resolve)
7446         {
7447             case DepthStencilResolve::Simultaneous:
7448                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7449                                   GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7450                 break;
7451             case DepthStencilResolve::SeparateAspectsButSameFramebuffer:
7452                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
7453                                   GL_NEAREST);
7454                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7455                                   GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7456                 break;
7457             case DepthStencilResolve::SeparateAspectsDifferentFramebuffers:
7458                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7459                                   GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7460                 break;
7461         }
7462         ASSERT_GL_NO_ERROR();
7463 
7464         if (secondResolve == SecondResolve::SameFramebuffer)
7465         {
7466             verifyDepth(resolveFBO1, kWidth, kHeight,
7467                         resolve == DepthStencilResolve::SeparateAspectsDifferentFramebuffers
7468                             ? depth1
7469                             : depth2);
7470             verifyStencil(resolveFBO1, kWidth, kHeight, stencil2);
7471         }
7472         else
7473         {
7474             verifyDepth(resolveFBO1, kWidth, kHeight, depth1);
7475             if (resolve != DepthStencilResolve::SeparateAspectsDifferentFramebuffers)
7476             {
7477                 verifyStencil(resolveFBO1, kWidth, kHeight, stencil1);
7478                 verifyDepth(resolveFBO2, kWidth, kHeight, depth2);
7479             }
7480             verifyStencil(resolveFBO2, kWidth, kHeight, stencil2);
7481         }
7482     };
7483 
7484     runTest(0.4f, 0x3F, 0.1f, 0xA2, DepthStencilResolve::Simultaneous,
7485             SecondResolve::SameFramebuffer);
7486     runTest(0.9f, 0x2B, 0.3f, 0xDD, DepthStencilResolve::Simultaneous,
7487             SecondResolve::AnotherFramebuffer);
7488     runTest(0.6f, 0x7E, 0.6f, 0x7E, DepthStencilResolve::SeparateAspectsButSameFramebuffer,
7489             SecondResolve::SameFramebuffer);
7490     runTest(0.1f, 0xA2, 0.4f, 0x34, DepthStencilResolve::SeparateAspectsButSameFramebuffer,
7491             SecondResolve::AnotherFramebuffer);
7492     runTest(0.4f, 0x3F, 0.5f, 0x6C, DepthStencilResolve::SeparateAspectsDifferentFramebuffers,
7493             SecondResolve::SameFramebuffer);
7494     runTest(0.9f, 0xF0, 0.9f, 0x2B, DepthStencilResolve::SeparateAspectsDifferentFramebuffers,
7495             SecondResolve::AnotherFramebuffer);
7496     ASSERT_GL_NO_ERROR();
7497 }
7498 
7499 // Test resolving a framebuffer once, then changing its attachment (with the same format) and
7500 // draw+resolving again.  Makes sure the wrong framebuffer or render pass is not picked from a
7501 // cache.
TEST_P(FramebufferTest_ES31,ResolveThenChangeAttachmentThenResolveAgain)7502 TEST_P(FramebufferTest_ES31, ResolveThenChangeAttachmentThenResolveAgain)
7503 {
7504     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
7505     glUseProgram(program);
7506     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
7507     ASSERT_NE(colorLoc, -1);
7508 
7509     constexpr int kWidth  = 36;
7510     constexpr int kHeight = 20;
7511     glViewport(0, 0, kWidth, kHeight);
7512 
7513     GLTexture msaa0, msaa1;
7514     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa0);
7515     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7516     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa1);
7517     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7518 
7519     GLFramebuffer msaaFBO;
7520     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7521     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa0,
7522                            0);
7523     ASSERT_GL_NO_ERROR();
7524     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7525 
7526     // Create the resolve FBO and texture.
7527     GLTexture resolveTexture;
7528     glBindTexture(GL_TEXTURE_2D, resolveTexture);
7529     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kWidth * 2 + 1, kHeight * 2 + 1);
7530 
7531     GLFramebuffer resolveFBO;
7532     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
7533     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
7534     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7535 
7536     // Draw and resolve once
7537     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7538     glUniform4fv(colorLoc, 1, GLColor::green.toNormalizedVector().data());
7539     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7540     ASSERT_GL_NO_ERROR();
7541 
7542     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7543     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7544                       GL_NEAREST);
7545     ASSERT_GL_NO_ERROR();
7546 
7547     // Change the framebuffer attachment to another texture
7548     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7549     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa1,
7550                            0);
7551     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7552 
7553     // Draw and resolve again
7554     glUniform4fv(colorLoc, 1, GLColor::blue.toNormalizedVector().data());
7555     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7556     ASSERT_GL_NO_ERROR();
7557 
7558     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7559     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7560                       GL_NEAREST);
7561     ASSERT_GL_NO_ERROR();
7562 
7563     // Verify results
7564     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
7565     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue);
7566     ASSERT_GL_NO_ERROR();
7567 }
7568 
7569 // Test resolving a depth/stencil framebuffer once, then changing its attachment (with the same
7570 // format) and draw+resolving again.  Makes sure the wrong framebuffer or render pass is not picked
7571 // from a cache.
TEST_P(FramebufferTest_ES31,DepthStencilResolveThenChangeAttachmentThenResolveAgain)7572 TEST_P(FramebufferTest_ES31, DepthStencilResolveThenChangeAttachmentThenResolveAgain)
7573 {
7574     enum class DepthStencilResolve
7575     {
7576         Simultaneous,
7577         SeparateAspects,
7578     };
7579 
7580     constexpr int kWidth  = 24;
7581     constexpr int kHeight = 12;
7582     glViewport(0, 0, kWidth, kHeight);
7583 
7584     GLFramebuffer msaaFBO;
7585     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7586 
7587     GLRenderbuffer depthStencil, depth, stencil;
7588     glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
7589     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, kWidth, kHeight);
7590 
7591     glBindRenderbuffer(GL_RENDERBUFFER, depth);
7592     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, kWidth, kHeight);
7593     glBindRenderbuffer(GL_RENDERBUFFER, stencil);
7594     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_STENCIL_INDEX8, kWidth, kHeight);
7595 
7596     // Create two resolve FBOs and textures. Use different texture levels and layers.
7597     GLTexture resolveTexture1;
7598     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
7599     glTexStorage2D(GL_TEXTURE_2D, 4, GL_DEPTH24_STENCIL8, kWidth * 4, kHeight * 4);
7600 
7601     GLFramebuffer resolveFBO1;
7602     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
7603     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
7604                            resolveTexture1, 2);
7605     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7606 
7607     GLTexture resolveTexture2;
7608     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
7609     glTexStorage2D(GL_TEXTURE_2D, 2, GL_DEPTH_COMPONENT16, kWidth * 2, kHeight * 2);
7610 
7611     GLFramebuffer resolveFBO2;
7612     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
7613     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, resolveTexture2, 1);
7614     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7615 
7616     GLTexture resolveTexture3;
7617     glBindTexture(GL_TEXTURE_2D, resolveTexture3);
7618     glTexStorage2D(GL_TEXTURE_2D, 2, GL_STENCIL_INDEX8, kWidth * 2, kHeight * 2);
7619 
7620     GLFramebuffer resolveFBO3;
7621     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO3);
7622     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, resolveTexture3,
7623                            1);
7624     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7625 
7626     ANGLE_GL_PROGRAM(red, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
7627 
7628     auto runTest = [&](float depth1, int stencil1, float depth2, int stencil2,
7629                        DepthStencilResolve resolve) {
7630         glEnable(GL_DEPTH_TEST);
7631         glDepthFunc(GL_ALWAYS);
7632         glDepthMask(GL_TRUE);
7633         glEnable(GL_STENCIL_TEST);
7634         glStencilFunc(GL_ALWAYS, stencil1, 0xFF);
7635         glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
7636         glStencilMask(0xFF);
7637 
7638         // Initialize the depth/stencil image
7639         glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7640         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7641                                   depthStencil);
7642         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7643 
7644         drawQuad(red, essl1_shaders::PositionAttrib(), depth1);
7645         ASSERT_GL_NO_ERROR();
7646 
7647         // Resolve depth and stencil
7648         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
7649         switch (resolve)
7650         {
7651             case DepthStencilResolve::Simultaneous:
7652                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7653                                   GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7654                 break;
7655             case DepthStencilResolve::SeparateAspects:
7656                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
7657                                   GL_NEAREST);
7658                 glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
7659                                   GL_STENCIL_BUFFER_BIT, GL_NEAREST);
7660                 break;
7661         }
7662 
7663         // Change the framebuffer and draw/resolve again
7664         glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7665         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
7666         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
7667         drawQuad(red, essl1_shaders::PositionAttrib(), depth2);
7668         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7669 
7670         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
7671         glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_DEPTH_BUFFER_BIT,
7672                           GL_NEAREST);
7673         ASSERT_GL_NO_ERROR();
7674 
7675         glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7676         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
7677         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencil);
7678         glStencilFunc(GL_ALWAYS, stencil2, 0xFF);
7679         drawQuad(red, essl1_shaders::PositionAttrib(), 0);
7680         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7681 
7682         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO3);
7683         glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_STENCIL_BUFFER_BIT,
7684                           GL_NEAREST);
7685         ASSERT_GL_NO_ERROR();
7686 
7687         verifyDepth(resolveFBO1, kWidth, kHeight, depth1);
7688         verifyStencil(resolveFBO1, kWidth, kHeight, stencil1);
7689         verifyDepth(resolveFBO2, kWidth, kHeight, depth2);
7690         verifyStencil(resolveFBO3, kWidth, kHeight, stencil2);
7691     };
7692 
7693     runTest(0.1f, 0x78, 0.4f, 0x34, DepthStencilResolve::Simultaneous);
7694     runTest(0.6f, 0x7E, 0.5f, 0x6C, DepthStencilResolve::SeparateAspects);
7695     ASSERT_GL_NO_ERROR();
7696 }
7697 
7698 // Similar to ResolveThenChangeAttachmentThenResolveAgain, but the attachment format is also changed
TEST_P(FramebufferTest_ES31,ResolveThenChangeAttachmentFormatThenResolveAgain)7699 TEST_P(FramebufferTest_ES31, ResolveThenChangeAttachmentFormatThenResolveAgain)
7700 {
7701     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
7702     glUseProgram(program);
7703     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
7704     ASSERT_NE(colorLoc, -1);
7705 
7706     constexpr int kWidth  = 32;
7707     constexpr int kHeight = 24;
7708     glViewport(0, 0, kWidth, kHeight);
7709 
7710     GLTexture msaa0, msaa1;
7711     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa0);
7712     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7713     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa1);
7714     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB565, kWidth, kHeight, false);
7715 
7716     GLFramebuffer msaaFBO;
7717     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7718     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa0,
7719                            0);
7720     ASSERT_GL_NO_ERROR();
7721     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7722 
7723     // Create two resolve FBOs and textures. Use different texture levels and layers.
7724     GLTexture resolveTexture1;
7725     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
7726     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kWidth * 4, kHeight * 4);
7727 
7728     GLFramebuffer resolveFBO1;
7729     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
7730     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 2);
7731     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7732 
7733     GLTexture resolveTexture2;
7734     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
7735     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGB565, kWidth * 4, kHeight * 4);
7736 
7737     GLFramebuffer resolveFBO2;
7738     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
7739     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 2);
7740     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7741 
7742     // Draw and resolve once
7743     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7744     glUniform4fv(colorLoc, 1, GLColor::blue.toNormalizedVector().data());
7745     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7746     ASSERT_GL_NO_ERROR();
7747 
7748     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
7749     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7750                       GL_NEAREST);
7751     ASSERT_GL_NO_ERROR();
7752 
7753     // Change the framebuffer attachment to another texture with a different format
7754     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7755     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa1,
7756                            0);
7757     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7758 
7759     // Draw and resolve again
7760     glUniform4fv(colorLoc, 1, GLColor::yellow.toNormalizedVector().data());
7761     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7762     ASSERT_GL_NO_ERROR();
7763 
7764     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
7765     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7766                       GL_NEAREST);
7767     ASSERT_GL_NO_ERROR();
7768 
7769     // Verify results
7770     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
7771     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue);
7772     ASSERT_GL_NO_ERROR();
7773 
7774     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
7775     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::yellow);
7776     ASSERT_GL_NO_ERROR();
7777 }
7778 
7779 // Draw and resolve once, use the resolve attachment as a storage image, then draw and resolve
7780 // again.  The storage image usage may recreate the image internally, and this test makes sure the
7781 // wrong framebuffer or render pass is not picked from a cache.
TEST_P(FramebufferTest_ES31,ResolveThenUseAsStorageImageThenResolveAgain)7782 TEST_P(FramebufferTest_ES31, ResolveThenUseAsStorageImageThenResolveAgain)
7783 {
7784     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
7785     glUseProgram(program);
7786     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
7787     ASSERT_NE(colorLoc, -1);
7788 
7789     constexpr int kWidth  = 36;
7790     constexpr int kHeight = 20;
7791     glViewport(0, 0, kWidth, kHeight);
7792 
7793     GLTexture msaa0, msaa1;
7794     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa0);
7795     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7796     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaa1);
7797     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, false);
7798 
7799     GLFramebuffer msaaFBO;
7800     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7801     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msaa0,
7802                            0);
7803     ASSERT_GL_NO_ERROR();
7804     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7805 
7806     // Create the resolve FBO and texture.
7807     GLTexture resolveTexture;
7808     glBindTexture(GL_TEXTURE_2D, resolveTexture);
7809     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kWidth * 2, kHeight * 2);
7810 
7811     GLFramebuffer resolveFBO;
7812     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
7813     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
7814     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7815 
7816     // Draw and resolve once
7817     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7818     glUniform4fv(colorLoc, 1, GLColor::green.toNormalizedVector().data());
7819     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7820     ASSERT_GL_NO_ERROR();
7821 
7822     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7823     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7824                       GL_NEAREST);
7825     ASSERT_GL_NO_ERROR();
7826 
7827     // Use the resolve attachment as a storage image.  A different level is used to be able to
7828     // verify the compute shader results.
7829     constexpr char kCS[] = R"(#version 310 es
7830 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
7831 layout(rgba8, binding = 0) writeonly uniform highp image2D image;
7832 void main()
7833 {
7834     imageStore(image, ivec2(gl_GlobalInvocationID.xy), vec4(1, 1, 0, 1));
7835 })";
7836 
7837     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCS);
7838     glUseProgram(csProgram);
7839     glBindImageTexture(0, resolveTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
7840     glDispatchCompute(kWidth * 2, kHeight * 2, 1);
7841 
7842     // Draw and resolve again
7843     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
7844     glUseProgram(program);
7845     glUniform4fv(colorLoc, 1, GLColor::blue.toNormalizedVector().data());
7846     glEnable(GL_BLEND);
7847     glBlendFunc(GL_ONE, GL_ONE);
7848     drawQuad(program, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
7849     ASSERT_GL_NO_ERROR();
7850 
7851     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
7852     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
7853                       GL_NEAREST);
7854     ASSERT_GL_NO_ERROR();
7855 
7856     // Verify resolve results
7857     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
7858     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::cyan);
7859 
7860     // For completeness, verify compute shader write results
7861     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
7862 
7863     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture,
7864                            0);
7865     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
7866     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth * 2, kHeight * 2, GLColor::yellow);
7867     ASSERT_GL_NO_ERROR();
7868 }
7869 ANGLE_INSTANTIATE_TEST_ES2_AND(AddMockTextureNoRenderTargetTest,
7870                                ES2_D3D9().enable(Feature::AddMockTextureNoRenderTarget),
7871                                ES2_D3D11().enable(Feature::AddMockTextureNoRenderTarget));
7872 
7873 ANGLE_INSTANTIATE_TEST_ES2(FramebufferTest);
7874 ANGLE_INSTANTIATE_TEST_ES2(FramebufferExtensionsTest);
7875 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
7876 
7877 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES3);
7878 ANGLE_INSTANTIATE_TEST_ES3_AND(FramebufferTest_ES3,
7879                                ES3_VULKAN().enable(Feature::EmulatedPrerotation90),
7880                                ES3_VULKAN().enable(Feature::EmulatedPrerotation180),
7881                                ES3_VULKAN().enable(Feature::EmulatedPrerotation270));
7882 
7883 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES3Metal);
7884 ANGLE_INSTANTIATE_TEST(FramebufferTest_ES3Metal,
7885                        ES3_METAL().enable(Feature::LimitMaxColorTargetBitsForTesting));
7886 
7887 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES31);
7888 ANGLE_INSTANTIATE_TEST_ES31_AND(FramebufferTest_ES31,
7889                                 ES31_VULKAN().disable(Feature::SupportsImagelessFramebuffer));
7890 ANGLE_INSTANTIATE_TEST_ES3(FramebufferTestWithFormatFallback);
7891 ANGLE_INSTANTIATE_TEST_ES3(DefaultFramebufferTest);
7892