• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // Framebuffer tests:
7 //   Various tests related for Frambuffers.
8 //
9 
10 #include "common/mathutil.h"
11 #include "platform/FeaturesD3D.h"
12 #include "test_utils/ANGLETest.h"
13 #include "test_utils/gl_raii.h"
14 
15 using namespace angle;
16 
17 namespace
18 {
19 
ExpectFramebufferCompleteOrUnsupported(GLenum binding)20 void ExpectFramebufferCompleteOrUnsupported(GLenum binding)
21 {
22     GLenum status = glCheckFramebufferStatus(binding);
23     EXPECT_TRUE(status == GL_FRAMEBUFFER_COMPLETE || status == GL_FRAMEBUFFER_UNSUPPORTED);
24 }
25 
26 }  // anonymous namespace
27 
28 class FramebufferFormatsTest : public ANGLETest
29 {
30   protected:
FramebufferFormatsTest()31     FramebufferFormatsTest() : mFramebuffer(0), mTexture(0), mRenderbuffer(0), mProgram(0)
32     {
33         setWindowWidth(128);
34         setWindowHeight(128);
35         setConfigRedBits(8);
36         setConfigGreenBits(8);
37         setConfigBlueBits(8);
38         setConfigAlphaBits(8);
39     }
40 
checkBitCount(GLuint fbo,GLenum channel,GLint minBits)41     void checkBitCount(GLuint fbo, GLenum channel, GLint minBits)
42     {
43         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
44 
45         GLint bits = 0;
46         glGetIntegerv(channel, &bits);
47 
48         if (minBits == 0)
49         {
50             EXPECT_EQ(minBits, bits);
51         }
52         else
53         {
54             EXPECT_GE(bits, minBits);
55         }
56     }
57 
testBitCounts(GLuint fbo,GLint minRedBits,GLint minGreenBits,GLint minBlueBits,GLint minAlphaBits,GLint minDepthBits,GLint minStencilBits)58     void testBitCounts(GLuint fbo,
59                        GLint minRedBits,
60                        GLint minGreenBits,
61                        GLint minBlueBits,
62                        GLint minAlphaBits,
63                        GLint minDepthBits,
64                        GLint minStencilBits)
65     {
66         checkBitCount(fbo, GL_RED_BITS, minRedBits);
67         checkBitCount(fbo, GL_GREEN_BITS, minGreenBits);
68         checkBitCount(fbo, GL_BLUE_BITS, minBlueBits);
69         checkBitCount(fbo, GL_ALPHA_BITS, minAlphaBits);
70         checkBitCount(fbo, GL_DEPTH_BITS, minDepthBits);
71         checkBitCount(fbo, GL_STENCIL_BITS, minStencilBits);
72     }
73 
testTextureFormat(GLenum internalFormat,GLint minRedBits,GLint minGreenBits,GLint minBlueBits,GLint minAlphaBits)74     void testTextureFormat(GLenum internalFormat,
75                            GLint minRedBits,
76                            GLint minGreenBits,
77                            GLint minBlueBits,
78                            GLint minAlphaBits)
79     {
80         glGenTextures(1, &mTexture);
81         glBindTexture(GL_TEXTURE_2D, mTexture);
82 
83         if (getClientMajorVersion() >= 3)
84         {
85             glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
86         }
87         else
88         {
89             glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
90         }
91 
92         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
93 
94         testBitCounts(mFramebuffer, minRedBits, minGreenBits, minBlueBits, minAlphaBits, 0, 0);
95     }
96 
testRenderbufferMultisampleFormat(int minESVersion,GLenum attachmentType,GLenum internalFormat)97     void testRenderbufferMultisampleFormat(int minESVersion,
98                                            GLenum attachmentType,
99                                            GLenum internalFormat)
100     {
101         int clientVersion = getClientMajorVersion();
102         if (clientVersion < minESVersion)
103         {
104             return;
105         }
106 
107         // Check that multisample is supported with at least two samples (minimum required is 1)
108         bool supports2Samples = false;
109 
110         if (clientVersion == 2)
111         {
112             if (IsGLExtensionEnabled("ANGLE_framebuffer_multisample"))
113             {
114                 int maxSamples;
115                 glGetIntegerv(GL_MAX_SAMPLES_ANGLE, &maxSamples);
116                 supports2Samples = maxSamples >= 2;
117             }
118         }
119         else
120         {
121             assert(clientVersion >= 3);
122             int maxSamples;
123             glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
124             supports2Samples = maxSamples >= 2;
125         }
126 
127         if (!supports2Samples)
128         {
129             return;
130         }
131 
132         glGenRenderbuffers(1, &mRenderbuffer);
133         glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
134 
135         EXPECT_GL_NO_ERROR();
136         glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, internalFormat, 128, 128);
137         EXPECT_GL_NO_ERROR();
138         glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentType, GL_RENDERBUFFER, mRenderbuffer);
139         EXPECT_GL_NO_ERROR();
140     }
141 
testZeroHeightRenderbuffer()142     void testZeroHeightRenderbuffer()
143     {
144         glGenRenderbuffers(1, &mRenderbuffer);
145         glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
146         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 0);
147         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
148                                   mRenderbuffer);
149         EXPECT_GL_NO_ERROR();
150     }
151 
testSetUp()152     void testSetUp() override
153     {
154         glGenFramebuffers(1, &mFramebuffer);
155         glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
156     }
157 
testTearDown()158     void testTearDown() override
159     {
160         if (mTexture != 0)
161         {
162             glDeleteTextures(1, &mTexture);
163             mTexture = 0;
164         }
165 
166         if (mRenderbuffer != 0)
167         {
168             glDeleteRenderbuffers(1, &mRenderbuffer);
169             mRenderbuffer = 0;
170         }
171 
172         if (mFramebuffer != 0)
173         {
174             glDeleteFramebuffers(1, &mFramebuffer);
175             mFramebuffer = 0;
176         }
177 
178         if (mProgram != 0)
179         {
180             glDeleteProgram(mProgram);
181             mProgram = 0;
182         }
183     }
184 
185     GLuint mFramebuffer;
186     GLuint mTexture;
187     GLuint mRenderbuffer;
188     GLuint mProgram;
189 };
190 
TEST_P(FramebufferFormatsTest,RGBA4)191 TEST_P(FramebufferFormatsTest, RGBA4)
192 {
193     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
194                        !IsGLExtensionEnabled("GL_EXT_texture_storage"));
195 
196     testTextureFormat(GL_RGBA4, 4, 4, 4, 4);
197 }
198 
TEST_P(FramebufferFormatsTest,RGB565)199 TEST_P(FramebufferFormatsTest, RGB565)
200 {
201     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
202                        !IsGLExtensionEnabled("GL_EXT_texture_storage"));
203 
204     testTextureFormat(GL_RGB565, 5, 6, 5, 0);
205 }
206 
TEST_P(FramebufferFormatsTest,RGB8)207 TEST_P(FramebufferFormatsTest, RGB8)
208 {
209     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
210                        (!IsGLExtensionEnabled("GL_OES_rgb8_rgba8") ||
211                         !IsGLExtensionEnabled("GL_EXT_texture_storage")));
212 
213     testTextureFormat(GL_RGB8_OES, 8, 8, 8, 0);
214 }
215 
TEST_P(FramebufferFormatsTest,BGRA8)216 TEST_P(FramebufferFormatsTest, BGRA8)
217 {
218     ANGLE_SKIP_TEST_IF(
219         !IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888") ||
220         (getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_texture_storage")));
221 
222     testTextureFormat(GL_BGRA8_EXT, 8, 8, 8, 8);
223 }
224 
TEST_P(FramebufferFormatsTest,RGBA8)225 TEST_P(FramebufferFormatsTest, RGBA8)
226 {
227     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
228                        (!IsGLExtensionEnabled("GL_OES_rgb8_rgba8") ||
229                         !IsGLExtensionEnabled("GL_EXT_texture_storage")));
230 
231     testTextureFormat(GL_RGBA8_OES, 8, 8, 8, 8);
232 }
233 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH16)234 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH16)
235 {
236     testRenderbufferMultisampleFormat(2, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16);
237 }
238 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH24)239 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24)
240 {
241     testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24);
242 }
243 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH32F)244 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F)
245 {
246     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
247 
248     testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT32F);
249 }
250 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH24_STENCIL8)251 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24_STENCIL8)
252 {
253     testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH24_STENCIL8);
254 }
255 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH32F_STENCIL8)256 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F_STENCIL8)
257 {
258     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
259 
260     testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH32F_STENCIL8);
261 }
262 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_STENCIL_INDEX8)263 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_STENCIL_INDEX8)
264 {
265     // TODO(geofflang): Figure out how to support GLSTENCIL_INDEX8 on desktop GL
266     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
267 
268     testRenderbufferMultisampleFormat(2, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8);
269 }
270 
271 // Test that binding an incomplete cube map is rejected by ANGLE.
TEST_P(FramebufferFormatsTest,IncompleteCubeMap)272 TEST_P(FramebufferFormatsTest, IncompleteCubeMap)
273 {
274     // http://anglebug.com/3145
275     ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
276 
277     // First make a complete CubeMap.
278     glGenTextures(1, &mTexture);
279     glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
280     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
281                  nullptr);
282     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
283                  nullptr);
284     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
285                  nullptr);
286     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
287                  nullptr);
288     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
289                  nullptr);
290     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
291                  nullptr);
292     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
293     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
294 
295     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
296                            mTexture, 0);
297 
298     // Verify the framebuffer is complete.
299     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
300 
301     // Make the CubeMap cube-incomplete.
302     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
303                  nullptr);
304 
305     // Verify the framebuffer is incomplete.
306     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
307                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
308 
309     ASSERT_GL_NO_ERROR();
310 
311     // Verify drawing with the incomplete framebuffer produces a GL error
312     mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
313     ASSERT_NE(0u, mProgram);
314     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
315     ASSERT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
316 }
317 
318 // Test that a renderbuffer with zero height but nonzero width is handled without crashes/asserts.
TEST_P(FramebufferFormatsTest,ZeroHeightRenderbuffer)319 TEST_P(FramebufferFormatsTest, ZeroHeightRenderbuffer)
320 {
321     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
322 
323     testZeroHeightRenderbuffer();
324 }
325 
326 // Test to cover a bug where the read framebuffer affects the completeness of the draw framebuffer.
TEST_P(FramebufferFormatsTest,ReadDrawCompleteness)327 TEST_P(FramebufferFormatsTest, ReadDrawCompleteness)
328 {
329     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
330 
331     GLTexture incompleteTexture;
332     glBindTexture(GL_TEXTURE_2D, incompleteTexture);
333 
334     GLFramebuffer incompleteFBO;
335     glBindFramebuffer(GL_FRAMEBUFFER, incompleteFBO);
336     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, incompleteTexture,
337                            0);
338     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
339                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
340 
341     GLTexture completeTexture;
342     glBindTexture(GL_TEXTURE_2D, completeTexture);
343     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
344 
345     GLFramebuffer completeFBO;
346     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, completeFBO);
347     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
348                            completeTexture, 0);
349 
350     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
351                      glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
352     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
353 
354     ASSERT_GL_NO_ERROR();
355 
356     // Simple draw program.
357     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
358 
359     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
360     EXPECT_GL_NO_ERROR();
361 
362     glBindFramebuffer(GL_READ_FRAMEBUFFER, completeFBO);
363     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
364 }
365 
366 // Test that a renderbuffer with RGB565 format works as expected. This test is intended for some
367 // back-end having no support for native RGB565 renderbuffer and thus having to emulate using RGBA
368 // format.
TEST_P(FramebufferFormatsTest,RGB565Renderbuffer)369 TEST_P(FramebufferFormatsTest, RGB565Renderbuffer)
370 {
371     GLRenderbuffer rbo;
372     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
373     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB565, 1, 1);
374 
375     GLFramebuffer completeFBO;
376     glBindFramebuffer(GL_FRAMEBUFFER, completeFBO);
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, 0, 0.5f);
384     glClear(GL_COLOR_BUFFER_BIT);
385     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
386 }
387 
388 class FramebufferTest_ES3 : public ANGLETest
389 {
390   protected:
FramebufferTest_ES3()391     FramebufferTest_ES3()
392     {
393         setWindowWidth(kWidth);
394         setWindowHeight(kHeight);
395         setConfigRedBits(8);
396         setConfigGreenBits(8);
397         setConfigBlueBits(8);
398         setConfigAlphaBits(8);
399         setConfigDepthBits(24);
400         setConfigStencilBits(8);
401     }
402 
403     static constexpr GLsizei kWidth  = 64;
404     static constexpr GLsizei kHeight = 256;
405 };
406 
407 // Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error.
TEST_P(FramebufferTest_ES3,InvalidateIncomplete)408 TEST_P(FramebufferTest_ES3, InvalidateIncomplete)
409 {
410     GLFramebuffer framebuffer;
411     GLRenderbuffer renderbuffer;
412 
413     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
414     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
415     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
416     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
417                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
418 
419     std::vector<GLenum> attachments;
420     attachments.push_back(GL_COLOR_ATTACHMENT0);
421 
422     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
423     EXPECT_GL_NO_ERROR();
424 }
425 
426 // Covers sub-invalidating an incomplete framebuffer. This should be a no-op, but should not error.
TEST_P(FramebufferTest_ES3,SubInvalidateIncomplete)427 TEST_P(FramebufferTest_ES3, SubInvalidateIncomplete)
428 {
429     GLFramebuffer framebuffer;
430     GLRenderbuffer renderbuffer;
431 
432     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
433     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
434     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
435     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
436                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
437 
438     std::vector<GLenum> attachments;
439     attachments.push_back(GL_COLOR_ATTACHMENT0);
440 
441     glInvalidateSubFramebuffer(GL_FRAMEBUFFER, 1, attachments.data(), 5, 5, 10, 10);
442     EXPECT_GL_NO_ERROR();
443 }
444 
445 // Test that subinvalidate with no prior command works.  Regression test for the Vulkan backend that
446 // assumed a render pass is started when sub invalidate is called.
TEST_P(FramebufferTest_ES3,SubInvalidateFirst)447 TEST_P(FramebufferTest_ES3, SubInvalidateFirst)
448 {
449     glBindFramebuffer(GL_FRAMEBUFFER, 0);
450 
451     // Invalidate half of the framebuffer using swapped dimensions.
452     std::array<GLenum, 1> attachments = {GL_COLOR};
453     glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 1, attachments.data(), 0, 0, kHeight, kWidth);
454     EXPECT_GL_NO_ERROR();
455 }
456 
457 // Test that subinvalidate doesn't discard data outside area.  Uses swapped width/height for
458 // invalidate which results in a partial invalidate, but also prevents bugs with Vulkan
459 // pre-rotation.
TEST_P(FramebufferTest_ES3,SubInvalidatePartial)460 TEST_P(FramebufferTest_ES3, SubInvalidatePartial)
461 {
462     glBindFramebuffer(GL_FRAMEBUFFER, 0);
463 
464     // Clear the attachment.
465     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
466     glClear(GL_COLOR_BUFFER_BIT);
467     EXPECT_GL_NO_ERROR();
468 
469     // Invalidate half of the framebuffer using swapped dimensions.
470     std::array<GLenum, 1> attachments = {GL_COLOR};
471     glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 1, attachments.data(), 0, 0, kHeight, kWidth);
472     EXPECT_GL_NO_ERROR();
473 
474     // Make sure the other half is correct.
475     EXPECT_PIXEL_COLOR_EQ(0, kWidth, GLColor::red);
476     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kWidth, GLColor::red);
477     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
478     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::red);
479 }
480 
481 // Test that a scissored draw followed by subinvalidate followed by a non-scissored draw retains the
482 // part that is not invalidated.  Uses swapped width/height for invalidate which results in a
483 // partial invalidate, but also prevents bugs with Vulkan pre-rotation.
TEST_P(FramebufferTest_ES3,ScissoredDrawSubInvalidateThenNonScissoredDraw)484 TEST_P(FramebufferTest_ES3, ScissoredDrawSubInvalidateThenNonScissoredDraw)
485 {
486     swapBuffers();
487     glBindFramebuffer(GL_FRAMEBUFFER, 0);
488 
489     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
490     glUseProgram(drawColor);
491     GLint colorUniformLocation =
492         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
493     ASSERT_NE(colorUniformLocation, -1);
494 
495     // Clear color to red and the depth/stencil buffer to 1.0 and 0x55
496     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
497     glClearDepthf(1);
498     glClearStencil(0x55);
499     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
500     EXPECT_GL_NO_ERROR();
501 
502     // Break rendering so the following draw call starts rendering with a scissored area.
503     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
504 
505     // Issue a scissored draw call that changes depth to 0.5 and stencil 0x3C
506     glScissor(0, 0, kHeight, kWidth);
507     glEnable(GL_SCISSOR_TEST);
508 
509     glEnable(GL_DEPTH_TEST);
510     glDepthFunc(GL_ALWAYS);
511 
512     glEnable(GL_STENCIL_TEST);
513     glStencilFunc(GL_ALWAYS, 0x3C, 0xFF);
514     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
515     glStencilMask(0xFF);
516 
517     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
518     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0);
519 
520     // Invalidate the draw region (half of the framebuffer using swapped dimensions).
521     std::array<GLenum, 3> attachments = {GL_COLOR, GL_DEPTH, GL_STENCIL};
522     glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 3, attachments.data(), 0, 0, kHeight, kWidth);
523     EXPECT_GL_NO_ERROR();
524 
525     // Match the scissor to the framebuffer size and issue a draw call that blends blue, and expects
526     // depth to be 1 and stencil to be 0x55.  This is only valid for the half that was not
527     // invalidated.
528     glScissor(0, 0, kWidth, kHeight);
529     glDepthFunc(GL_LESS);
530     glStencilFunc(GL_EQUAL, 0x55, 0xFF);
531     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
532 
533     glEnable(GL_BLEND);
534     glBlendFunc(GL_ONE, GL_ONE);
535     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
536     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95f);
537     ASSERT_GL_NO_ERROR();
538 
539     // Make sure the half that was not invalidated is correct.
540     EXPECT_PIXEL_COLOR_EQ(0, kWidth, GLColor::magenta);
541     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kWidth, GLColor::magenta);
542     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
543     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
544 }
545 
546 // Test that the framebuffer state tracking robustly handles a depth-only attachment being set
547 // as a depth-stencil attachment. It is equivalent to detaching the depth-stencil attachment.
TEST_P(FramebufferTest_ES3,DepthOnlyAsDepthStencil)548 TEST_P(FramebufferTest_ES3, DepthOnlyAsDepthStencil)
549 {
550     GLFramebuffer framebuffer;
551     GLRenderbuffer renderbuffer;
552 
553     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
554     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
555     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 4, 4);
556 
557     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
558                               renderbuffer);
559     EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
560 }
561 
562 // Test that the framebuffer correctly returns that it is not complete if invalid texture mip levels
563 // are bound
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevels)564 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevels)
565 {
566     GLFramebuffer framebuffer;
567     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
568 
569     GLTexture texture;
570     glBindTexture(GL_TEXTURE_2D, texture);
571 
572     // Create a complete mip chain in mips 1 to 3
573     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
574     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
575     glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
576 
577     // Create another complete mip chain in mips 4 to 5
578     glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
579     glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
580 
581     // Create a non-complete mip chain in mip 6
582     glTexImage2D(GL_TEXTURE_2D, 6, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
583 
584     // Incomplete, mipLevel != baseLevel and texture is not mip complete
585     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
586     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
587                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
588 
589     // Complete, mipLevel == baseLevel
590     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
591     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
592 
593     // Complete, mipLevel != baseLevel but texture is now mip complete
594     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2);
595     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
596     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3);
597     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
598 
599     // Incomplete, attached level below the base level
600     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
601     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
602     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
603                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
604 
605     // Incomplete, attached level is beyond effective max level
606     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 4);
607     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
608                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
609 
610     // Complete, mipLevel == baseLevel
611     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
612     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
613 
614     // Complete, mipLevel != baseLevel but texture is now mip complete
615     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 5);
616     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
617 
618     // Complete, mipLevel == baseLevel
619     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 6);
620     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 6);
621     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
622 }
623 
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevelsReadBack)624 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBack)
625 {
626     GLFramebuffer framebuffer;
627     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
628 
629     GLTexture texture;
630     glBindTexture(GL_TEXTURE_2D, texture);
631 
632     const std::array<GLColor, 4 * 4> mip0Data = {
633         GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
634         GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
635         GLColor::red, GLColor::red, GLColor::red, GLColor::red};
636     const std::array<GLColor, 2 * 2> mip1Data = {GLColor::green, GLColor::green, GLColor::green,
637                                                  GLColor::green};
638 
639     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data());
640     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data());
641 
642     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
643     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
644     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
645 
646     glClearColor(0, 0, 1.0f, 1.0f);
647     glClear(GL_COLOR_BUFFER_BIT);
648     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
649 }
650 
651 // TextureAttachmentMipLevelsReadBackWithDraw is a copy of TextureAttachmentMipLevelsReadBack except
652 // for adding a draw after the last clear. The draw forces ANGLE's Vulkan backend to use the
653 // framebuffer that is level 1 of the texture which will trigger the mismatch use of the GL level
654 // and Vulkan level in referring to that rendertarget.
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevelsReadBackWithDraw)655 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBackWithDraw)
656 {
657     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
658 
659     GLFramebuffer framebuffer;
660     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
661 
662     GLTexture texture;
663     glBindTexture(GL_TEXTURE_2D, texture);
664 
665     const std::array<GLColor, 4 * 4> mip0Data = {
666         GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
667         GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red, GLColor::red,
668         GLColor::red, GLColor::red, GLColor::red, GLColor::red};
669     const std::array<GLColor, 2 * 2> mip1Data = {GLColor::green, GLColor::green, GLColor::green,
670                                                  GLColor::green};
671 
672     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data());
673     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data());
674 
675     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
676     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
677     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
678 
679     glClearColor(0, 0, 1.0f, 1.0f);
680     glClear(GL_COLOR_BUFFER_BIT);
681 
682     // This draw triggers the use of the framebuffer
683     glUseProgram(greenProgram);
684     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
685     ASSERT_GL_NO_ERROR();
686     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
687 }
688 
689 // Test that passing an attachment COLOR_ATTACHMENTm where m is equal to MAX_COLOR_ATTACHMENTS
690 // generates an INVALID_OPERATION.
691 // OpenGL ES Version 3.0.5 (November 3, 2016), 4.4.2.4 Attaching Texture Images to a Framebuffer, p.
692 // 208
TEST_P(FramebufferTest_ES3,ColorAttachmentIndexOutOfBounds)693 TEST_P(FramebufferTest_ES3, ColorAttachmentIndexOutOfBounds)
694 {
695     GLFramebuffer framebuffer;
696     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
697 
698     GLint maxColorAttachments = 0;
699     glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
700     GLenum attachment = static_cast<GLenum>(maxColorAttachments + GL_COLOR_ATTACHMENT0);
701 
702     GLTexture texture;
703     glBindTexture(GL_TEXTURE_2D, texture.get());
704     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
705     glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture.get(), 0);
706     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
707 }
708 
709 // Check that depth-only attachments report the correct number of samples.
TEST_P(FramebufferTest_ES3,MultisampleDepthOnly)710 TEST_P(FramebufferTest_ES3, MultisampleDepthOnly)
711 {
712     GLRenderbuffer renderbuffer;
713     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
714     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT24, 32, 32);
715 
716     GLFramebuffer framebuffer;
717     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
718     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
719     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
720     EXPECT_GL_NO_ERROR();
721 
722     GLint samples = 0;
723     glGetIntegerv(GL_SAMPLES, &samples);
724     EXPECT_GL_NO_ERROR();
725     EXPECT_GE(samples, 2);
726 }
727 
728 // Check that we only compare width and height of attachments, not depth.
TEST_P(FramebufferTest_ES3,AttachmentWith3DLayers)729 TEST_P(FramebufferTest_ES3, AttachmentWith3DLayers)
730 {
731     GLTexture texA;
732     glBindTexture(GL_TEXTURE_2D, texA);
733     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
734 
735     GLTexture texB;
736     glBindTexture(GL_TEXTURE_3D, texB);
737     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
738 
739     GLFramebuffer framebuffer;
740     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
741     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
742     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texB, 0, 0);
743     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
744     EXPECT_GL_NO_ERROR();
745 }
746 
747 // Check that invalid layer is detected in framebuffer completeness check.
748 TEST_P(FramebufferTest_ES3, 3DAttachmentInvalidLayer)
749 {
750     GLTexture tex;
751     glBindTexture(GL_TEXTURE_3D, tex);
752     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
753 
754     GLFramebuffer framebuffer;
755     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
756     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
757     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
758                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
759 
760     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
761     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
762     EXPECT_GL_NO_ERROR();
763 }
764 
765 // Check that invalid layer is detected in framebuffer completeness check.
766 TEST_P(FramebufferTest_ES3, 2DArrayInvalidLayer)
767 {
768     GLTexture tex;
769     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
770     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
771 
772     GLFramebuffer framebuffer;
773     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
774     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 2);
775     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
776                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
777 
778     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
779     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
780     EXPECT_GL_NO_ERROR();
781 }
782 
783 // Test that clearing the stencil buffer when the framebuffer only has a color attachment does not
784 // crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentStencil)785 TEST_P(FramebufferTest_ES3, ClearNonexistentStencil)
786 {
787     GLRenderbuffer rbo;
788     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
789     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
790 
791     GLFramebuffer fbo;
792     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
793     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
794 
795     GLint clearValue = 0;
796     glClearBufferiv(GL_STENCIL, 0, &clearValue);
797 
798     // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
799     EXPECT_GL_NO_ERROR();
800 }
801 
802 // Test that clearing the depth buffer when the framebuffer only has a color attachment does not
803 // crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentDepth)804 TEST_P(FramebufferTest_ES3, ClearNonexistentDepth)
805 {
806     GLRenderbuffer rbo;
807     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
808     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
809 
810     GLFramebuffer fbo;
811     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
812     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
813 
814     GLfloat clearValue = 0.0f;
815     glClearBufferfv(GL_DEPTH, 0, &clearValue);
816 
817     // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
818     EXPECT_GL_NO_ERROR();
819 }
820 
821 // Test that clearing a nonexistent color attachment does not crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentColor)822 TEST_P(FramebufferTest_ES3, ClearNonexistentColor)
823 {
824     GLRenderbuffer rbo;
825     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
826     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
827 
828     GLFramebuffer fbo;
829     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
830     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
831 
832     std::vector<GLfloat> clearValue = {{0.0f, 1.0f, 0.0f, 1.0f}};
833     glClearBufferfv(GL_COLOR, 1, clearValue.data());
834 
835     // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
836     EXPECT_GL_NO_ERROR();
837 }
838 
839 // Test that clearing the depth and stencil buffers when the framebuffer only has a color attachment
840 // does not crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentDepthStencil)841 TEST_P(FramebufferTest_ES3, ClearNonexistentDepthStencil)
842 {
843     GLRenderbuffer rbo;
844     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
845     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
846 
847     GLFramebuffer fbo;
848     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
849     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
850 
851     glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
852 
853     // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
854     EXPECT_GL_NO_ERROR();
855 }
856 
857 // Test that clearing a color attachment that has been deleted doesn't crash.
TEST_P(FramebufferTest_ES3,ClearDeletedAttachment)858 TEST_P(FramebufferTest_ES3, ClearDeletedAttachment)
859 {
860     // An INVALID_FRAMEBUFFER_OPERATION error was seen in this test on Mac, not sure where it might
861     // be originating from. http://anglebug.com/2834
862     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
863 
864     GLFramebuffer fbo;
865     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
866 
867     // There used to be a bug where some draw buffer state used to remain set even after the
868     // attachment was detached via deletion. That's why we create, attach and delete this RBO here.
869     GLuint rbo = 0u;
870     glGenRenderbuffers(1, &rbo);
871     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
872     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
873     glDeleteRenderbuffers(1, &rbo);
874 
875     // There needs to be at least one color attachment to prevent early out from the clear calls.
876     GLRenderbuffer rbo2;
877     glBindRenderbuffer(GL_RENDERBUFFER, rbo2);
878     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
879     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rbo2);
880 
881     ASSERT_GL_NO_ERROR();
882 
883     // There's no error specified for clearing nonexistent buffers, it's simply a no-op, so we
884     // expect no GL errors below.
885     std::array<GLfloat, 4> floatClearValue = {0.0f, 0.0f, 0.0f, 0.0f};
886     glClearBufferfv(GL_COLOR, 0, floatClearValue.data());
887     EXPECT_GL_NO_ERROR();
888     std::array<GLuint, 4> uintClearValue = {0u, 0u, 0u, 0u};
889     glClearBufferuiv(GL_COLOR, 0, uintClearValue.data());
890     EXPECT_GL_NO_ERROR();
891     std::array<GLint, 4> intClearValue = {0, 0, 0, 0};
892     glClearBufferiv(GL_COLOR, 0, intClearValue.data());
893     EXPECT_GL_NO_ERROR();
894 }
895 
896 // Test that resizing the color attachment is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeColorAttachmentSmallToLarge)897 TEST_P(FramebufferTest_ES3, ResizeColorAttachmentSmallToLarge)
898 {
899     GLFramebuffer fbo;
900     GLTexture smallTexture;
901     GLTexture largeTexture;
902 
903     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
904     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
905 
906     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
907 
908     // Bind the small texture
909     glBindTexture(GL_TEXTURE_2D, smallTexture);
910     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
911                  GL_UNSIGNED_BYTE, nullptr);
912     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
913     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
914     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
915     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
916 
917     // Draw to FBO backed by the small texture
918     glUseProgram(greenProgram);
919     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
920     ASSERT_GL_NO_ERROR();
921     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
922     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
923 
924     // Change the attachment to the larger texture that fills the window
925     glBindTexture(GL_TEXTURE_2D, largeTexture);
926     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
927                  GL_UNSIGNED_BYTE, nullptr);
928     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
929     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
930     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
931     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
932 
933     // Draw to FBO backed by the large texture
934     glUseProgram(blueProgram);
935     drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
936     ASSERT_GL_NO_ERROR();
937     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
938     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
939 }
940 
941 // Test that resizing the color attachment is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeColorAttachmentLargeToSmall)942 TEST_P(FramebufferTest_ES3, ResizeColorAttachmentLargeToSmall)
943 {
944     GLFramebuffer fbo;
945     GLTexture smallTexture;
946     GLTexture largeTexture;
947 
948     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
949     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
950 
951     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
952 
953     // Bind the large texture
954     glBindTexture(GL_TEXTURE_2D, largeTexture);
955     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
956                  GL_UNSIGNED_BYTE, nullptr);
957     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
958     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
959     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
960     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
961 
962     // Draw to FBO backed by the large texture
963     glUseProgram(blueProgram);
964     drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
965     ASSERT_GL_NO_ERROR();
966     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
967     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
968 
969     // Change the attachment to the smaller texture
970     glBindTexture(GL_TEXTURE_2D, smallTexture);
971     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
972                  GL_UNSIGNED_BYTE, nullptr);
973     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
974     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
975     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
976     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
977 
978     // Draw to FBO backed by the small texture
979     glUseProgram(greenProgram);
980     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
981     ASSERT_GL_NO_ERROR();
982     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
983     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
984 }
985 
986 // Test that resizing the texture is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeTextureLargeToSmall)987 TEST_P(FramebufferTest_ES3, ResizeTextureLargeToSmall)
988 {
989     GLFramebuffer fbo;
990     GLTexture texture;
991 
992     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
993     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
994 
995     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
996 
997     // Allocate a large texture
998     glBindTexture(GL_TEXTURE_2D, texture);
999     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1000                  GL_UNSIGNED_BYTE, nullptr);
1001     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1002     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1003     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1004     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1005 
1006     // Draw to FBO backed by the large texture
1007     glUseProgram(blueProgram);
1008     drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
1009     ASSERT_GL_NO_ERROR();
1010     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1011     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
1012 
1013     // Shrink the texture
1014     glBindTexture(GL_TEXTURE_2D, texture);
1015     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
1016                  GL_UNSIGNED_BYTE, nullptr);
1017     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1018     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1019     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1020     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1021 
1022     // Draw to FBO backed by the small texture
1023     glUseProgram(greenProgram);
1024     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
1025     ASSERT_GL_NO_ERROR();
1026     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1027     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
1028 }
1029 
1030 // Test that resizing the texture is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeTextureSmallToLarge)1031 TEST_P(FramebufferTest_ES3, ResizeTextureSmallToLarge)
1032 {
1033     GLFramebuffer fbo;
1034     GLTexture texture;
1035 
1036     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1037     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1038 
1039     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1040 
1041     // Allocate a small texture
1042     glBindTexture(GL_TEXTURE_2D, texture);
1043     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
1044                  GL_UNSIGNED_BYTE, nullptr);
1045     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1046     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1047     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1048     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1049 
1050     // Draw to FBO backed by the large texture
1051     glUseProgram(blueProgram);
1052     drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
1053     ASSERT_GL_NO_ERROR();
1054     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1055     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::blue);
1056 
1057     // Grow the texture
1058     glBindTexture(GL_TEXTURE_2D, texture);
1059     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1060                  GL_UNSIGNED_BYTE, nullptr);
1061     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1062     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1063     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1064     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1065 
1066     // Draw to FBO backed by the small texture
1067     glUseProgram(greenProgram);
1068     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
1069     ASSERT_GL_NO_ERROR();
1070     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1071     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
1072 }
1073 
1074 // Test that fewer outputs than framebuffer attachments doesn't crash.  This causes a Vulkan
1075 // validation warning, but should not be fatal.
TEST_P(FramebufferTest_ES3,FewerShaderOutputsThanAttachments)1076 TEST_P(FramebufferTest_ES3, FewerShaderOutputsThanAttachments)
1077 {
1078     constexpr char kFS[] = R"(#version 300 es
1079 precision highp float;
1080 
1081 layout(location = 0) out vec4 color0;
1082 layout(location = 1) out vec4 color1;
1083 layout(location = 2) out vec4 color2;
1084 
1085 void main()
1086 {
1087     color0 = vec4(1.0, 0.0, 0.0, 1.0);
1088     color1 = vec4(0.0, 1.0, 0.0, 1.0);
1089     color2 = vec4(0.0, 0.0, 1.0, 1.0);
1090 }
1091 )";
1092 
1093     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
1094 
1095     constexpr GLint kDrawBufferCount = 4;
1096 
1097     GLint maxDrawBuffers;
1098     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
1099     ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
1100 
1101     GLTexture textures[kDrawBufferCount];
1102 
1103     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
1104     {
1105         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
1106         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
1107                      GL_UNSIGNED_BYTE, nullptr);
1108     }
1109 
1110     GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,
1111                                         GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
1112 
1113     GLFramebuffer fbo;
1114     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
1115 
1116     // Enable all draw buffers.
1117     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
1118     {
1119         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
1120         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
1121                                textures[texIndex], 0);
1122     }
1123     glDrawBuffers(kDrawBufferCount, allBufs);
1124 
1125     // Draw with simple program.
1126     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1127     ASSERT_GL_NO_ERROR();
1128 }
1129 
1130 class FramebufferTestWithFormatFallback : public ANGLETest
1131 {
1132   protected:
FramebufferTestWithFormatFallback()1133     FramebufferTestWithFormatFallback()
1134     {
1135         setWindowWidth(16);
1136         setWindowHeight(16);
1137         setConfigRedBits(8);
1138         setConfigGreenBits(8);
1139         setConfigBlueBits(8);
1140         setConfigAlphaBits(8);
1141         setConfigDepthBits(24);
1142         setConfigStencilBits(8);
1143     }
1144 
1145     void texImageFollowedByFBORead(GLenum internalFormat, GLenum type);
1146     void blitCopyFollowedByFBORead(GLenum internalFormat, GLenum type);
1147     void copyTexImageFollowedBySampling(GLenum internalFormat, GLenum type);
1148     void cubeTexImageFollowedByFBORead(GLenum internalFormat, GLenum type);
1149     GLushort convertGLColorToUShort(GLenum internalFormat, const GLColor &color);
1150     static constexpr GLsizei kTexWidth  = 16;
1151     static constexpr GLsizei kTexHeight = 16;
1152     static constexpr GLsizei kMaxLevel  = 4;
1153 };
1154 
convertGLColorToUShort(GLenum internalFormat,const GLColor & color)1155 GLushort FramebufferTestWithFormatFallback::convertGLColorToUShort(GLenum internalFormat,
1156                                                                    const GLColor &color)
1157 {
1158     GLushort r, g, b, a;
1159     switch (internalFormat)
1160     {
1161         case GL_RGB5_A1:
1162             r = (color.R >> 3) << 11;
1163             g = (color.G >> 3) << 6;
1164             b = (color.B >> 3) << 1;
1165             a = color.A >> 7;
1166             break;
1167         case GL_RGBA4:
1168             r = (color.R >> 4) << 12;
1169             g = (color.G >> 4) << 8;
1170             b = (color.B >> 4) << 4;
1171             a = color.A >> 4;
1172             break;
1173         default:
1174             UNREACHABLE();
1175             r = 0;
1176             g = 0;
1177             b = 0;
1178             a = 0;
1179             break;
1180     }
1181     return r | g | b | a;
1182 }
1183 
1184 // Test texture format fallback while it has staged updates.
texImageFollowedByFBORead(GLenum internalFormat,GLenum type)1185 void FramebufferTestWithFormatFallback::texImageFollowedByFBORead(GLenum internalFormat,
1186                                                                   GLenum type)
1187 {
1188     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
1189     GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1190     ASSERT_NE(-1, textureLocation);
1191     GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1192     ASSERT_NE(-1, lodLocation);
1193 
1194     const GLColor kColor = GLColor::blue;
1195 
1196     for (int loop = 0; loop < 4; loop++)
1197     {
1198         GLTexture texture;
1199         glBindTexture(GL_TEXTURE_2D, texture);
1200         const GLushort u16Color = convertGLColorToUShort(internalFormat, kColor);
1201         std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1202         if (loop == 0 || loop == 2)
1203         {
1204             glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1205                          pixels.data());
1206         }
1207         else
1208         {
1209             glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, kTexWidth, kTexHeight);
1210             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTexWidth, kTexHeight, GL_RGBA, type,
1211                             pixels.data());
1212         }
1213         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1214         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1215 
1216         if (loop >= 2)
1217         {
1218             // Draw quad using texture
1219             glUseProgram(program);
1220             glActiveTexture(GL_TEXTURE0);
1221             glBindTexture(GL_TEXTURE_2D, texture);
1222             glClearColor(0, 0, 0, 1);
1223             glClear(GL_COLOR_BUFFER_BIT);
1224             glUniform1f(lodLocation, 0);
1225             drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1226             EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
1227             ASSERT_GL_NO_ERROR();
1228         }
1229 
1230         // attach blue texture to FBO
1231         GLFramebuffer fbo;
1232         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1233         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1234         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1235         EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, kColor.R, kColor.G, kColor.B, kColor.A);
1236         ASSERT_GL_NO_ERROR();
1237     }
1238 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_TexImage)1239 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_TexImage)
1240 {
1241     texImageFollowedByFBORead(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
1242 }
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_TexImage)1243 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_TexImage)
1244 {
1245     texImageFollowedByFBORead(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
1246 }
1247 
1248 // Test texture format fallback while it has staged updates and then do copyTexImage2D and followed
1249 // by sampling.
copyTexImageFollowedBySampling(GLenum internalFormat,GLenum type)1250 void FramebufferTestWithFormatFallback::copyTexImageFollowedBySampling(GLenum internalFormat,
1251                                                                        GLenum type)
1252 {
1253     const GLColor kColor = GLColor::blue;
1254     // Create blue texture
1255     GLTexture blueTex2D;
1256     glBindTexture(GL_TEXTURE_2D, blueTex2D);
1257     const GLushort u16Color = convertGLColorToUShort(internalFormat, kColor);
1258     std::vector<GLushort> bluePixels(kTexWidth * kTexHeight, u16Color);
1259     glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1260                  bluePixels.data());
1261     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1262     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1263 
1264     // attach blue texture to FBO and read back to verify. This should trigger format conversion
1265     GLFramebuffer blueFbo;
1266     glBindFramebuffer(GL_FRAMEBUFFER, blueFbo);
1267     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blueTex2D, 0);
1268     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1269     EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 0, 0, 255, 255);
1270     ASSERT_GL_NO_ERROR();
1271 
1272     // Create red texture
1273     GLTexture copyTex2D;
1274     glBindTexture(GL_TEXTURE_2D, copyTex2D);
1275     std::vector<GLushort> redPixels(kTexWidth * kTexHeight, 0xF801);
1276     glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1277                  redPixels.data());
1278     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1279     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1280 
1281     // CopyTexImage from blue to red
1282     glCopyTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 0, 0, kTexWidth, kTexHeight, 0);
1283     ASSERT_GL_NO_ERROR();
1284 
1285     // Draw with copyTex2D
1286     glBindFramebuffer(GL_FRAMEBUFFER, 0);
1287     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
1288     glUseProgram(program);
1289     GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1290     ASSERT_NE(-1, textureLocation);
1291     GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1292     ASSERT_NE(-1, lodLocation);
1293     glActiveTexture(GL_TEXTURE0);
1294     glBindTexture(GL_TEXTURE_2D, copyTex2D);
1295     glClearColor(0, 1, 0, 1);
1296     glClear(GL_COLOR_BUFFER_BIT);
1297     glUniform1f(lodLocation, 0);
1298     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1299     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, kColor.R, kColor.G, kColor.B,
1300                     kColor.A);
1301     ASSERT_GL_NO_ERROR();
1302 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_CopyTexImage)1303 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_CopyTexImage)
1304 {
1305     copyTexImageFollowedBySampling(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
1306 }
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_CopyTexImage)1307 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_CopyTexImage)
1308 {
1309     copyTexImageFollowedBySampling(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
1310 }
1311 
1312 // Test texture format fallback while it has staged updates and then do FBO blit and followed by
1313 // copyTexImage2D.
blitCopyFollowedByFBORead(GLenum internalFormat,GLenum type)1314 void FramebufferTestWithFormatFallback::blitCopyFollowedByFBORead(GLenum internalFormat,
1315                                                                   GLenum type)
1316 {
1317     for (int loop = 0; loop < 2; loop++)
1318     {
1319         // Create blue texture
1320         GLTexture blueTex2D;
1321         glBindTexture(GL_TEXTURE_2D, blueTex2D);
1322         GLushort u16Color = convertGLColorToUShort(internalFormat, GLColor::blue);
1323         std::vector<GLushort> bluePixels(kTexWidth * kTexHeight, u16Color);
1324         glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1325                      bluePixels.data());
1326         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1327         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1328 
1329         // attach blue texture to FBO
1330         GLFramebuffer readFbo;
1331         glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1332         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blueTex2D,
1333                                0);
1334         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
1335 
1336         GLTexture redTex2D;
1337         GLRenderbuffer renderBuffer;
1338         GLFramebuffer drawFbo;
1339         if (loop == 0)
1340         {
1341             glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
1342             glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, kTexWidth, kTexHeight);
1343 
1344             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
1345             glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1346                                       renderBuffer);
1347             EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1348             glClearColor(1.0, 0.0, 0.0, 1.0);
1349             glClear(GL_COLOR_BUFFER_BIT);
1350         }
1351         else
1352         {
1353             glBindTexture(GL_TEXTURE_2D, redTex2D);
1354             u16Color = convertGLColorToUShort(internalFormat, GLColor::red);
1355             std::vector<GLushort> redPixels(kTexWidth * kTexHeight, u16Color);
1356             glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1357                          redPixels.data());
1358             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1359             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1360 
1361             glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFbo);
1362             glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1363                                    redTex2D, 0);
1364             EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1365         }
1366 
1367         // Blit
1368         glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1369         glBlitFramebuffer(0, 0, kTexWidth, kTexHeight, 0, 0, kTexWidth, kTexHeight,
1370                           GL_COLOR_BUFFER_BIT, GL_NEAREST);
1371         ASSERT_GL_NO_ERROR();
1372 
1373         GLFramebuffer readFbo2;
1374         if (loop == 0)
1375         {
1376             // CopyTexImage from renderBuffer to copyTex2D
1377             glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo2);
1378             glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1379                                       renderBuffer);
1380         }
1381         else
1382         {
1383 
1384             // CopyTexImage from redTex2D to copyTex2D
1385             glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo2);
1386             glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1387                                    redTex2D, 0);
1388         }
1389         GLTexture copyTex2D;
1390         glBindTexture(GL_TEXTURE_2D, copyTex2D);
1391         glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, kTexWidth, kTexHeight, 0);
1392         ASSERT_GL_NO_ERROR();
1393         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1394         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1395         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1396         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1397         glBindTexture(GL_TEXTURE_2D, 0);
1398 
1399         // Read out red texture
1400         GLFramebuffer readFbo3;
1401         glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo3);
1402         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTex2D,
1403                                0);
1404         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
1405         EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 0, 0, 255, 255);
1406         ASSERT_GL_NO_ERROR();
1407     }
1408 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_BlitCopyTexImage)1409 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_BlitCopyTexImage)
1410 {
1411     blitCopyFollowedByFBORead(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
1412 }
TEST_P(FramebufferTestWithFormatFallback,RGBA4444_BlitCopyTexImage)1413 TEST_P(FramebufferTestWithFormatFallback, RGBA4444_BlitCopyTexImage)
1414 {
1415     blitCopyFollowedByFBORead(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
1416 }
1417 
1418 // Test texture format fallback while it has staged updates, specially for cubemap target.
cubeTexImageFollowedByFBORead(GLenum internalFormat,GLenum type)1419 void FramebufferTestWithFormatFallback::cubeTexImageFollowedByFBORead(GLenum internalFormat,
1420                                                                       GLenum type)
1421 {
1422     const GLColor kColors[6] = {GLColor::red,  GLColor::green,  GLColor::blue,
1423                                 GLColor::cyan, GLColor::yellow, GLColor::magenta};
1424     GLTexture cubeTex2D;
1425     glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex2D);
1426     for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1427          target++)
1428     {
1429         int j                   = target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
1430         const GLushort u16Color = convertGLColorToUShort(internalFormat, kColors[j]);
1431         std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1432         glTexImage2D(target, 0, internalFormat, kTexWidth, kTexHeight, 0, GL_RGBA, type,
1433                      pixels.data());
1434     }
1435     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1436     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1437 
1438     // attach blue texture to FBO
1439     GLFramebuffer fbo;
1440     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1441     for (GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1442          target++)
1443     {
1444         GLint j = target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
1445         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, cubeTex2D, 0);
1446         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1447         EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, kColors[j].R, kColors[j].G, kColors[j].B,
1448                         kColors[j].A);
1449     }
1450     ASSERT_GL_NO_ERROR();
1451 }
TEST_P(FramebufferTestWithFormatFallback,R5G5B5A1_CubeTexImage)1452 TEST_P(FramebufferTestWithFormatFallback, R5G5B5A1_CubeTexImage)
1453 {
1454     cubeTexImageFollowedByFBORead(GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1);
1455 }
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_CubeTexImage)1456 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_CubeTexImage)
1457 {
1458     cubeTexImageFollowedByFBORead(GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4);
1459 }
1460 
1461 // Tests that the out-of-range staged update is reformated when mipmapping is enabled, but not
1462 // before it.
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_OutOfRangeStagedUpdateReformated)1463 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_OutOfRangeStagedUpdateReformated)
1464 {
1465     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
1466     glUseProgram(program);
1467     GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1468     ASSERT_NE(-1, textureLocation);
1469     GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1470     ASSERT_NE(-1, lodLocation);
1471 
1472     GLTexture texture;
1473     glBindTexture(GL_TEXTURE_2D, texture);
1474     GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
1475     std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1476     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
1477                  GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
1478     u16Color = convertGLColorToUShort(GL_RGB5_A1, GLColor::green);
1479     pixels.assign(kTexWidth * kTexHeight, u16Color);
1480     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth / 2, kTexHeight / 2, 0, GL_RGBA,
1481                  GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
1482     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1483     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1484 
1485     // Draw quad
1486     glActiveTexture(GL_TEXTURE0);
1487     glBindTexture(GL_TEXTURE_2D, texture);
1488     glUniform1f(lodLocation, 0);
1489     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1490     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
1491 
1492     // Now trigger format conversion
1493     GLFramebuffer readFbo;
1494     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1495     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1496     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
1497     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowWidth() / 2, 255, 0, 0, 255);
1498 
1499     // update level0 with compatible data and enable mipmap
1500     u16Color = convertGLColorToUShort(GL_RGB5_A1, GLColor::blue);
1501     pixels.assign(kTexWidth * kTexHeight, u16Color);
1502     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
1503                  GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
1504     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1505     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1506     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
1507 
1508     // Draw quad with lod0 and lod1 and verify color
1509     glUniform1f(lodLocation, 0);
1510     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1511     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
1512     glUniform1f(lodLocation, 1);
1513     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1514     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
1515     ASSERT_GL_NO_ERROR();
1516 }
1517 
1518 // Tests that the texture is reformatted when the clear is done through the draw path.
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_MaskedClear)1519 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_MaskedClear)
1520 {
1521     for (int loop = 0; loop < 2; loop++)
1522     {
1523         GLTexture texture;
1524         glBindTexture(GL_TEXTURE_2D, texture);
1525         GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
1526         std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1527         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
1528                      GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
1529         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1530         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1531 
1532         if (loop == 0)
1533         {
1534             // Draw quad
1535             ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(),
1536                              essl3_shaders::fs::Texture2DLod());
1537             glUseProgram(program);
1538             GLint textureLocation =
1539                 glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1540             ASSERT_NE(-1, textureLocation);
1541             GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1542             ASSERT_NE(-1, lodLocation);
1543             glActiveTexture(GL_TEXTURE0);
1544             glBindTexture(GL_TEXTURE_2D, texture);
1545             glClearColor(0, 0, 0, 1);
1546             glClear(GL_COLOR_BUFFER_BIT);
1547             glUniform1f(lodLocation, 0);
1548             drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1549             EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
1550             ASSERT_GL_NO_ERROR();
1551         }
1552 
1553         // Now trigger format conversion with masked clear
1554         GLFramebuffer fbo;
1555         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1556         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1557         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1558         glClearColor(0, 1, 1, 1);
1559         glColorMask(false, true, false, false);
1560         glClear(GL_COLOR_BUFFER_BIT);
1561         EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 255, 255, 0, 255);
1562         ASSERT_GL_NO_ERROR();
1563     }
1564 }
1565 
1566 // Tests that glGenerateMipmap works when the format is converted to renderable..
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_GenerateMipmap)1567 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_GenerateMipmap)
1568 {
1569     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
1570     glUseProgram(program);
1571     GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1572     ASSERT_NE(-1, textureLocation);
1573     GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1574     ASSERT_NE(-1, lodLocation);
1575 
1576     for (int loop = 0; loop < 4; loop++)
1577     {
1578         GLTexture texture;
1579         glBindTexture(GL_TEXTURE_2D, texture);
1580         GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
1581         std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1582         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
1583                      GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
1584         u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::green);
1585         pixels.assign(kTexWidth * kTexHeight, u16Color);
1586         glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth / 2, kTexHeight / 2, 0, GL_RGBA,
1587                      GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
1588         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1589         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1590 
1591         if (loop == 0 || loop == 2)
1592         {
1593             // Draw quad
1594             glUniform1f(lodLocation, 0);
1595             drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1596             EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
1597             ASSERT_GL_NO_ERROR();
1598         }
1599 
1600         if (loop > 2)
1601         {
1602             // Now trigger format conversion
1603             GLFramebuffer readFbo;
1604             glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1605             glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1606                                    texture, 0);
1607             EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
1608         }
1609 
1610         // GenerateMipmap
1611         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1612         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1613         glGenerateMipmap(GL_TEXTURE_2D);
1614 
1615         // Verify each lod
1616         for (int lod = 0; lod <= kMaxLevel; lod++)
1617         {
1618             glUniform1f(lodLocation, lod);
1619             drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1620             EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
1621         }
1622         ASSERT_GL_NO_ERROR();
1623     }
1624 }
1625 
1626 // Tests that when reformatting the image, incompatible updates don't cause a problem.
TEST_P(FramebufferTestWithFormatFallback,R4G4B4A4_InCompatibleFormat)1627 TEST_P(FramebufferTestWithFormatFallback, R4G4B4A4_InCompatibleFormat)
1628 {
1629     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
1630     glUseProgram(program);
1631     GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
1632     ASSERT_NE(-1, textureLocation);
1633     GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
1634     ASSERT_NE(-1, lodLocation);
1635 
1636     for (int loop = 0; loop < 4; loop++)
1637     {
1638         GLTexture texture;
1639         glBindTexture(GL_TEXTURE_2D, texture);
1640         // Define a texture with lod0 and lod1 with two different effective internal formats or size
1641         GLushort u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::red);
1642         std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
1643         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
1644                      GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
1645         if (loop < 2)
1646         {
1647             u16Color = convertGLColorToUShort(GL_RGB5_A1, GLColor::green);
1648             pixels.assign(kTexWidth * kTexHeight, u16Color);
1649             // bad effective internal format
1650             glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth / 2, kTexHeight / 2, 0, GL_RGBA,
1651                          GL_UNSIGNED_SHORT_5_5_5_1, pixels.data());
1652         }
1653         else
1654         {
1655             u16Color = convertGLColorToUShort(GL_RGBA4, GLColor::green);
1656             pixels.assign(kTexWidth * kTexHeight, u16Color);
1657             // bad size
1658             glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kTexWidth, kTexHeight, 0, GL_RGBA,
1659                          GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
1660         }
1661         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1662         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1663 
1664         // Now trigger format conversion and verify lod0
1665         GLFramebuffer readFbo;
1666         glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
1667         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture,
1668                                0);
1669         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
1670         EXPECT_PIXEL_EQ(kTexWidth / 2, kTexHeight / 2, 255, 0, 0, 255);
1671 
1672         if (loop == 1 || loop == 3)
1673         {
1674             // Disable mipmap and sample from lod0 and verify
1675             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1676             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1677             glUniform1f(lodLocation, 0);
1678             drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1679             EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
1680         }
1681     }
1682 }
1683 
1684 class FramebufferTest_ES31 : public ANGLETest
1685 {
1686   protected:
validateSamplePass(GLuint & query,GLuint & passedCount,GLint width,GLint height)1687     void validateSamplePass(GLuint &query, GLuint &passedCount, GLint width, GLint height)
1688     {
1689         glUniform2i(0, width - 1, height - 1);
1690         glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
1691         glDrawArrays(GL_TRIANGLES, 0, 6);
1692         glEndQuery(GL_ANY_SAMPLES_PASSED);
1693         glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
1694         EXPECT_GT(static_cast<GLint>(passedCount), 0);
1695 
1696         glUniform2i(0, width - 1, height);
1697         glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
1698         glDrawArrays(GL_TRIANGLES, 0, 6);
1699         glEndQuery(GL_ANY_SAMPLES_PASSED);
1700         glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
1701         EXPECT_EQ(static_cast<GLint>(passedCount), 0);
1702 
1703         glUniform2i(0, width, height - 1);
1704         glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
1705         glDrawArrays(GL_TRIANGLES, 0, 6);
1706         glEndQuery(GL_ANY_SAMPLES_PASSED);
1707         glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
1708         EXPECT_EQ(static_cast<GLint>(passedCount), 0);
1709     }
1710 
1711     static constexpr char kFSWriteRedGreen[] = R"(#extension GL_EXT_draw_buffers : enable
1712 precision highp float;
1713 void main()
1714 {
1715     gl_FragData[0] = vec4(1.0, 0.0, 0.0, 1.0);  // attachment 0: red
1716     gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0);  // attachment 1: green
1717 })";
1718 };
1719 
1720 // Until C++17, need to redundantly declare the constexpr array members outside the class.
1721 constexpr char FramebufferTest_ES31::kFSWriteRedGreen[];
1722 
1723 // Test that without attachment, if either the value of FRAMEBUFFER_DEFAULT_WIDTH or
1724 // FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is incomplete.
TEST_P(FramebufferTest_ES31,IncompleteMissingAttachmentDefaultParam)1725 TEST_P(FramebufferTest_ES31, IncompleteMissingAttachmentDefaultParam)
1726 {
1727     GLFramebuffer mFramebuffer;
1728     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1729 
1730     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
1731     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
1732     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1733 
1734     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
1735     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
1736     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
1737                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
1738 
1739     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
1740     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
1741     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
1742                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
1743 
1744     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
1745     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
1746     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
1747                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
1748 
1749     ASSERT_GL_NO_ERROR();
1750 }
1751 
1752 // Test that the sample count of a mix of texture and renderbuffer should be same.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleSampleCountMix)1753 TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix)
1754 {
1755     GLFramebuffer mFramebuffer;
1756     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1757 
1758     // Lookup the supported number of sample counts (rely on fact that ANGLE uses the same set of
1759     // sample counts for textures and renderbuffers)
1760     GLint numSampleCounts = 0;
1761     std::vector<GLint> sampleCounts;
1762     GLsizei queryBufferSize = 1;
1763     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
1764                           queryBufferSize, &numSampleCounts);
1765     ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
1766     sampleCounts.resize(numSampleCounts);
1767     queryBufferSize = numSampleCounts;
1768     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
1769                           sampleCounts.data());
1770 
1771     GLTexture mTexture;
1772     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
1773     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
1774 
1775     GLRenderbuffer mRenderbuffer;
1776     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
1777     glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCounts[1], GL_RGBA8, 1, 1);
1778     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1779                            mTexture.get(), 0);
1780     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
1781                               mRenderbuffer.get());
1782     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1783                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
1784 
1785     ASSERT_GL_NO_ERROR();
1786 }
1787 
1788 // Test that the sample count of texture attachments should be same.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleSampleCountTex)1789 TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex)
1790 {
1791     GLFramebuffer mFramebuffer;
1792     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1793 
1794     // Lookup the supported number of sample counts
1795     GLint numSampleCounts = 0;
1796     std::vector<GLint> sampleCounts;
1797     GLsizei queryBufferSize = 1;
1798     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
1799                           queryBufferSize, &numSampleCounts);
1800     ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
1801     sampleCounts.resize(numSampleCounts);
1802     queryBufferSize = numSampleCounts;
1803     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
1804                           sampleCounts.data());
1805 
1806     GLTexture mTextures[2];
1807     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
1808     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
1809     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
1810     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[1], GL_RGBA8, 1, 1, true);
1811     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1812                            mTextures[0].get(), 0);
1813     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1814                            mTextures[1].get(), 0);
1815     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1816                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
1817 
1818     ASSERT_GL_NO_ERROR();
1819 }
1820 
1821 // Test that if the attached images are a mix of renderbuffers and textures, the value of
1822 // TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleFixedSampleLocationsMix)1823 TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsMix)
1824 {
1825     GLFramebuffer mFramebuffer;
1826     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1827 
1828     GLTexture mTexture;
1829     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
1830     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
1831 
1832     GLRenderbuffer mRenderbuffer;
1833     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
1834     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
1835     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1836                            mTexture.get(), 0);
1837     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
1838                               mRenderbuffer.get());
1839     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1840                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
1841 
1842     ASSERT_GL_NO_ERROR();
1843 }
1844 
1845 // Test that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleFixedSampleLocationsTex)1846 TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsTex)
1847 {
1848     GLFramebuffer mFramebuffer;
1849     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1850 
1851     GLTexture mTextures[2];
1852     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
1853     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
1854     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1855                            mTextures[0].get(), 0);
1856     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
1857     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGB8, 1, 1, true);
1858     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1859                            mTextures[1].get(), 0);
1860     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1861                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
1862 
1863     ASSERT_GL_NO_ERROR();
1864 }
1865 
1866 // Test resolving a multisampled texture with blit
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlit)1867 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlit)
1868 {
1869     constexpr int kSize = 16;
1870     glViewport(0, 0, kSize, kSize);
1871 
1872     GLFramebuffer msaaFBO;
1873     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1874 
1875     GLTexture texture;
1876     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
1877     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1878     ASSERT_GL_NO_ERROR();
1879     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1880                            texture.get(), 0);
1881     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1882 
1883     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1884                      essl31_shaders::fs::RedGreenGradient());
1885     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1886     ASSERT_GL_NO_ERROR();
1887 
1888     // Create another FBO to resolve the multisample buffer into.
1889     GLTexture resolveTexture;
1890     GLFramebuffer resolveFBO;
1891     glBindTexture(GL_TEXTURE_2D, resolveTexture);
1892     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1893     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1894     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1895     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1896 
1897     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1898     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1899     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1900     ASSERT_GL_NO_ERROR();
1901 
1902     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1903     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
1904     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
1905     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
1906     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
1907     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
1908                       255, 1.0);
1909 }
1910 
1911 // Test resolving a multisampled texture with blit to a different format
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitDifferentFormats)1912 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitDifferentFormats)
1913 {
1914     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888"));
1915 
1916     constexpr int kSize = 16;
1917     glViewport(0, 0, kSize, kSize);
1918 
1919     GLFramebuffer msaaFBO;
1920     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1921 
1922     GLTexture texture;
1923     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
1924     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1925     ASSERT_GL_NO_ERROR();
1926     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1927                            texture.get(), 0);
1928     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1929 
1930     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1931                      essl31_shaders::fs::RedGreenGradient());
1932     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1933     ASSERT_GL_NO_ERROR();
1934 
1935     // Create another FBO to resolve the multisample buffer into.
1936     GLTexture resolveTexture;
1937     GLFramebuffer resolveFBO;
1938     glBindTexture(GL_TEXTURE_2D, resolveTexture);
1939     glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA8_EXT, kSize, kSize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1940                  nullptr);
1941     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1942     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1943     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1944 
1945     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1946     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1947     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1948     ASSERT_GL_NO_ERROR();
1949 
1950     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1951     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
1952     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
1953     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
1954     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
1955     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
1956                       255, 1.0);
1957 }
1958 
1959 // Test resolving a multisampled texture with blit after drawing to mulitiple FBOs.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitMultipleFBOs)1960 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitMultipleFBOs)
1961 {
1962     // FBO 1 -> multisample draw (red)
1963     // FBO 2 -> multisample draw (green)
1964     // Bind FBO 1 as read
1965     // Bind FBO 3 as draw
1966     // Resolve
1967 
1968     constexpr int kSize = 16;
1969     glViewport(0, 0, kSize, kSize);
1970 
1971     GLFramebuffer msaaFBORed;
1972     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBORed.get());
1973 
1974     GLTexture textureRed;
1975     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureRed.get());
1976     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1977     ASSERT_GL_NO_ERROR();
1978     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1979                            textureRed.get(), 0);
1980     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1981 
1982     ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
1983     drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1984     ASSERT_GL_NO_ERROR();
1985 
1986     GLFramebuffer msaaFBOGreen;
1987     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBOGreen.get());
1988 
1989     GLTexture textureGreen;
1990     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureGreen.get());
1991     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1992     ASSERT_GL_NO_ERROR();
1993     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1994                            textureGreen.get(), 0);
1995     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1996 
1997     ANGLE_GL_PROGRAM(greenProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Green());
1998     drawQuad(greenProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1999     ASSERT_GL_NO_ERROR();
2000 
2001     // Create another FBO to resolve the multisample buffer into.
2002     GLTexture resolveTexture;
2003     GLFramebuffer resolveFBO;
2004     glBindTexture(GL_TEXTURE_2D, resolveTexture);
2005     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2006     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2007     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2008     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2009 
2010     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
2011     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2012     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2013     ASSERT_GL_NO_ERROR();
2014 
2015     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2016     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2017 }
2018 
2019 // Test resolving a multisampled texture with blit after drawing to mulitiple FBOs.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitMultipleResolves)2020 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitMultipleResolves)
2021 {
2022     // Draw multisampled in FBO 1
2023     // Bind FBO 1 as read
2024     // Bind FBO 2 as draw
2025     // Resolve
2026     // Bind FBO 3 as draw
2027     // Resolve
2028 
2029     constexpr int kSize = 16;
2030     glViewport(0, 0, kSize, kSize);
2031 
2032     GLFramebuffer msaaFBORed;
2033     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBORed.get());
2034 
2035     GLTexture textureRed;
2036     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureRed.get());
2037     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2038     ASSERT_GL_NO_ERROR();
2039     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2040                            textureRed.get(), 0);
2041     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2042 
2043     ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
2044     drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2045     ASSERT_GL_NO_ERROR();
2046 
2047     // Create another FBO to resolve the multisample buffer into.
2048     GLTexture resolveTexture1;
2049     GLFramebuffer resolveFBO1;
2050     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
2051     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2052     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
2053     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
2054     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2055 
2056     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
2057     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
2058     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2059     ASSERT_GL_NO_ERROR();
2060 
2061     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
2062     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2063 
2064     // Create another FBO to resolve the multisample buffer into.
2065     GLTexture resolveTexture2;
2066     GLFramebuffer resolveFBO2;
2067     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
2068     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2069     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
2070     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
2071     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2072 
2073     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
2074     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
2075     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2076     ASSERT_GL_NO_ERROR();
2077 
2078     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
2079     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2080 }
2081 
2082 // Test resolving a multisampled texture with blit into an FBO with different read and draw
2083 // attachments.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitDifferentReadDrawBuffers)2084 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitDifferentReadDrawBuffers)
2085 {
2086     constexpr int kSize = 16;
2087     glViewport(0, 0, kSize, kSize);
2088 
2089     GLFramebuffer msaaFBO;
2090     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2091 
2092     GLTexture texture;
2093     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
2094     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2095     ASSERT_GL_NO_ERROR();
2096     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2097                            texture.get(), 0);
2098     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2099 
2100     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2101                      essl31_shaders::fs::RedGreenGradient());
2102     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2103     ASSERT_GL_NO_ERROR();
2104 
2105     // Create another FBO to resolve the multisample buffer into.
2106     GLFramebuffer resolveFBO;
2107     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2108 
2109     // Bind both read and draw textures as separate attachments.
2110     const std::vector<GLColor> blueColors(kSize * kSize, GLColor::blue);
2111     GLTexture resolveReadTexture;
2112     glBindTexture(GL_TEXTURE_2D, resolveReadTexture);
2113     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2114                  blueColors.data());
2115     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveReadTexture,
2116                            0);
2117     glReadBuffer(GL_COLOR_ATTACHMENT0);
2118     ASSERT_GL_NO_ERROR();
2119 
2120     GLTexture resolveDrawTexture;
2121     glBindTexture(GL_TEXTURE_2D, resolveDrawTexture);
2122     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2123     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, resolveDrawTexture,
2124                            0);
2125     // Only enable color attachment 1 to be drawn to, since the Vulkan back end (currently) only
2126     // supports using resolve attachments when there is a single draw attachment enabled. This
2127     // ensures that the read and draw images are treated separately, including their layouts.
2128     GLenum drawBuffers[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
2129     glDrawBuffers(2, drawBuffers);
2130     ASSERT_GL_NO_ERROR();
2131     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2132 
2133     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2134     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2135     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2136     ASSERT_GL_NO_ERROR();
2137 
2138     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2139     glReadBuffer(GL_COLOR_ATTACHMENT1);
2140     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2141     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2142     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2143     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2144     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2145                       255, 1.0);
2146 }
2147 
2148 // Test resolving a multisampled texture into a mipmaped texture with blit
TEST_P(FramebufferTest_ES31,MultisampleResolveIntoMipMapWithBlit)2149 TEST_P(FramebufferTest_ES31, MultisampleResolveIntoMipMapWithBlit)
2150 {
2151     // FBO 1 is attached to a 64x64 texture
2152     // FBO 2 attached to level 1 of a 128x128 texture
2153 
2154     constexpr int kSize = 64;
2155     glViewport(0, 0, kSize, kSize);
2156 
2157     // Create the textures early and call glGenerateMipmap() so it doesn't break the render pass
2158     // between the drawQuad() and glBlitFramebuffer(), so we can test the resolve with subpass path
2159     // in the Vulkan back end.
2160     GLTexture texture;
2161     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
2162     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2163     ASSERT_GL_NO_ERROR();
2164 
2165     GLTexture resolveTexture;
2166     glBindTexture(GL_TEXTURE_2D, resolveTexture);
2167     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2168     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
2169     ASSERT_GL_NO_ERROR();
2170 
2171     GLFramebuffer msaaFBO;
2172     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2173     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2174                            texture.get(), 0);
2175     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2176 
2177     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2178                      essl31_shaders::fs::RedGreenGradient());
2179     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2180     ASSERT_GL_NO_ERROR();
2181 
2182     // Create another FBO to resolve the multisample buffer into.
2183     GLFramebuffer resolveFBO;
2184     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2185     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
2186     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2187 
2188     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2189     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2190     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2191     ASSERT_GL_NO_ERROR();
2192 
2193     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2194     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2195     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2196     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2197     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2198     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2199                       255, 1.0);
2200 }
2201 
2202 // Test resolving a multisampled texture with blit after drawing to multiple FBOs.
TEST_P(FramebufferTest_ES31,MultipleTextureMultisampleResolveWithBlitMultipleResolves)2203 TEST_P(FramebufferTest_ES31, MultipleTextureMultisampleResolveWithBlitMultipleResolves)
2204 {
2205     // Attach two MSAA textures to FBO1
2206     // Set read buffer 0
2207     // Resolve into FBO2
2208     // Set read buffer 1
2209     // Resolve into FBO3
2210 
2211     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
2212 
2213     constexpr int kSize = 16;
2214     glViewport(0, 0, kSize, kSize);
2215 
2216     GLFramebuffer msaaFBO;
2217     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2218 
2219     GLTexture msaaTextureRed;
2220     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed.get());
2221     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2222     ASSERT_GL_NO_ERROR();
2223     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2224                            msaaTextureRed.get(), 0);
2225     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2226 
2227     GLTexture msaaTextureGreen;
2228     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen.get());
2229     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2230     ASSERT_GL_NO_ERROR();
2231     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
2232                            msaaTextureGreen.get(), 0);
2233     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2234 
2235     // Setup program to render red into attachment 0 and green into attachment 1.
2236     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
2237     glUseProgram(program);
2238     constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
2239     glDrawBuffers(2, kDrawBuffers);
2240 
2241     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2242     ASSERT_GL_NO_ERROR();
2243 
2244     // Create another FBO to resolve the multisample buffer into.
2245     GLTexture resolveTexture1;
2246     GLFramebuffer resolveFBO1;
2247     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
2248     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2249     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
2250     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
2251     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2252 
2253     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2254     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
2255     glReadBuffer(GL_COLOR_ATTACHMENT0);  // Red
2256     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2257     ASSERT_GL_NO_ERROR();
2258 
2259     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
2260     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2261 
2262     // Create another FBO to resolve the multisample buffer into.
2263     GLTexture resolveTexture2;
2264     GLFramebuffer resolveFBO2;
2265     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
2266     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2267     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
2268     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
2269     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2270 
2271     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2272     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
2273     glReadBuffer(GL_COLOR_ATTACHMENT1);  // Green
2274     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2275     ASSERT_GL_NO_ERROR();
2276 
2277     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
2278     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2279 }
2280 
2281 // Test resolving a multisampled texture with blit after drawing to multiple FBOs, with color
2282 // attachment 1 resolved first.
TEST_P(FramebufferTest_ES31,MultipleTextureMultisampleResolveWithBlitMultipleResolvesAttachment1First)2283 TEST_P(FramebufferTest_ES31,
2284        MultipleTextureMultisampleResolveWithBlitMultipleResolvesAttachment1First)
2285 {
2286     // Attach two MSAA textures to FBO1
2287     // Set read buffer 1
2288     // Resolve into FBO2
2289     // Set read buffer 0
2290     // Resolve into FBO3
2291 
2292     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
2293 
2294     constexpr int kSize = 16;
2295     glViewport(0, 0, kSize, kSize);
2296 
2297     GLFramebuffer msaaFBO;
2298     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2299 
2300     GLTexture msaaTextureRed;
2301     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed.get());
2302     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2303     ASSERT_GL_NO_ERROR();
2304     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2305                            msaaTextureRed.get(), 0);
2306     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2307 
2308     GLTexture msaaTextureGreen;
2309     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen.get());
2310     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2311     ASSERT_GL_NO_ERROR();
2312     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
2313                            msaaTextureGreen.get(), 0);
2314     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2315 
2316     // Setup program to render red into attachment 0 and green into attachment 1.
2317     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
2318     glUseProgram(program);
2319     constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
2320     glDrawBuffers(2, kDrawBuffers);
2321 
2322     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2323     ASSERT_GL_NO_ERROR();
2324 
2325     // Create another FBO to resolve the multisample buffer into.
2326     GLTexture resolveTexture1;
2327     GLFramebuffer resolveFBO1;
2328     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
2329     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2330     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
2331     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
2332     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2333 
2334     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2335     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
2336     glReadBuffer(GL_COLOR_ATTACHMENT1);  // Green
2337     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2338     ASSERT_GL_NO_ERROR();
2339 
2340     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
2341     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2342 
2343     // Create another FBO to resolve the multisample buffer into.
2344     GLTexture resolveTexture2;
2345     GLFramebuffer resolveFBO2;
2346     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
2347     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2348     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
2349     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
2350     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2351 
2352     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2353     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
2354     glReadBuffer(GL_COLOR_ATTACHMENT0);  // Red
2355     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2356     ASSERT_GL_NO_ERROR();
2357 
2358     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
2359     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2360 }
2361 
2362 // Test resolving a multisampled texture with blit, then drawing multisampled again.  The latter
2363 // should not get re-resolved automatically.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDraw)2364 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDraw)
2365 {
2366     constexpr int kSize = 16;
2367     glViewport(0, 0, kSize, kSize);
2368 
2369     GLFramebuffer msaaFBO;
2370     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2371 
2372     GLTexture texture;
2373     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
2374     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2375     ASSERT_GL_NO_ERROR();
2376     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2377                            texture.get(), 0);
2378     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2379 
2380     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2381                      essl31_shaders::fs::RedGreenGradient());
2382     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2383     ASSERT_GL_NO_ERROR();
2384 
2385     // Create another FBO to resolve the multisample buffer into.
2386     GLTexture resolveTexture;
2387     GLFramebuffer resolveFBO;
2388     glBindTexture(GL_TEXTURE_2D, resolveTexture);
2389     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2390     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2391     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2392     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2393 
2394     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2395     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2396     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2397     ASSERT_GL_NO_ERROR();
2398 
2399     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2400     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2401     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2402     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2403     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2404     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2405                       255, 1.0);
2406 
2407     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
2408     ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
2409     drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2410     ASSERT_GL_NO_ERROR();
2411 
2412     // The resolved FBO should be unaffected by the last draw call.
2413     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2414     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2415     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2416     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2417                       255, 1.0);
2418 }
2419 
2420 // Test resolving a multisampled texture with blit, then drawing multisampled again.  The latter
2421 // should not get re-resolved automatically.  Resoloves color attachment 1.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDrawAttachment1)2422 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawAttachment1)
2423 {
2424     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
2425 
2426     constexpr int kSize = 16;
2427     glViewport(0, 0, kSize, kSize);
2428 
2429     GLFramebuffer msaaFBO;
2430     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2431 
2432     GLTexture msaaTextureRed;
2433     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed.get());
2434     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2435     ASSERT_GL_NO_ERROR();
2436     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2437                            msaaTextureRed.get(), 0);
2438     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2439 
2440     GLTexture msaaTextureGreen;
2441     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen.get());
2442     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2443     ASSERT_GL_NO_ERROR();
2444     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
2445                            msaaTextureGreen.get(), 0);
2446     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2447 
2448     // Setup program to render red into attachment 0 and green into attachment 1.
2449     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
2450     glUseProgram(program);
2451     constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
2452     glDrawBuffers(2, kDrawBuffers);
2453 
2454     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2455     ASSERT_GL_NO_ERROR();
2456 
2457     // Create another FBO to resolve the multisample buffer into.
2458     GLTexture resolveTexture;
2459     GLFramebuffer resolveFBO;
2460     glBindTexture(GL_TEXTURE_2D, resolveTexture);
2461     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2462     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2463     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2464     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2465 
2466     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2467     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2468     glReadBuffer(GL_COLOR_ATTACHMENT1);  // Green
2469     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2470     ASSERT_GL_NO_ERROR();
2471 
2472     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2473     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2474     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
2475     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
2476     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
2477 
2478     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
2479     ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
2480     drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2481     ASSERT_GL_NO_ERROR();
2482 
2483     // The resolved FBO should be unaffected by the last draw call.
2484     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2485     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
2486     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
2487     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
2488 }
2489 
2490 // Test resolving a multisampled texture with blit, then drawing multisampled again and resolving to
2491 // same framebuffer.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDrawThenResolveAgain)2492 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawThenResolveAgain)
2493 {
2494     constexpr int kSize = 16;
2495     glViewport(0, 0, kSize, kSize);
2496 
2497     GLFramebuffer msaaFBO;
2498     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2499 
2500     GLTexture texture;
2501     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
2502     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2503     ASSERT_GL_NO_ERROR();
2504     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2505                            texture.get(), 0);
2506     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2507 
2508     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2509                      essl31_shaders::fs::RedGreenGradient());
2510     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2511     ASSERT_GL_NO_ERROR();
2512 
2513     // Create another FBO to resolve the multisample buffer into.
2514     GLTexture resolveTexture;
2515     GLFramebuffer resolveFBO;
2516     glBindTexture(GL_TEXTURE_2D, resolveTexture);
2517     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2518     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
2519     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
2520     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2521 
2522     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2523     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2524     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2525     ASSERT_GL_NO_ERROR();
2526 
2527     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2528     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2529     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2530     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2531     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2532     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2533                       255, 1.0);
2534 
2535     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
2536     ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
2537     drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2538     ASSERT_GL_NO_ERROR();
2539 
2540     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2541     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
2542     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2543     ASSERT_GL_NO_ERROR();
2544 
2545     // Verify that the resolve happened correctly
2546     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
2547     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2548     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
2549     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
2550     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
2551 }
2552 
2553 // Test resolving a multisampled texture with blit, then drawing multisampled again and resolving to
2554 // another framebuffer.
TEST_P(FramebufferTest_ES31,MultisampleResolveWithBlitThenDrawThenResolveAgainToDifferentFBO)2555 TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawThenResolveAgainToDifferentFBO)
2556 {
2557     constexpr int kSize = 16;
2558     glViewport(0, 0, kSize, kSize);
2559 
2560     GLFramebuffer msaaFBO;
2561     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
2562 
2563     GLTexture texture;
2564     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
2565     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
2566     ASSERT_GL_NO_ERROR();
2567     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
2568                            texture.get(), 0);
2569     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2570 
2571     ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
2572                      essl31_shaders::fs::RedGreenGradient());
2573     drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2574     ASSERT_GL_NO_ERROR();
2575 
2576     // Create another FBO to resolve the multisample buffer into.
2577     GLTexture resolveTexture1;
2578     GLFramebuffer resolveFBO1;
2579     glBindTexture(GL_TEXTURE_2D, resolveTexture1);
2580     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2581     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
2582     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
2583     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2584 
2585     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2586     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
2587     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2588     ASSERT_GL_NO_ERROR();
2589 
2590     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
2591     constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
2592     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2593     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2594     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2595     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2596                       255, 1.0);
2597 
2598     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
2599     ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
2600     drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2601     ASSERT_GL_NO_ERROR();
2602 
2603     // Create another FBO to resolve the multisample buffer into.
2604     GLTexture resolveTexture2;
2605     GLFramebuffer resolveFBO2;
2606     glBindTexture(GL_TEXTURE_2D, resolveTexture2);
2607     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2608     glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
2609     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
2610     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2611 
2612     glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
2613     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
2614     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2615     ASSERT_GL_NO_ERROR();
2616 
2617     // Verify that the resolve happened to the correct FBO
2618     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
2619     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2620     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
2621     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
2622     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
2623 
2624     // The first resolve FBO should be untouched.
2625     glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
2626     EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2627     EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
2628     EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
2629     EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0,
2630                       255, 1.0);
2631 }
2632 
2633 // If there are no attachments, rendering will be limited to a rectangle having a lower left of
2634 // (0, 0) and an upper right of(width, height), where width and height are the framebuffer
2635 // object's default width and height.
TEST_P(FramebufferTest_ES31,RenderingLimitToDefaultFBOSizeWithNoAttachments)2636 TEST_P(FramebufferTest_ES31, RenderingLimitToDefaultFBOSizeWithNoAttachments)
2637 {
2638     // anglebug.com/2253
2639     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
2640     // Occlusion query reports fragments outside the render area are still rendered
2641     ANGLE_SKIP_TEST_IF(IsAndroid() || (IsWindows() && (IsIntel() || IsAMD())));
2642 
2643     constexpr char kVS1[] = R"(#version 310 es
2644 in layout(location = 0) highp vec2 a_position;
2645 void main()
2646 {
2647     gl_Position = vec4(a_position, 0.0, 1.0);
2648 })";
2649 
2650     constexpr char kFS1[] = R"(#version 310 es
2651 uniform layout(location = 0) highp ivec2 u_expectedSize;
2652 out layout(location = 3) mediump vec4 f_color;
2653 void main()
2654 {
2655     if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
2656     f_color = vec4(1.0, 0.5, 0.25, 1.0);
2657 })";
2658 
2659     constexpr char kVS2[] = R"(#version 310 es
2660 in layout(location = 0) highp vec2 a_position;
2661 void main()
2662 {
2663     gl_Position = vec4(a_position, 0.0, 1.0);
2664 })";
2665 
2666     constexpr char kFS2[] = R"(#version 310 es
2667 uniform layout(location = 0) highp ivec2 u_expectedSize;
2668 out layout(location = 2) mediump vec4 f_color;
2669 void main()
2670 {
2671     if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
2672     f_color = vec4(1.0, 0.5, 0.25, 1.0);
2673 })";
2674 
2675     ANGLE_GL_PROGRAM(program1, kVS1, kFS1);
2676     ANGLE_GL_PROGRAM(program2, kVS2, kFS2);
2677 
2678     glUseProgram(program1);
2679 
2680     GLFramebuffer mFramebuffer;
2681     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
2682     GLuint defaultWidth  = 1;
2683     GLuint defaultHeight = 1;
2684 
2685     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
2686     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
2687     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2688 
2689     const float data[] = {
2690         1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
2691     };
2692 
2693     GLuint vertexArray  = 0;
2694     GLuint vertexBuffer = 0;
2695     GLuint query        = 0;
2696     GLuint passedCount  = 0;
2697 
2698     glGenQueries(1, &query);
2699     glGenVertexArrays(1, &vertexArray);
2700     glBindVertexArray(vertexArray);
2701 
2702     glGenBuffers(1, &vertexBuffer);
2703     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2704     glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2705 
2706     glEnableVertexAttribArray(0);
2707     glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
2708     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2709 
2710     validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
2711 
2712     glUseProgram(program2);
2713     validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
2714 
2715     glUseProgram(program1);
2716     // If fbo has attachments, the rendering size should be the same as its attachment.
2717     GLTexture mTexture;
2718     GLuint width  = 2;
2719     GLuint height = 2;
2720     glBindTexture(GL_TEXTURE_2D, mTexture.get());
2721     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
2722 
2723     const GLenum bufs[] = {GL_NONE, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT3};
2724 
2725     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, mTexture.get(),
2726                            0);
2727     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2728     glDrawBuffers(4, bufs);
2729 
2730     validateSamplePass(query, passedCount, width, height);
2731 
2732     // If fbo's attachment has been removed, the rendering size should be the same as framebuffer
2733     // default size.
2734     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, 0, 0, 0);
2735     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
2736 
2737     validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
2738 
2739     glDisableVertexAttribArray(0);
2740     glBindBuffer(GL_ARRAY_BUFFER, 0);
2741     glBindVertexArray(0);
2742     glDeleteBuffers(1, &vertexBuffer);
2743     glDeleteVertexArrays(1, &vertexArray);
2744 
2745     ASSERT_GL_NO_ERROR();
2746 }
2747 
2748 class AddMockTextureNoRenderTargetTest : public ANGLETest
2749 {
2750   public:
AddMockTextureNoRenderTargetTest()2751     AddMockTextureNoRenderTargetTest()
2752     {
2753         setWindowWidth(512);
2754         setWindowHeight(512);
2755         setConfigRedBits(8);
2756         setConfigGreenBits(8);
2757         setConfigBlueBits(8);
2758         setConfigAlphaBits(8);
2759     }
2760 
overrideWorkaroundsD3D(FeaturesD3D * features)2761     void overrideWorkaroundsD3D(FeaturesD3D *features) override
2762     {
2763         features->overrideFeatures({"add_mock_texture_no_render_target"}, true);
2764     }
2765 };
2766 
2767 // Test to verify workaround succeeds when no program outputs exist http://anglebug.com/2283
TEST_P(AddMockTextureNoRenderTargetTest,NoProgramOutputWorkaround)2768 TEST_P(AddMockTextureNoRenderTargetTest, NoProgramOutputWorkaround)
2769 {
2770     constexpr char kVS[] = "void main() {}";
2771     constexpr char kFS[] = "void main() {}";
2772 
2773     ANGLE_GL_PROGRAM(drawProgram, kVS, kFS);
2774 
2775     glUseProgram(drawProgram);
2776 
2777     glDrawArrays(GL_TRIANGLES, 0, 6);
2778 
2779     ASSERT_GL_NO_ERROR();
2780 }
2781 
2782 // Covers a bug in ANGLE's Vulkan back-end framebuffer cache which ignored depth/stencil after
2783 // calls to DrawBuffers.
TEST_P(FramebufferTest_ES3,AttachmentStateChange)2784 TEST_P(FramebufferTest_ES3, AttachmentStateChange)
2785 {
2786     constexpr GLuint kSize = 2;
2787 
2788     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2789 
2790     GLTexture colorTexture;
2791     glBindTexture(GL_TEXTURE_2D, colorTexture);
2792     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2793 
2794     GLFramebuffer fbo;
2795     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2796     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
2797 
2798     ASSERT_GL_NO_ERROR();
2799     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2800 
2801     // First draw without a depth buffer.
2802     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2803 
2804     GLRenderbuffer depthBuffer;
2805     glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
2806     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kSize, kSize);
2807 
2808     // Bind just a renderbuffer and draw.
2809     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
2810 
2811     ASSERT_GL_NO_ERROR();
2812     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2813 
2814     glDrawBuffers(0, nullptr);
2815     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2816 
2817     // Re-enable color buffer and draw one final time. This previously triggered a crash.
2818     GLenum drawBuffs = {GL_COLOR_ATTACHMENT0};
2819     glDrawBuffers(1, &drawBuffs);
2820 
2821     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2822     ASSERT_GL_NO_ERROR();
2823     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2824 }
2825 
2826 // Tests that we can support a feedback loop between a depth textures and the depth buffer.
2827 // The test emulates the read-only feedback loop in Manhattan.
TEST_P(FramebufferTest_ES3,ReadOnlyDepthFeedbackLoopSupported)2828 TEST_P(FramebufferTest_ES3, ReadOnlyDepthFeedbackLoopSupported)
2829 {
2830     // Feedback loops are only supported on Vulkan.
2831     // TODO(jmadill): Make GL extension. http://anglebug.com/4969
2832     ANGLE_SKIP_TEST_IF(!IsVulkan());
2833 
2834     constexpr GLuint kSize = 2;
2835     glViewport(0, 0, kSize, kSize);
2836 
2837     constexpr char kFS[] = R"(precision mediump float;
2838 varying vec2 v_texCoord;
2839 uniform sampler2D depth;
2840 void main()
2841 {
2842     if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
2843     {
2844         gl_FragColor = vec4(0, 1, 0, 1);
2845     }
2846     else
2847     {
2848         gl_FragColor = vec4(1, 0, 0, 1);
2849     }
2850 })";
2851 
2852     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
2853 
2854     GLFramebuffer framebuffer;
2855     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
2856 
2857     GLTexture colorTexture;
2858     glBindTexture(GL_TEXTURE_2D, colorTexture);
2859     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2860 
2861     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2862     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2863     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
2864 
2865     GLTexture depthTexture;
2866     glBindTexture(GL_TEXTURE_2D, depthTexture);
2867     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
2868                  GL_UNSIGNED_INT, nullptr);
2869     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2870     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2871     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
2872 
2873     ASSERT_GL_NO_ERROR();
2874     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2875 
2876     // Clear depth to 0.5.
2877     glClearDepthf(0.5f);
2878     glClear(GL_DEPTH_BUFFER_BIT);
2879 
2880     // Disable depth. Although this does not remove the feedback loop as defined by the
2881     // spec it mimics what gfxbench does in its rendering tests.
2882     glDepthMask(false);
2883     glDisable(GL_DEPTH_TEST);
2884 
2885     // Verify we can sample the depth texture and get 0.5.
2886     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
2887 
2888     ASSERT_GL_NO_ERROR();
2889     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2890 }
2891 
2892 // Tests corner cases with read-only depth-stencil feedback loops.
TEST_P(FramebufferTest_ES3,ReadOnlyDepthFeedbackLoopStateChanges)2893 TEST_P(FramebufferTest_ES3, ReadOnlyDepthFeedbackLoopStateChanges)
2894 {
2895     // Feedback loops are only supported on Vulkan.
2896     // TODO(jmadill): Make GL extension. http://anglebug.com/4969
2897     ANGLE_SKIP_TEST_IF(!IsVulkan());
2898 
2899     constexpr GLuint kSize = 2;
2900     glViewport(0, 0, kSize, kSize);
2901 
2902     constexpr char kFS[] = R"(precision mediump float;
2903 varying vec2 v_texCoord;
2904 uniform sampler2D depth;
2905 void main()
2906 {
2907     if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
2908     {
2909         gl_FragColor = vec4(0, 1, 0, 1);
2910     }
2911     else
2912     {
2913         gl_FragColor = vec4(1, 0, 0, 1);
2914     }
2915 })";
2916 
2917     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
2918     glUseProgram(program);
2919 
2920     setupQuadVertexBuffer(0.5f, 1.0f);
2921     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
2922     glEnableVertexAttribArray(0);
2923 
2924     GLFramebuffer framebuffer1;
2925     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
2926 
2927     GLTexture colorTexture;
2928     glBindTexture(GL_TEXTURE_2D, colorTexture);
2929     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2930 
2931     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2932     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2933     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
2934 
2935     GLTexture depthTexture;
2936     glBindTexture(GL_TEXTURE_2D, depthTexture);
2937     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
2938                  GL_UNSIGNED_INT, nullptr);
2939     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2940     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2941     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
2942     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2943 
2944     GLFramebuffer framebuffer2;
2945     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
2946     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
2947     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2948 
2949     ASSERT_GL_NO_ERROR();
2950 
2951     // Clear depth to 0.5.
2952     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
2953     glClearDepthf(0.5f);
2954     glClear(GL_DEPTH_BUFFER_BIT);
2955     glFlush();
2956 
2957     // Disable depth. Although this does not remove the feedback loop as defined by the
2958     // spec it mimics what gfxbench does in its rendering tests.
2959     glDepthMask(false);
2960     glDisable(GL_DEPTH_TEST);
2961 
2962     // Draw with loop.
2963     glDrawArrays(GL_TRIANGLES, 0, 6);
2964     ASSERT_GL_NO_ERROR();
2965 
2966     // Draw with no loop and second FBO. Starts RP in writable mode.
2967     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
2968     glBindTexture(GL_TEXTURE_2D, 0);
2969     glDrawArrays(GL_TRIANGLES, 0, 6);
2970     ASSERT_GL_NO_ERROR();
2971 
2972     // Draw with loop, restarts RP.
2973     glBindTexture(GL_TEXTURE_2D, depthTexture);
2974     glDrawArrays(GL_TRIANGLES, 0, 6);
2975     ASSERT_GL_NO_ERROR();
2976 }
2977 
2978 // Tests that if the framebuffer is cleared, a feedback loop between a depth textures and the depth
2979 // buffer is established, and a scissored clear is issued, that the clear is not mistakenly
2980 // scissored.
TEST_P(FramebufferTest_ES3,ReadOnlyDepthFeedbackLoopWithClearAndScissoredDraw)2981 TEST_P(FramebufferTest_ES3, ReadOnlyDepthFeedbackLoopWithClearAndScissoredDraw)
2982 {
2983     // Feedback loops are only supported on Vulkan.
2984     // TODO(jmadill): Make GL extension. http://anglebug.com/4969
2985     ANGLE_SKIP_TEST_IF(!IsVulkan());
2986 
2987     constexpr GLuint kSize = 16;
2988     glViewport(0, 0, kSize, kSize);
2989 
2990     constexpr char kFS[] = R"(precision mediump float;
2991 varying vec2 v_texCoord;
2992 uniform sampler2D depth;
2993 void main()
2994 {
2995     if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
2996     {
2997         gl_FragColor = vec4(0, 1, 0, 1);
2998     }
2999     else
3000     {
3001         gl_FragColor = vec4(1, 0, 0, 1);
3002     }
3003 })";
3004 
3005     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
3006 
3007     GLFramebuffer framebuffer;
3008     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3009 
3010     GLTexture colorTexture;
3011     glBindTexture(GL_TEXTURE_2D, colorTexture);
3012     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3013 
3014     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3015     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3016     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3017 
3018     GLTexture depthTexture;
3019     glBindTexture(GL_TEXTURE_2D, depthTexture);
3020     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
3021                  GL_UNSIGNED_INT, nullptr);
3022     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3023     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3024     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
3025 
3026     ASSERT_GL_NO_ERROR();
3027     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3028 
3029     // Clear color to blue and depth to 0.5.
3030     glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
3031     glClearDepthf(0.5f);
3032     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3033 
3034     // Disable depth. Although this does not remove the feedback loop as defined by the
3035     // spec it mimics what gfxbench does in its rendering tests.
3036     glDepthMask(false);
3037     glDisable(GL_DEPTH_TEST);
3038 
3039     // Verify we can sample the depth texture and get 0.5.  Use a scissor.
3040     glScissor(0, 0, kSize / 2, kSize);
3041     glEnable(GL_SCISSOR_TEST);
3042     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3043     ASSERT_GL_NO_ERROR();
3044 
3045     // Make sure the scissored region passes the depth test and is changed to green.
3046     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3047     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
3048     EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, 0, GLColor::green);
3049     EXPECT_PIXEL_COLOR_EQ(kSize / 2 - 1, kSize - 1, GLColor::green);
3050 
3051     // Make sure the region outside the scissor is cleared to blue.
3052     EXPECT_PIXEL_COLOR_EQ(kSize / 2, 0, GLColor::blue);
3053     EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize - 1, GLColor::blue);
3054     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
3055     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
3056 }
3057 
3058 // Tests that we can support a color texture also attached to the color attachment but
3059 // with different LOD. From GLES3.0 spec section 4.4.3.2, if min_filter is GL_NEAREST_MIPMAP_NEAREST
3060 // and the lod is within the [base_level, max_level] range, and it is possible to sample from a LOD
3061 // that is rendering to then it does form a feedback loop. But if it is using textureLOD to
3062 // explicitly fetching texture on different LOD, there is no loop and should still work. Aztec_ruins
3063 // (https://issuetracker.google.com/175584609) is doing exactly this.
TEST_P(FramebufferTest_ES3,SampleFromAttachedTextureWithDifferentLOD)3064 TEST_P(FramebufferTest_ES3, SampleFromAttachedTextureWithDifferentLOD)
3065 {
3066     // TODO: https://anglebug.com/5760
3067     ANGLE_SKIP_TEST_IF(IsD3D());
3068 
3069     constexpr GLuint kLevel0Size = 4;
3070     constexpr GLuint kLevel1Size = kLevel0Size / 2;
3071     constexpr GLuint kLevel2Size = kLevel1Size / 2;
3072     std::array<GLColor, kLevel0Size * kLevel0Size> gData;
3073 
3074     GLTexture colorTexture;
3075     glBindTexture(GL_TEXTURE_2D, colorTexture);
3076     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3077     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3078     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kLevel0Size, kLevel0Size);
3079     gData.fill(GLColor::red);
3080     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
3081                     gData.data());
3082     gData.fill(GLColor::green);
3083     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
3084                     gData.data());
3085     gData.fill(GLColor::blue);
3086     glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, kLevel2Size, kLevel2Size, GL_RGBA, GL_UNSIGNED_BYTE,
3087                     gData.data());
3088 
3089     // Attach level 1 to a FBO
3090     GLFramebuffer framebuffer;
3091     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3092     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
3093     ASSERT_GL_NO_ERROR();
3094     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3095 
3096     // Render to FBO with color texture level 1 and textureLod from level 0.
3097     const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
3098     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
3099     glViewport(0, 0, kLevel1Size, kLevel1Size);
3100     glScissor(0, 0, kLevel1Size, kLevel1Size);
3101     glEnable(GL_CULL_FACE);
3102     glCullFace(GL_BACK);
3103     glDisable(GL_BLEND);
3104     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3105     glActiveTexture(GL_TEXTURE0);
3106     glBindTexture(GL_TEXTURE_2D, colorTexture);
3107 
3108     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
3109     glUseProgram(program);
3110     GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
3111     GLint lodLoc     = glGetUniformLocation(program, essl3_shaders::LodUniform());
3112     ASSERT_NE(-1, textureLoc);
3113     ASSERT_NE(-1, lodLoc);
3114     glUniform1i(textureLoc, 0);  // texture unit 0
3115     glUniform1f(lodLoc, 0);      // with Lod=0
3116     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3117 
3118     glDisable(GL_CULL_FACE);
3119     glDisable(GL_DEPTH_TEST);
3120     glDisable(GL_BLEND);
3121     glDisable(GL_SCISSOR_TEST);
3122     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3123 
3124     ASSERT_GL_NO_ERROR();
3125     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3126 }
3127 
3128 // This extends the test SampleFromAttachedTextureWithDifferentLOD by creating two renderpasses
3129 // without changing texture binding. This is to make sure that sample/render to the same texture
3130 // still function properly when transition from one renderpass to another without texture binding
3131 // change.
TEST_P(FramebufferTest_ES3,SampleFromAttachedTextureWithDifferentLODAndFBOSwitch)3132 TEST_P(FramebufferTest_ES3, SampleFromAttachedTextureWithDifferentLODAndFBOSwitch)
3133 {
3134     // TODO: https://anglebug.com/5760
3135     ANGLE_SKIP_TEST_IF(IsD3D());
3136 
3137     constexpr GLuint kLevel0Size = 4;
3138     constexpr GLuint kLevel1Size = kLevel0Size / 2;
3139     constexpr GLuint kLevel2Size = kLevel1Size / 2;
3140     std::array<GLColor, kLevel0Size * kLevel0Size> gData;
3141 
3142     GLTexture colorTexture;
3143     glBindTexture(GL_TEXTURE_2D, colorTexture);
3144     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3145     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3146     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kLevel0Size, kLevel0Size);
3147     gData.fill(GLColor::red);
3148     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
3149                     gData.data());
3150     gData.fill(GLColor::green);
3151     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
3152                     gData.data());
3153     gData.fill(GLColor::blue);
3154     glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, kLevel2Size, kLevel2Size, GL_RGBA, GL_UNSIGNED_BYTE,
3155                     gData.data());
3156 
3157     // Attach level 1 to two FBOs
3158     GLFramebuffer framebuffer1;
3159     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
3160     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
3161     ASSERT_GL_NO_ERROR();
3162     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3163     GLFramebuffer framebuffer2;
3164     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
3165     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
3166     ASSERT_GL_NO_ERROR();
3167     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3168 
3169     // Render to left half of FBO1 and textureLod from level 0.
3170     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
3171     glViewport(0, 0, kLevel1Size / 2, kLevel1Size);
3172     glScissor(0, 0, kLevel1Size / 2, kLevel1Size);
3173     glActiveTexture(GL_TEXTURE0);
3174     glBindTexture(GL_TEXTURE_2D, colorTexture);
3175     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
3176     glUseProgram(program);
3177     GLint textureLoc = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
3178     GLint lodLoc     = glGetUniformLocation(program, essl3_shaders::LodUniform());
3179     ASSERT_NE(-1, textureLoc);
3180     ASSERT_NE(-1, lodLoc);
3181     glUniform1i(textureLoc, 0);  // texture unit 0
3182     glUniform1f(lodLoc, 0);      // with Lod=0
3183     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3184     ASSERT_GL_NO_ERROR();
3185 
3186     // Render to right half of FBO2 and textureLod from level 0 without trigger texture binding
3187     // change.
3188     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
3189     glViewport(kLevel1Size / 2, 0, kLevel1Size / 2, kLevel1Size);
3190     glScissor(kLevel1Size / 2, 0, kLevel1Size / 2, kLevel1Size);
3191     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3192     ASSERT_GL_NO_ERROR();
3193     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3194     EXPECT_PIXEL_COLOR_EQ(kLevel1Size - 1, 0, GLColor::red);
3195 }
3196 
3197 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
3198 // renders to an immutable texture at the level that is bigger than GL_TEXTURE_MAX_LEVEL. The
3199 // texture itself has not been initialized with any data before rendering (TexSubImage call may
3200 // initialize a VkImage object).
TEST_P(FramebufferTest_ES3,RenderAndInvalidateImmutableTextureWithBeyondMaxLevel)3201 TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithBeyondMaxLevel)
3202 {
3203     constexpr GLuint kLevel0Size = 4;
3204     constexpr GLuint kLevel1Size = kLevel0Size / 2;
3205 
3206     GLTexture colorTexture;
3207     glBindTexture(GL_TEXTURE_2D, colorTexture);
3208     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3209     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3210     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
3211     // set max_level to 0
3212     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
3213 
3214     // Attach level 1 to a FBO
3215     GLFramebuffer framebuffer;
3216     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3217     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
3218     ASSERT_GL_NO_ERROR();
3219     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3220 
3221     // Render to FBO
3222     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3223     const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
3224     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
3225     glViewport(0, 0, kLevel1Size, kLevel1Size);
3226     glScissor(0, 0, kLevel1Size, kLevel1Size);
3227     glEnable(GL_CULL_FACE);
3228     glCullFace(GL_BACK);
3229     glDisable(GL_BLEND);
3230     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3231     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
3232     glUseProgram(program);
3233     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3234 
3235     glDisable(GL_CULL_FACE);
3236     glDisable(GL_DEPTH_TEST);
3237     glDisable(GL_BLEND);
3238     glDisable(GL_SCISSOR_TEST);
3239     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3240 
3241     ASSERT_GL_NO_ERROR();
3242     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3243 }
3244 
3245 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
3246 // renders to an immutable texture at the level that is bigger than GL_TEXTURE_MAX_LEVEL. The
3247 // texture itself has been initialized with data before rendering.
TEST_P(FramebufferTest_ES3,RenderAndInvalidateImmutableTextureWithSubImageWithBeyondMaxLevel)3248 TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithSubImageWithBeyondMaxLevel)
3249 {
3250     constexpr GLuint kLevel0Size = 4;
3251     constexpr GLuint kLevel1Size = kLevel0Size / 2;
3252     std::array<GLColor, kLevel0Size * kLevel0Size> gData;
3253 
3254     GLTexture colorTexture;
3255     glBindTexture(GL_TEXTURE_2D, colorTexture);
3256     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3257     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3258     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
3259     // set max_level to 0
3260     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
3261     // Initialize with TexSubImage call
3262     gData.fill(GLColor::blue);
3263     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
3264                     gData.data());
3265 
3266     // Attach level 1 to a FBO
3267     GLFramebuffer framebuffer;
3268     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3269     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
3270     ASSERT_GL_NO_ERROR();
3271     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3272 
3273     // Render to FBO
3274     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3275     const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
3276     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
3277     glViewport(0, 0, kLevel1Size, kLevel1Size);
3278     glScissor(0, 0, kLevel1Size, kLevel1Size);
3279     glEnable(GL_CULL_FACE);
3280     glCullFace(GL_BACK);
3281     glDisable(GL_BLEND);
3282     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3283     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
3284     glUseProgram(program);
3285     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3286 
3287     glDisable(GL_CULL_FACE);
3288     glDisable(GL_DEPTH_TEST);
3289     glDisable(GL_BLEND);
3290     glDisable(GL_SCISSOR_TEST);
3291     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3292 
3293     ASSERT_GL_NO_ERROR();
3294     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3295 }
3296 
3297 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
3298 // renders to an immutable texture at the level that is smaller than GL_TEXTURE_BASE_LEVEL. The
3299 // texture itself has been initialized with data before rendering. Filament is using it this way
TEST_P(FramebufferTest_ES3,RenderAndInvalidateImmutableTextureWithBellowBaseLevelLOD)3300 TEST_P(FramebufferTest_ES3, RenderAndInvalidateImmutableTextureWithBellowBaseLevelLOD)
3301 {
3302     constexpr GLuint kLevel0Size = 4;
3303     constexpr GLuint kLevel1Size = kLevel0Size / 2;
3304     std::array<GLColor, kLevel0Size * kLevel0Size> gData;
3305 
3306     GLTexture colorTexture;
3307     glBindTexture(GL_TEXTURE_2D, colorTexture);
3308     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3309     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3310     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
3311     // set base_level to 1
3312     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
3313     gData.fill(GLColor::blue);
3314     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
3315                     gData.data());
3316 
3317     // Attach level 0 to a FBO
3318     GLFramebuffer framebuffer;
3319     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3320     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3321     ASSERT_GL_NO_ERROR();
3322     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3323 
3324     // Render to FBO
3325     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3326     const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
3327     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
3328     glViewport(0, 0, kLevel0Size, kLevel0Size);
3329     glScissor(0, 0, kLevel0Size, kLevel0Size);
3330     glEnable(GL_CULL_FACE);
3331     glCullFace(GL_BACK);
3332     glDisable(GL_BLEND);
3333     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3334     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
3335     glUseProgram(program);
3336     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
3337 
3338     glDisable(GL_CULL_FACE);
3339     glDisable(GL_DEPTH_TEST);
3340     glDisable(GL_BLEND);
3341     glDisable(GL_SCISSOR_TEST);
3342     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3343 
3344     ASSERT_GL_NO_ERROR();
3345     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3346 }
3347 
3348 // Test render to a texture level that is excluded from [base_level, max_level]. This specific test
3349 // renders to an immutable texture at the level that is bigger than GL_TEXTURE_MAX_LEVEL. The
3350 // texture level that we render to has been initialized with data before rendering. This test if
3351 // render to that level will get flush the level update even though it is outside [base, max]
3352 // levels.
TEST_P(FramebufferTest_ES3,RenderImmutableTextureWithSubImageWithBeyondMaxLevel)3353 TEST_P(FramebufferTest_ES3, RenderImmutableTextureWithSubImageWithBeyondMaxLevel)
3354 {
3355     // Set up program to sample from specific lod level.
3356     GLProgram textureLodProgram;
3357     textureLodProgram.makeRaster(essl3_shaders::vs::Texture2DLod(),
3358                                  essl3_shaders::fs::Texture2DLod());
3359     ASSERT(textureLodProgram.valid());
3360     glUseProgram(textureLodProgram);
3361 
3362     GLint textureLocation =
3363         glGetUniformLocation(textureLodProgram, essl3_shaders::Texture2DUniform());
3364     ASSERT_NE(-1, textureLocation);
3365     GLint lodLocation = glGetUniformLocation(textureLodProgram, essl3_shaders::LodUniform());
3366     ASSERT_NE(-1, lodLocation);
3367 
3368     constexpr GLuint kLevel0Size = 4;
3369     constexpr GLuint kLevel1Size = kLevel0Size / 2;
3370     std::array<GLColor, kLevel0Size * kLevel0Size> gData;
3371 
3372     GLTexture colorTexture;
3373     glBindTexture(GL_TEXTURE_2D, colorTexture);
3374     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3375     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3376     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, kLevel0Size, kLevel0Size);
3377     // Initialize level 0 with blue
3378     gData.fill(GLColor::blue);
3379     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kLevel0Size, kLevel0Size, GL_RGBA, GL_UNSIGNED_BYTE,
3380                     gData.data());
3381     // set max_level to 0
3382     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
3383     // Draw with level 0
3384     glUniform1f(lodLocation, 0);
3385     drawQuad(textureLodProgram, essl3_shaders::PositionAttrib(), 0.5f);
3386     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3387 
3388     // Initalize level 1 with green
3389     gData.fill(GLColor::green);
3390     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_RGBA, GL_UNSIGNED_BYTE,
3391                     gData.data());
3392     // Attach level 1 to a FBO
3393     GLFramebuffer framebuffer;
3394     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3395     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 1);
3396     ASSERT_GL_NO_ERROR();
3397     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3398     // Render to FBO (i.e. level 1) with Red and blend with existing texture level data
3399     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3400     glViewport(0, 0, kLevel1Size, kLevel1Size);
3401     glScissor(0, 0, kLevel1Size, kLevel1Size);
3402     glEnable(GL_CULL_FACE);
3403     glCullFace(GL_BACK);
3404     glEnable(GL_BLEND);
3405     glBlendFunc(GL_ONE, GL_ONE);
3406     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3407     ANGLE_GL_PROGRAM(redProgram, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
3408     glUseProgram(redProgram);
3409     drawQuad(redProgram, essl3_shaders::PositionAttrib(), 0.5f);
3410 
3411     glDisable(GL_CULL_FACE);
3412     glDisable(GL_DEPTH_TEST);
3413     glDisable(GL_BLEND);
3414     glDisable(GL_SCISSOR_TEST);
3415     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3416 
3417     ASSERT_GL_NO_ERROR();
3418     // Expect to see Red + Green, which is Yellow
3419     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
3420 }
3421 
3422 // Similar to the other RenderImmutableTexture*** tests, but test on depth attachment instead of
3423 // color attachment. This tests render to a depth texture level that is less than
3424 // GL_TEXTURE_BASE_LEVEL and sample from it at the same time.
TEST_P(FramebufferTest_ES3,RenderSampleDepthTextureWithExcludedLevel)3425 TEST_P(FramebufferTest_ES3, RenderSampleDepthTextureWithExcludedLevel)
3426 {
3427     // Set up program to copy depth texture's value to color.red.
3428     constexpr char kVS[] = R"(precision mediump float;
3429 attribute vec4 a_position;
3430 varying vec2 v_texCoord;
3431 void main()
3432 {
3433     gl_Position = a_position;
3434     v_texCoord = a_position.xy * 0.5 + vec2(0.5);
3435 })";
3436     constexpr char kFS[] = R"(precision mediump float;
3437 varying vec2 v_texCoord;
3438 uniform sampler2D depth;
3439 void main()
3440 {
3441     gl_FragColor = vec4(texture2D(depth, v_texCoord).x, 1, 0, 1);
3442 })";
3443     ANGLE_GL_PROGRAM(program, kVS, kFS);
3444 
3445     constexpr GLuint kLevel0Size = 4;
3446     constexpr GLuint kLevel1Size = kLevel0Size / 2;
3447 
3448     GLTexture colorTexture;
3449     glBindTexture(GL_TEXTURE_2D, colorTexture);
3450     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3451     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3452     glTexStorage2D(GL_TEXTURE_2D, 3, GL_RGBA8, kLevel0Size, kLevel0Size);
3453 
3454     GLTexture depthTexture;
3455     glBindTexture(GL_TEXTURE_2D, depthTexture);
3456     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3457     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3458     glTexStorage2D(GL_TEXTURE_2D, 3, GL_DEPTH_COMPONENT32F, kLevel0Size, kLevel0Size);
3459     // Initialize level 1 with known depth value
3460     std::array<GLfloat, kLevel1Size *kLevel1Size> gData = {0.2, 0.4, 0.6, 0.8};
3461     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kLevel1Size, kLevel1Size, GL_DEPTH_COMPONENT, GL_FLOAT,
3462                     gData.data());
3463     // set base_level and max_level to 1, exclude level 0
3464     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
3465     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
3466 
3467     // Attach level 0 to a FBO
3468     GLFramebuffer framebuffer;
3469     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3470     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
3471     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
3472     ASSERT_GL_NO_ERROR();
3473     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3474 
3475     // Render to FBO (LOD 0) with depth texture LOD 1
3476     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3477     glViewport(0, 0, kLevel0Size, kLevel0Size);
3478     glScissor(0, 0, kLevel0Size, kLevel0Size);
3479     glDepthMask(GL_TRUE);
3480     glEnable(GL_DEPTH_TEST);
3481     glDepthFunc(GL_ALWAYS);
3482     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3483     ASSERT_GL_NO_ERROR();
3484     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(51u, 255u, 0, 255u), 1);
3485     EXPECT_PIXEL_COLOR_NEAR(kLevel0Size - 1, 0, GLColor(102u, 255u, 0, 255u), 1);
3486     EXPECT_PIXEL_COLOR_NEAR(0, kLevel0Size - 1, GLColor(153u, 255u, 0, 255u), 1);
3487     EXPECT_PIXEL_COLOR_NEAR(kLevel0Size - 1, kLevel0Size - 1, GLColor(204u, 255u, 0, 255u), 1);
3488 
3489     // Now check depth value is 0.5
3490     glDepthFunc(GL_LESS);
3491     glDepthMask(GL_FALSE);
3492     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3493     glUseProgram(blueProgram);
3494     // should fail depth test
3495     drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.51f);
3496     ASSERT_GL_NO_ERROR();
3497     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(51u, 255u, 0, 255u), 1);
3498     // should pass depth test
3499     drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.49f);
3500     ASSERT_GL_NO_ERROR();
3501     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3502 }
3503 
3504 // Covers a bug in ANGLE's Vulkan back-end. Our VkFramebuffer cache would in some cases forget to
3505 // check the draw states when computing a cache key.
TEST_P(FramebufferTest_ES3,DisabledAttachmentRedefinition)3506 TEST_P(FramebufferTest_ES3, DisabledAttachmentRedefinition)
3507 {
3508     constexpr GLuint kSize = 2;
3509 
3510     // Make a Framebuffer with two attachments with one enabled and one disabled.
3511     GLTexture texA, texB;
3512     glBindTexture(GL_TEXTURE_2D, texA);
3513     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3514     glBindTexture(GL_TEXTURE_2D, texB);
3515     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3516 
3517     GLFramebuffer fbo;
3518     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3519     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
3520     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texB, 0);
3521 
3522     // Mask out the second texture.
3523     constexpr GLenum kOneDrawBuf = GL_COLOR_ATTACHMENT0;
3524     glDrawBuffers(1, &kOneDrawBuf);
3525 
3526     ASSERT_GL_NO_ERROR();
3527     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3528 
3529     // Set up a very simple shader.
3530     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
3531     glViewport(0, 0, kSize, kSize);
3532 
3533     // Draw
3534     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3535     ASSERT_GL_NO_ERROR();
3536     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3537 
3538     // Update the masked out attachment and draw again.
3539     std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
3540     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
3541                     redPixels.data());
3542 
3543     // Draw
3544     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3545     ASSERT_GL_NO_ERROR();
3546     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3547 
3548     glReadBuffer(GL_COLOR_ATTACHMENT1);
3549     ASSERT_GL_NO_ERROR();
3550     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3551 }
3552 
3553 // Test that changing the attachment of a framebuffer then sync'ing both READ and DRAW framebuffer
3554 // (currently possible with glInvalidateFramebuffer) updates the scissor correctly.
TEST_P(FramebufferTest_ES3,ChangeAttachmentThenInvalidateAndDraw)3555 TEST_P(FramebufferTest_ES3, ChangeAttachmentThenInvalidateAndDraw)
3556 {
3557     constexpr GLsizei kSizeLarge = 32;
3558     constexpr GLsizei kSizeSmall = 16;
3559 
3560     GLTexture color1;
3561     glBindTexture(GL_TEXTURE_2D, color1);
3562     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeSmall, kSizeSmall, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3563                  nullptr);
3564 
3565     GLTexture color2;
3566     glBindTexture(GL_TEXTURE_2D, color2);
3567     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeLarge, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3568                  nullptr);
3569 
3570     GLFramebuffer fbo;
3571     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3572     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
3573 
3574     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3575     glUseProgram(drawColor);
3576     GLint colorUniformLocation =
3577         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3578     ASSERT_NE(colorUniformLocation, -1);
3579 
3580     glViewport(0, 0, kSizeLarge, kSizeLarge);
3581 
3582     // Draw red into the framebuffer.
3583     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3584     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3585     ASSERT_GL_NO_ERROR();
3586 
3587     // Change the attachment, invalidate it and draw green.
3588     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color2, 0);
3589     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3590 
3591     std::array<GLenum, 1> attachments = {GL_COLOR_ATTACHMENT0};
3592     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
3593     ASSERT_GL_NO_ERROR();
3594 
3595     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
3596     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3597     ASSERT_GL_NO_ERROR();
3598 
3599     // Validate the result.
3600     EXPECT_PIXEL_RECT_EQ(0, 0, kSizeLarge, kSizeLarge, GLColor::green);
3601 
3602     // Do the same, but changing from the large to small attachment.
3603 
3604     // Draw red into the framebuffer.
3605     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3606     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3607     ASSERT_GL_NO_ERROR();
3608 
3609     // Change the attachment, invalidate it and draw blue.
3610     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
3611     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3612     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
3613 
3614     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
3615     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3616     ASSERT_GL_NO_ERROR();
3617 
3618     // Validate the result.
3619     EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::blue);
3620 }
3621 
3622 // Test Framebuffer object with two attachments that have unequal size. In OpenGLES3.0, this is
3623 // a supported config. The common intersection area should be correctly rendered. The contents
3624 // outside common intersection area are undefined.
TEST_P(FramebufferTest_ES3,AttachmentsWithUnequalDimensions)3625 TEST_P(FramebufferTest_ES3, AttachmentsWithUnequalDimensions)
3626 {
3627     ANGLE_SKIP_TEST_IF(IsD3D());
3628 
3629     constexpr GLsizei kSizeLarge = 32;
3630     constexpr GLsizei kSizeSmall = 16;
3631 
3632     GLTexture colorTexture;
3633     glBindTexture(GL_TEXTURE_2D, colorTexture);
3634     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSizeLarge, kSizeSmall, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3635                  nullptr);
3636 
3637     GLRenderbuffer color;
3638     glBindRenderbuffer(GL_RENDERBUFFER, color);
3639     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSizeSmall, kSizeLarge);
3640 
3641     GLRenderbuffer depth;
3642     glBindRenderbuffer(GL_RENDERBUFFER, depth);
3643     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kSizeSmall, kSizeLarge);
3644 
3645     GLRenderbuffer stencil;
3646     glBindRenderbuffer(GL_RENDERBUFFER, stencil);
3647     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSizeSmall, kSizeLarge);
3648 
3649     struct
3650     {
3651         GLenum attachment;
3652         GLuint renderbuffer;
3653     } attachment2[4] = {{GL_COLOR_ATTACHMENT1, 0},
3654                         {GL_COLOR_ATTACHMENT1, color},
3655                         {GL_DEPTH_ATTACHMENT, depth},
3656                         {GL_STENCIL_ATTACHMENT, stencil}};
3657     for (int i = 0; i < 4; i++)
3658     {
3659         GLFramebuffer fbo;
3660         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3661         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture,
3662                                0);
3663         if (attachment2[i].renderbuffer)
3664         {
3665             glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment2[i].attachment, GL_RENDERBUFFER,
3666                                       attachment2[i].renderbuffer);
3667         }
3668         ASSERT_GL_NO_ERROR();
3669         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3670 
3671         ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3672         glUseProgram(drawColor);
3673         GLint colorUniformLocation =
3674             glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3675         ASSERT_NE(colorUniformLocation, -1);
3676 
3677         glViewport(0, 0, kSizeLarge, kSizeLarge);
3678         const GLenum discard[] = {GL_COLOR_ATTACHMENT0};
3679         glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discard);
3680 
3681         // Draw red into the framebuffer.
3682         glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3683         drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3684         ASSERT_GL_NO_ERROR();
3685 
3686         // Validate the result. The intersected common area should be red now
3687         EXPECT_PIXEL_RECT_EQ(0, 0, kSizeSmall, kSizeSmall, GLColor::red);
3688     }
3689 }
3690 
3691 class FramebufferTest : public ANGLETest
3692 {};
3693 
3694 template <typename T>
FillTexture2D(GLuint texture,GLsizei width,GLsizei height,const T & onePixelData,GLint level,GLint internalFormat,GLenum format,GLenum type)3695 void FillTexture2D(GLuint texture,
3696                    GLsizei width,
3697                    GLsizei height,
3698                    const T &onePixelData,
3699                    GLint level,
3700                    GLint internalFormat,
3701                    GLenum format,
3702                    GLenum type)
3703 {
3704     std::vector<T> allPixelsData(width * height, onePixelData);
3705 
3706     glBindTexture(GL_TEXTURE_2D, texture);
3707     glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
3708                  allPixelsData.data());
3709     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3710     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3711     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3712     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3713 }
3714 
3715 // Multi-context uses of textures should not cause rendering feedback loops.
TEST_P(FramebufferTest,MultiContextNoRenderingFeedbackLoops)3716 TEST_P(FramebufferTest, MultiContextNoRenderingFeedbackLoops)
3717 {
3718     constexpr char kTextureVS[] =
3719         R"(attribute vec4 a_position;
3720 varying vec2 v_texCoord;
3721 void main() {
3722     gl_Position = a_position;
3723     v_texCoord = (a_position.xy * 0.5) + 0.5;
3724 })";
3725 
3726     constexpr char kTextureFS[] =
3727         R"(precision mediump float;
3728 varying vec2 v_texCoord;
3729 uniform sampler2D u_texture;
3730 void main() {
3731     gl_FragColor = texture2D(u_texture, v_texCoord).rgba;
3732 })";
3733 
3734     ANGLE_GL_PROGRAM(textureProgram, kTextureVS, kTextureFS);
3735 
3736     glUseProgram(textureProgram.get());
3737     GLint uniformLoc = glGetUniformLocation(textureProgram.get(), "u_texture");
3738     ASSERT_NE(-1, uniformLoc);
3739     glUniform1i(uniformLoc, 0);
3740 
3741     GLTexture texture;
3742     FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
3743     glBindTexture(GL_TEXTURE_2D, texture.get());
3744     // Note that _texture_ is still bound to GL_TEXTURE_2D in this context at this point.
3745 
3746     EGLWindow *window          = getEGLWindow();
3747     EGLDisplay display         = window->getDisplay();
3748     EGLConfig config           = window->getConfig();
3749     EGLSurface surface         = window->getSurface();
3750     EGLint contextAttributes[] = {
3751         EGL_CONTEXT_MAJOR_VERSION_KHR,
3752         GetParam().majorVersion,
3753         EGL_CONTEXT_MINOR_VERSION_KHR,
3754         GetParam().minorVersion,
3755         EGL_NONE,
3756     };
3757     EGLContext context1 = eglGetCurrentContext();
3758     // Create context2, sharing resources with context1.
3759     EGLContext context2 = eglCreateContext(display, config, context1, contextAttributes);
3760     ASSERT_NE(context2, EGL_NO_CONTEXT);
3761     eglMakeCurrent(display, surface, surface, context2);
3762 
3763     constexpr char kVS[] =
3764         R"(attribute vec4 a_position;
3765 void main() {
3766     gl_Position = a_position;
3767 })";
3768 
3769     constexpr char kFS[] =
3770         R"(precision mediump float;
3771 void main() {
3772     gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
3773 })";
3774 
3775     ANGLE_GL_PROGRAM(program, kVS, kFS);
3776     glUseProgram(program.get());
3777 
3778     ASSERT_GL_NO_ERROR();
3779 
3780     // Render to the texture in context2.
3781     GLFramebuffer framebuffer;
3782     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
3783     // Texture is still a valid name in context2.
3784     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
3785     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3786     // There is no rendering feedback loop at this point.
3787 
3788     glDisable(GL_BLEND);
3789     glDisable(GL_DEPTH_TEST);
3790     ASSERT_GL_NO_ERROR();
3791 
3792     // If draw is no-op'ed, texture will not be filled appropriately.
3793     drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
3794     ASSERT_GL_NO_ERROR();
3795     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3796 
3797     // Make context1 current again.
3798     eglMakeCurrent(display, surface, surface, context1);
3799 
3800     // Render texture to screen.
3801     drawQuad(textureProgram.get(), "a_position", 0.5f, 1.0f, true);
3802     ASSERT_GL_NO_ERROR();
3803     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3804 
3805     eglDestroyContext(display, context2);
3806 }
3807 
3808 // Ensure cube-incomplete attachments cause incomplete Framebuffers.
TEST_P(FramebufferTest,IncompleteCubeMap)3809 TEST_P(FramebufferTest, IncompleteCubeMap)
3810 {
3811     constexpr GLuint kSize = 2;
3812 
3813     GLTexture srcTex;
3814     glBindTexture(GL_TEXTURE_CUBE_MAP, srcTex);
3815     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
3816                  GL_UNSIGNED_BYTE, nullptr);
3817 
3818     GLFramebuffer fbo;
3819     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3820     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
3821                            srcTex, 0);
3822 
3823     ASSERT_GL_NO_ERROR();
3824     ASSERT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
3825                      GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
3826 }
3827 
3828 // Test FBOs with different sizes are drawn correctly
TEST_P(FramebufferTest,BindAndDrawDifferentSizedFBOs)3829 TEST_P(FramebufferTest, BindAndDrawDifferentSizedFBOs)
3830 {
3831     // 1. Create FBO 1 with dimensions 16x16
3832     // 2. Draw red into FBO 1 (note, FramebufferVk::syncState is called)
3833     // 3. Create FBO 2 with dimensions 8x8
3834     // 4. Draw green into FBO 2 (note, FramebufferVk::syncState is called)
3835     // 5. Bind FBO 1 (note, it's not dirty)
3836     // 6. Draw blue into FBO 1
3837     // 7. Verify FBO 1 is entirely blue
3838 
3839     GLFramebuffer smallFbo;
3840     GLFramebuffer largeFbo;
3841     GLTexture smallTexture;
3842     GLTexture largeTexture;
3843     constexpr GLsizei kLargeWidth  = 16;
3844     constexpr GLsizei kLargeHeight = 16;
3845     constexpr GLsizei kSmallWidth  = 8;
3846     constexpr GLsizei kSmallHeight = 8;
3847 
3848     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3849     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
3850     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3851 
3852     // 1. Create FBO 1 with dimensions 16x16
3853     glBindFramebuffer(GL_FRAMEBUFFER, largeFbo);
3854     glBindTexture(GL_TEXTURE_2D, largeTexture);
3855     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kLargeWidth, kLargeHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3856                  nullptr);
3857     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3858     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3859     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
3860     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3861 
3862     // 2. Draw red into FBO 1 (note, FramebufferVk::syncState is called)
3863     glUseProgram(redProgram);
3864     drawQuad(redProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
3865     ASSERT_GL_NO_ERROR();
3866 
3867     // 3. Create FBO 2 with dimensions 8x8
3868     glBindFramebuffer(GL_FRAMEBUFFER, smallFbo);
3869     glBindTexture(GL_TEXTURE_2D, smallTexture);
3870     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallWidth, kSmallHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3871                  nullptr);
3872     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3873     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3874     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
3875     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3876 
3877     // 4. Draw green into FBO 2 (note, FramebufferVk::syncState is called)
3878     glUseProgram(greenProgram);
3879     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
3880     ASSERT_GL_NO_ERROR();
3881 
3882     // 5. Bind FBO 1 (note, it's not dirty)
3883     glBindFramebuffer(GL_FRAMEBUFFER, largeFbo);
3884 
3885     // 6. Draw blue into FBO 1
3886     glUseProgram(blueProgram);
3887     drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
3888     ASSERT_GL_NO_ERROR();
3889 
3890     // 7. Verify FBO 1 is entirely blue
3891     EXPECT_PIXEL_RECT_EQ(0, 0, kLargeWidth, kLargeHeight, GLColor::blue);
3892 }
3893 
3894 // Regression test based on a fuzzer failure.  A crash was encountered in the following situation:
3895 //
3896 // - Texture bound as sampler with MAX_LEVEL 0
3897 // - Framebuffer bound to level 0
3898 // - Draw
3899 // - Texture MAX_LEVEL changed to 1
3900 // - Framebuffer bound to level 1
3901 // - Draw
3902 //
3903 // Notes: Removing the first half removed the crash.  MIN_FILTERING of LINEAR vs
3904 // LINEAR_MIPMAP_LINEAR did not make any changes.
TEST_P(FramebufferTest_ES3,FramebufferBindToNewLevelAfterMaxIncreaseShouldntCrash)3905 TEST_P(FramebufferTest_ES3, FramebufferBindToNewLevelAfterMaxIncreaseShouldntCrash)
3906 {
3907     constexpr char kFS[] = R"(precision mediump float;
3908 uniform sampler2D u_tex0;
3909 void main() {
3910     gl_FragColor = texture2D(u_tex0, vec2(0));
3911 })";
3912 
3913     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), kFS);
3914     glUseProgram(program);
3915 
3916     GLTexture mutTex;
3917     glBindTexture(GL_TEXTURE_2D, mutTex);
3918     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3919     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 5, 5, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3920 
3921     GLFramebuffer fb;
3922     glBindFramebuffer(GL_FRAMEBUFFER, fb);
3923 
3924     // Attempt a draw with level 0 (feedback loop)
3925     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
3926     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3927 
3928     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mutTex, 0);
3929     glDrawArrays(GL_POINTS, 0, 1);
3930 
3931     // Attempt another draw with level 1.
3932     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
3933 
3934     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mutTex, 1);
3935 
3936     // This shouldn't crash.
3937     glDrawArrays(GL_POINTS, 0, 1);
3938     ASSERT_GL_NO_ERROR();
3939 }
3940 
3941 // Modify renderbuffer attachment samples after bind
TEST_P(FramebufferTest_ES3,BindRenderbufferThenModifySamples)3942 TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySamples)
3943 {
3944     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3945     glUseProgram(program);
3946     GLint colorUniformLocation =
3947         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
3948     ASSERT_NE(colorUniformLocation, -1);
3949 
3950     GLFramebuffer fbo;
3951     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3952 
3953     GLsizei size = 16;
3954     glViewport(0, 0, size, size);
3955 
3956     GLRenderbuffer color;
3957     glBindRenderbuffer(GL_RENDERBUFFER, color);
3958 
3959     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, size, size);
3960     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
3961     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
3962 
3963     glUniform4f(colorUniformLocation, 1, 0, 0, 1);
3964     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3965 
3966     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3967     ASSERT_GL_NO_ERROR();
3968 }
3969 
3970 // Modify renderbuffer attachment size after bind
TEST_P(FramebufferTest_ES3,BindRenderbufferThenModifySize)3971 TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySize)
3972 {
3973     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3974     glUseProgram(program);
3975     GLint colorUniformLocation =
3976         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
3977     ASSERT_NE(colorUniformLocation, -1);
3978 
3979     GLFramebuffer fbo;
3980     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3981 
3982     GLsizei size = 16;
3983     glViewport(0, 0, size, size);
3984 
3985     GLRenderbuffer color;
3986     glBindRenderbuffer(GL_RENDERBUFFER, color);
3987 
3988     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
3989     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
3990     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size / 2, size * 2);
3991 
3992     glUniform4f(colorUniformLocation, 1, 0, 0, 1);
3993     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3994 
3995     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3996     ASSERT_GL_NO_ERROR();
3997 }
3998 
3999 ANGLE_INSTANTIATE_TEST_ES2(AddMockTextureNoRenderTargetTest);
4000 ANGLE_INSTANTIATE_TEST_ES2(FramebufferTest);
4001 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
4002 
4003 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES3);
4004 ANGLE_INSTANTIATE_TEST_ES3_AND(FramebufferTest_ES3,
4005                                WithEmulatedPrerotation(ES3_VULKAN(), 90),
4006                                WithEmulatedPrerotation(ES3_VULKAN(), 180),
4007                                WithEmulatedPrerotation(ES3_VULKAN(), 270));
4008 
4009 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FramebufferTest_ES31);
4010 ANGLE_INSTANTIATE_TEST_ES31(FramebufferTest_ES31);
4011 ANGLE_INSTANTIATE_TEST_ES3(FramebufferTestWithFormatFallback);
4012