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