• 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 "platform/FeaturesD3D.h"
11 #include "test_utils/ANGLETest.h"
12 #include "test_utils/gl_raii.h"
13 
14 using namespace angle;
15 
16 namespace
17 {
18 
ExpectFramebufferCompleteOrUnsupported(GLenum binding)19 void ExpectFramebufferCompleteOrUnsupported(GLenum binding)
20 {
21     GLenum status = glCheckFramebufferStatus(binding);
22     EXPECT_TRUE(status == GL_FRAMEBUFFER_COMPLETE || status == GL_FRAMEBUFFER_UNSUPPORTED);
23 }
24 
25 }  // anonymous namespace
26 
27 class FramebufferFormatsTest : public ANGLETest
28 {
29   protected:
FramebufferFormatsTest()30     FramebufferFormatsTest() : mFramebuffer(0), mTexture(0), mRenderbuffer(0), mProgram(0)
31     {
32         setWindowWidth(128);
33         setWindowHeight(128);
34         setConfigRedBits(8);
35         setConfigGreenBits(8);
36         setConfigBlueBits(8);
37         setConfigAlphaBits(8);
38     }
39 
checkBitCount(GLuint fbo,GLenum channel,GLint minBits)40     void checkBitCount(GLuint fbo, GLenum channel, GLint minBits)
41     {
42         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
43 
44         GLint bits = 0;
45         glGetIntegerv(channel, &bits);
46 
47         if (minBits == 0)
48         {
49             EXPECT_EQ(minBits, bits);
50         }
51         else
52         {
53             EXPECT_GE(bits, minBits);
54         }
55     }
56 
testBitCounts(GLuint fbo,GLint minRedBits,GLint minGreenBits,GLint minBlueBits,GLint minAlphaBits,GLint minDepthBits,GLint minStencilBits)57     void testBitCounts(GLuint fbo,
58                        GLint minRedBits,
59                        GLint minGreenBits,
60                        GLint minBlueBits,
61                        GLint minAlphaBits,
62                        GLint minDepthBits,
63                        GLint minStencilBits)
64     {
65         checkBitCount(fbo, GL_RED_BITS, minRedBits);
66         checkBitCount(fbo, GL_GREEN_BITS, minGreenBits);
67         checkBitCount(fbo, GL_BLUE_BITS, minBlueBits);
68         checkBitCount(fbo, GL_ALPHA_BITS, minAlphaBits);
69         checkBitCount(fbo, GL_DEPTH_BITS, minDepthBits);
70         checkBitCount(fbo, GL_STENCIL_BITS, minStencilBits);
71     }
72 
testTextureFormat(GLenum internalFormat,GLint minRedBits,GLint minGreenBits,GLint minBlueBits,GLint minAlphaBits)73     void testTextureFormat(GLenum internalFormat,
74                            GLint minRedBits,
75                            GLint minGreenBits,
76                            GLint minBlueBits,
77                            GLint minAlphaBits)
78     {
79         glGenTextures(1, &mTexture);
80         glBindTexture(GL_TEXTURE_2D, mTexture);
81 
82         if (getClientMajorVersion() >= 3)
83         {
84             glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
85         }
86         else
87         {
88             glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
89         }
90 
91         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
92 
93         testBitCounts(mFramebuffer, minRedBits, minGreenBits, minBlueBits, minAlphaBits, 0, 0);
94     }
95 
testRenderbufferMultisampleFormat(int minESVersion,GLenum attachmentType,GLenum internalFormat)96     void testRenderbufferMultisampleFormat(int minESVersion,
97                                            GLenum attachmentType,
98                                            GLenum internalFormat)
99     {
100         int clientVersion = getClientMajorVersion();
101         if (clientVersion < minESVersion)
102         {
103             return;
104         }
105 
106         // Check that multisample is supported with at least two samples (minimum required is 1)
107         bool supports2Samples = false;
108 
109         if (clientVersion == 2)
110         {
111             if (IsGLExtensionEnabled("ANGLE_framebuffer_multisample"))
112             {
113                 int maxSamples;
114                 glGetIntegerv(GL_MAX_SAMPLES_ANGLE, &maxSamples);
115                 supports2Samples = maxSamples >= 2;
116             }
117         }
118         else
119         {
120             assert(clientVersion >= 3);
121             int maxSamples;
122             glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
123             supports2Samples = maxSamples >= 2;
124         }
125 
126         if (!supports2Samples)
127         {
128             return;
129         }
130 
131         glGenRenderbuffers(1, &mRenderbuffer);
132         glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
133 
134         EXPECT_GL_NO_ERROR();
135         glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, internalFormat, 128, 128);
136         EXPECT_GL_NO_ERROR();
137         glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentType, GL_RENDERBUFFER, mRenderbuffer);
138         EXPECT_GL_NO_ERROR();
139     }
140 
testZeroHeightRenderbuffer()141     void testZeroHeightRenderbuffer()
142     {
143         glGenRenderbuffers(1, &mRenderbuffer);
144         glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
145         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 0);
146         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
147                                   mRenderbuffer);
148         EXPECT_GL_NO_ERROR();
149     }
150 
testSetUp()151     void testSetUp() override
152     {
153         glGenFramebuffers(1, &mFramebuffer);
154         glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
155     }
156 
testTearDown()157     void testTearDown() override
158     {
159         if (mTexture != 0)
160         {
161             glDeleteTextures(1, &mTexture);
162             mTexture = 0;
163         }
164 
165         if (mRenderbuffer != 0)
166         {
167             glDeleteRenderbuffers(1, &mRenderbuffer);
168             mRenderbuffer = 0;
169         }
170 
171         if (mFramebuffer != 0)
172         {
173             glDeleteFramebuffers(1, &mFramebuffer);
174             mFramebuffer = 0;
175         }
176 
177         if (mProgram != 0)
178         {
179             glDeleteProgram(mProgram);
180             mProgram = 0;
181         }
182     }
183 
184     GLuint mFramebuffer;
185     GLuint mTexture;
186     GLuint mRenderbuffer;
187     GLuint mProgram;
188 };
189 
TEST_P(FramebufferFormatsTest,RGBA4)190 TEST_P(FramebufferFormatsTest, RGBA4)
191 {
192     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
193                        !IsGLExtensionEnabled("GL_EXT_texture_storage"));
194 
195     testTextureFormat(GL_RGBA4, 4, 4, 4, 4);
196 }
197 
TEST_P(FramebufferFormatsTest,RGB565)198 TEST_P(FramebufferFormatsTest, RGB565)
199 {
200     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
201                        !IsGLExtensionEnabled("GL_EXT_texture_storage"));
202 
203     testTextureFormat(GL_RGB565, 5, 6, 5, 0);
204 }
205 
TEST_P(FramebufferFormatsTest,RGB8)206 TEST_P(FramebufferFormatsTest, RGB8)
207 {
208     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
209                        (!IsGLExtensionEnabled("GL_OES_rgb8_rgba8") ||
210                         !IsGLExtensionEnabled("GL_EXT_texture_storage")));
211 
212     testTextureFormat(GL_RGB8_OES, 8, 8, 8, 0);
213 }
214 
TEST_P(FramebufferFormatsTest,BGRA8)215 TEST_P(FramebufferFormatsTest, BGRA8)
216 {
217     ANGLE_SKIP_TEST_IF(
218         !IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888") ||
219         (getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_texture_storage")));
220 
221     testTextureFormat(GL_BGRA8_EXT, 8, 8, 8, 8);
222 }
223 
TEST_P(FramebufferFormatsTest,RGBA8)224 TEST_P(FramebufferFormatsTest, RGBA8)
225 {
226     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
227                        (!IsGLExtensionEnabled("GL_OES_rgb8_rgba8") ||
228                         !IsGLExtensionEnabled("GL_EXT_texture_storage")));
229 
230     testTextureFormat(GL_RGBA8_OES, 8, 8, 8, 8);
231 }
232 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH16)233 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH16)
234 {
235     testRenderbufferMultisampleFormat(2, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16);
236 }
237 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH24)238 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24)
239 {
240     testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24);
241 }
242 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH32F)243 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F)
244 {
245     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
246 
247     testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT32F);
248 }
249 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH24_STENCIL8)250 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24_STENCIL8)
251 {
252     testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH24_STENCIL8);
253 }
254 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_DEPTH32F_STENCIL8)255 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F_STENCIL8)
256 {
257     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
258 
259     testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH32F_STENCIL8);
260 }
261 
TEST_P(FramebufferFormatsTest,RenderbufferMultisample_STENCIL_INDEX8)262 TEST_P(FramebufferFormatsTest, RenderbufferMultisample_STENCIL_INDEX8)
263 {
264     // TODO(geofflang): Figure out how to support GLSTENCIL_INDEX8 on desktop GL
265     ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
266 
267     testRenderbufferMultisampleFormat(2, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8);
268 }
269 
270 // Test that binding an incomplete cube map is rejected by ANGLE.
TEST_P(FramebufferFormatsTest,IncompleteCubeMap)271 TEST_P(FramebufferFormatsTest, IncompleteCubeMap)
272 {
273     // http://anglebug.com/3145
274     ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
275 
276     // First make a complete CubeMap.
277     glGenTextures(1, &mTexture);
278     glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
279     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
280                  nullptr);
281     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
282                  nullptr);
283     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
284                  nullptr);
285     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
286                  nullptr);
287     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
288                  nullptr);
289     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
290                  nullptr);
291     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
292     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
293 
294     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
295                            mTexture, 0);
296 
297     // Verify the framebuffer is complete.
298     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
299 
300     // Make the CubeMap cube-incomplete.
301     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
302                  nullptr);
303 
304     // Verify the framebuffer is incomplete.
305     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
306                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
307 
308     ASSERT_GL_NO_ERROR();
309 
310     // Verify drawing with the incomplete framebuffer produces a GL error
311     mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
312     ASSERT_NE(0u, mProgram);
313     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
314     ASSERT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
315 }
316 
317 // Test that a renderbuffer with zero height but nonzero width is handled without crashes/asserts.
TEST_P(FramebufferFormatsTest,ZeroHeightRenderbuffer)318 TEST_P(FramebufferFormatsTest, ZeroHeightRenderbuffer)
319 {
320     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
321 
322     testZeroHeightRenderbuffer();
323 }
324 
325 // Test to cover a bug where the read framebuffer affects the completeness of the draw framebuffer.
TEST_P(FramebufferFormatsTest,ReadDrawCompleteness)326 TEST_P(FramebufferFormatsTest, ReadDrawCompleteness)
327 {
328     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
329 
330     GLTexture incompleteTexture;
331     glBindTexture(GL_TEXTURE_2D, incompleteTexture);
332 
333     GLFramebuffer incompleteFBO;
334     glBindFramebuffer(GL_FRAMEBUFFER, incompleteFBO);
335     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, incompleteTexture,
336                            0);
337     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
338                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
339 
340     GLTexture completeTexture;
341     glBindTexture(GL_TEXTURE_2D, completeTexture);
342     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
343 
344     GLFramebuffer completeFBO;
345     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, completeFBO);
346     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
347                            completeTexture, 0);
348 
349     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
350                      glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
351     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
352 
353     ASSERT_GL_NO_ERROR();
354 
355     // Simple draw program.
356     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
357 
358     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
359     EXPECT_GL_NO_ERROR();
360 
361     glBindFramebuffer(GL_READ_FRAMEBUFFER, completeFBO);
362     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
363 }
364 
365 class FramebufferTest_ES3 : public ANGLETest
366 {};
367 
368 // Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error.
TEST_P(FramebufferTest_ES3,InvalidateIncomplete)369 TEST_P(FramebufferTest_ES3, InvalidateIncomplete)
370 {
371     GLFramebuffer framebuffer;
372     GLRenderbuffer renderbuffer;
373 
374     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
375     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
376     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
377     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
378                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
379 
380     std::vector<GLenum> attachments;
381     attachments.push_back(GL_COLOR_ATTACHMENT0);
382 
383     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
384     EXPECT_GL_NO_ERROR();
385 }
386 
387 // Test that the framebuffer state tracking robustly handles a depth-only attachment being set
388 // as a depth-stencil attachment. It is equivalent to detaching the depth-stencil attachment.
TEST_P(FramebufferTest_ES3,DepthOnlyAsDepthStencil)389 TEST_P(FramebufferTest_ES3, DepthOnlyAsDepthStencil)
390 {
391     GLFramebuffer framebuffer;
392     GLRenderbuffer renderbuffer;
393 
394     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
395     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
396     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 4, 4);
397 
398     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
399                               renderbuffer);
400     EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
401 }
402 
403 // Test that the framebuffer correctly returns that it is not complete if invalid texture mip levels
404 // are bound
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevels)405 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevels)
406 {
407     GLFramebuffer framebuffer;
408     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
409 
410     GLTexture texture;
411     glBindTexture(GL_TEXTURE_2D, texture);
412 
413     // Create a complete mip chain in mips 1 to 3
414     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
415     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
416     glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
417 
418     // Create another complete mip chain in mips 4 to 5
419     glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
420     glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
421 
422     // Create a non-complete mip chain in mip 6
423     glTexImage2D(GL_TEXTURE_2D, 6, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
424 
425     // Incomplete, mipLevel != baseLevel and texture is not mip complete
426     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
427     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
428                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
429 
430     // Complete, mipLevel == baseLevel
431     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
432     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
433 
434     // Complete, mipLevel != baseLevel but texture is now mip complete
435     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2);
436     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
437     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3);
438     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
439 
440     // Incomplete, attached level below the base level
441     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
442     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
443     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
444                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
445 
446     // Incomplete, attached level is beyond effective max level
447     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 4);
448     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
449                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
450 
451     // Complete, mipLevel == baseLevel
452     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
453     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
454 
455     // Complete, mipLevel != baseLevel but texture is now mip complete
456     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 5);
457     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
458 
459     // Complete, mipLevel == baseLevel
460     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 6);
461     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 6);
462     ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
463 }
464 
TEST_P(FramebufferTest_ES3,TextureAttachmentMipLevelsReadBack)465 TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBack)
466 {
467     // http://anglebug.com/4695
468     ANGLE_SKIP_TEST_IF(IsVulkan());
469 
470     GLFramebuffer framebuffer;
471     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
472 
473     GLTexture texture;
474     glBindTexture(GL_TEXTURE_2D, texture);
475 
476     const std::array<GLColor, 2 * 2> mip0Data = {GLColor::red, GLColor::red, GLColor::red,
477                                                  GLColor::red};
478     const std::array<GLColor, 1 * 1> mip1Data = {GLColor::green};
479 
480     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data());
481     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data());
482 
483     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
484     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
485     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
486 
487     glClearColor(0, 0, 1.0f, 1.0f);
488     glClear(GL_COLOR_BUFFER_BIT);
489     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
490 }
491 
492 // Test that passing an attachment COLOR_ATTACHMENTm where m is equal to MAX_COLOR_ATTACHMENTS
493 // generates an INVALID_OPERATION.
494 // OpenGL ES Version 3.0.5 (November 3, 2016), 4.4.2.4 Attaching Texture Images to a Framebuffer, p.
495 // 208
TEST_P(FramebufferTest_ES3,ColorAttachmentIndexOutOfBounds)496 TEST_P(FramebufferTest_ES3, ColorAttachmentIndexOutOfBounds)
497 {
498     GLFramebuffer framebuffer;
499     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
500 
501     GLint maxColorAttachments = 0;
502     glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
503     GLenum attachment = static_cast<GLenum>(maxColorAttachments + GL_COLOR_ATTACHMENT0);
504 
505     GLTexture texture;
506     glBindTexture(GL_TEXTURE_2D, texture.get());
507     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
508     glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture.get(), 0);
509     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
510 }
511 
512 // Check that depth-only attachments report the correct number of samples.
TEST_P(FramebufferTest_ES3,MultisampleDepthOnly)513 TEST_P(FramebufferTest_ES3, MultisampleDepthOnly)
514 {
515     GLRenderbuffer renderbuffer;
516     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
517     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT24, 32, 32);
518 
519     GLFramebuffer framebuffer;
520     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
521     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
522     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
523     EXPECT_GL_NO_ERROR();
524 
525     GLint samples = 0;
526     glGetIntegerv(GL_SAMPLES, &samples);
527     EXPECT_GL_NO_ERROR();
528     EXPECT_GE(samples, 2);
529 }
530 
531 // Check that we only compare width and height of attachments, not depth.
TEST_P(FramebufferTest_ES3,AttachmentWith3DLayers)532 TEST_P(FramebufferTest_ES3, AttachmentWith3DLayers)
533 {
534     GLTexture texA;
535     glBindTexture(GL_TEXTURE_2D, texA);
536     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
537 
538     GLTexture texB;
539     glBindTexture(GL_TEXTURE_3D, texB);
540     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
541 
542     GLFramebuffer framebuffer;
543     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
544     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
545     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texB, 0, 0);
546     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
547     EXPECT_GL_NO_ERROR();
548 }
549 
550 // Test that clearing the stencil buffer when the framebuffer only has a color attachment does not
551 // crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentStencil)552 TEST_P(FramebufferTest_ES3, ClearNonexistentStencil)
553 {
554     GLRenderbuffer rbo;
555     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
556     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
557 
558     GLFramebuffer fbo;
559     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
560     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
561 
562     GLint clearValue = 0;
563     glClearBufferiv(GL_STENCIL, 0, &clearValue);
564 
565     // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
566     EXPECT_GL_NO_ERROR();
567 }
568 
569 // Test that clearing the depth buffer when the framebuffer only has a color attachment does not
570 // crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentDepth)571 TEST_P(FramebufferTest_ES3, ClearNonexistentDepth)
572 {
573     GLRenderbuffer rbo;
574     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
575     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
576 
577     GLFramebuffer fbo;
578     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
579     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
580 
581     GLfloat clearValue = 0.0f;
582     glClearBufferfv(GL_DEPTH, 0, &clearValue);
583 
584     // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
585     EXPECT_GL_NO_ERROR();
586 }
587 
588 // Test that clearing a nonexistent color attachment does not crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentColor)589 TEST_P(FramebufferTest_ES3, ClearNonexistentColor)
590 {
591     GLRenderbuffer rbo;
592     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
593     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
594 
595     GLFramebuffer fbo;
596     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
597     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
598 
599     std::vector<GLfloat> clearValue = {{0.0f, 1.0f, 0.0f, 1.0f}};
600     glClearBufferfv(GL_COLOR, 1, clearValue.data());
601 
602     // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
603     EXPECT_GL_NO_ERROR();
604 }
605 
606 // Test that clearing the depth and stencil buffers when the framebuffer only has a color attachment
607 // does not crash.
TEST_P(FramebufferTest_ES3,ClearNonexistentDepthStencil)608 TEST_P(FramebufferTest_ES3, ClearNonexistentDepthStencil)
609 {
610     GLRenderbuffer rbo;
611     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
612     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
613 
614     GLFramebuffer fbo;
615     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
616     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
617 
618     glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
619 
620     // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
621     EXPECT_GL_NO_ERROR();
622 }
623 
624 // Test that clearing a color attachment that has been deleted doesn't crash.
TEST_P(FramebufferTest_ES3,ClearDeletedAttachment)625 TEST_P(FramebufferTest_ES3, ClearDeletedAttachment)
626 {
627     // An INVALID_FRAMEBUFFER_OPERATION error was seen in this test on Mac, not sure where it might
628     // be originating from. http://anglebug.com/2834
629     ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
630 
631     GLFramebuffer fbo;
632     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
633 
634     // There used to be a bug where some draw buffer state used to remain set even after the
635     // attachment was detached via deletion. That's why we create, attach and delete this RBO here.
636     GLuint rbo = 0u;
637     glGenRenderbuffers(1, &rbo);
638     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
639     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
640     glDeleteRenderbuffers(1, &rbo);
641 
642     // There needs to be at least one color attachment to prevent early out from the clear calls.
643     GLRenderbuffer rbo2;
644     glBindRenderbuffer(GL_RENDERBUFFER, rbo2);
645     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
646     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rbo2);
647 
648     ASSERT_GL_NO_ERROR();
649 
650     // There's no error specified for clearing nonexistent buffers, it's simply a no-op, so we
651     // expect no GL errors below.
652     std::array<GLfloat, 4> floatClearValue = {0.0f, 0.0f, 0.0f, 0.0f};
653     glClearBufferfv(GL_COLOR, 0, floatClearValue.data());
654     EXPECT_GL_NO_ERROR();
655     std::array<GLuint, 4> uintClearValue = {0u, 0u, 0u, 0u};
656     glClearBufferuiv(GL_COLOR, 0, uintClearValue.data());
657     EXPECT_GL_NO_ERROR();
658     std::array<GLint, 4> intClearValue = {0, 0, 0, 0};
659     glClearBufferiv(GL_COLOR, 0, intClearValue.data());
660     EXPECT_GL_NO_ERROR();
661 }
662 
663 // Test that resizing the color attachment is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeColorAttachmentSmallToLarge)664 TEST_P(FramebufferTest_ES3, ResizeColorAttachmentSmallToLarge)
665 {
666     GLFramebuffer fbo;
667     GLTexture smallTexture;
668     GLTexture largeTexture;
669 
670     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
671     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
672 
673     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
674 
675     // Bind the small texture
676     glBindTexture(GL_TEXTURE_2D, smallTexture);
677     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
678                  GL_UNSIGNED_BYTE, nullptr);
679     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
680     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
681     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
682     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
683 
684     // Draw to FBO backed by the small texture
685     glUseProgram(greenProgram);
686     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
687     ASSERT_GL_NO_ERROR();
688     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
689     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
690 
691     // Change the attachment to the larger texture that fills the window
692     glBindTexture(GL_TEXTURE_2D, largeTexture);
693     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
694                  GL_UNSIGNED_BYTE, nullptr);
695     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
696     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
697     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
698     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
699 
700     // Draw to FBO backed by the large texture
701     glUseProgram(blueProgram);
702     drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
703     ASSERT_GL_NO_ERROR();
704     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
705     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
706 }
707 
708 // Test that resizing the color attachment is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeColorAttachmentLargeToSmall)709 TEST_P(FramebufferTest_ES3, ResizeColorAttachmentLargeToSmall)
710 {
711     GLFramebuffer fbo;
712     GLTexture smallTexture;
713     GLTexture largeTexture;
714 
715     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
716     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
717 
718     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
719 
720     // Bind the large texture
721     glBindTexture(GL_TEXTURE_2D, largeTexture);
722     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
723                  GL_UNSIGNED_BYTE, nullptr);
724     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
725     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
726     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
727     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
728 
729     // Draw to FBO backed by the large texture
730     glUseProgram(blueProgram);
731     drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
732     ASSERT_GL_NO_ERROR();
733     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
734     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
735 
736     // Change the attachment to the smaller texture
737     glBindTexture(GL_TEXTURE_2D, smallTexture);
738     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
739                  GL_UNSIGNED_BYTE, nullptr);
740     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
741     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
742     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
743     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
744 
745     // Draw to FBO backed by the small texture
746     glUseProgram(greenProgram);
747     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
748     ASSERT_GL_NO_ERROR();
749     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
750     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
751 }
752 
753 // Test that resizing the texture is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeTextureLargeToSmall)754 TEST_P(FramebufferTest_ES3, ResizeTextureLargeToSmall)
755 {
756     GLFramebuffer fbo;
757     GLTexture texture;
758 
759     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
760     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
761 
762     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
763 
764     // Allocate a large texture
765     glBindTexture(GL_TEXTURE_2D, texture);
766     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
767                  GL_UNSIGNED_BYTE, nullptr);
768     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
769     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
770     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
771     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
772 
773     // Draw to FBO backed by the large texture
774     glUseProgram(blueProgram);
775     drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
776     ASSERT_GL_NO_ERROR();
777     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
778     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
779 
780     // Shrink the texture
781     glBindTexture(GL_TEXTURE_2D, texture);
782     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
783                  GL_UNSIGNED_BYTE, nullptr);
784     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
785     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
786     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
787     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
788 
789     // Draw to FBO backed by the small texture
790     glUseProgram(greenProgram);
791     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
792     ASSERT_GL_NO_ERROR();
793     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
794     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
795 }
796 
797 // Test that resizing the texture is handled correctly.
TEST_P(FramebufferTest_ES3,ResizeTextureSmallToLarge)798 TEST_P(FramebufferTest_ES3, ResizeTextureSmallToLarge)
799 {
800     GLFramebuffer fbo;
801     GLTexture texture;
802 
803     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
804     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
805 
806     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
807 
808     // Allocate a small texture
809     glBindTexture(GL_TEXTURE_2D, texture);
810     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
811                  GL_UNSIGNED_BYTE, nullptr);
812     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
813     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
814     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
815     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
816 
817     // Draw to FBO backed by the large texture
818     glUseProgram(blueProgram);
819     drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
820     ASSERT_GL_NO_ERROR();
821     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
822     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::blue);
823 
824     // Grow the texture
825     glBindTexture(GL_TEXTURE_2D, texture);
826     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
827                  GL_UNSIGNED_BYTE, nullptr);
828     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
829     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
830     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
831     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
832 
833     // Draw to FBO backed by the small texture
834     glUseProgram(greenProgram);
835     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
836     ASSERT_GL_NO_ERROR();
837     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
838     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
839 }
840 
841 // Test that fewer outputs than framebuffer attachments doesn't crash.  This causes a Vulkan
842 // validation warning, but should not be fatal.
TEST_P(FramebufferTest_ES3,FewerShaderOutputsThanAttachments)843 TEST_P(FramebufferTest_ES3, FewerShaderOutputsThanAttachments)
844 {
845     constexpr char kFS[] = R"(#version 300 es
846 precision highp float;
847 
848 layout(location = 0) out vec4 color0;
849 layout(location = 1) out vec4 color1;
850 layout(location = 2) out vec4 color2;
851 
852 void main()
853 {
854     color0 = vec4(1.0, 0.0, 0.0, 1.0);
855     color1 = vec4(0.0, 1.0, 0.0, 1.0);
856     color2 = vec4(0.0, 0.0, 1.0, 1.0);
857 }
858 )";
859 
860     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
861 
862     constexpr GLint kDrawBufferCount = 4;
863 
864     GLint maxDrawBuffers;
865     glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
866     ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
867 
868     GLTexture textures[kDrawBufferCount];
869 
870     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
871     {
872         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
873         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
874                      GL_UNSIGNED_BYTE, nullptr);
875     }
876 
877     GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,
878                                         GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
879 
880     GLFramebuffer fbo;
881     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
882 
883     // Enable all draw buffers.
884     for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
885     {
886         glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
887         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
888                                textures[texIndex], 0);
889     }
890     glDrawBuffers(kDrawBufferCount, allBufs);
891 
892     // Draw with simple program.
893     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
894     ASSERT_GL_NO_ERROR();
895 }
896 
897 class FramebufferTest_ES31 : public ANGLETest
898 {
899   protected:
validateSamplePass(GLuint & query,GLuint & passedCount,GLint width,GLint height)900     void validateSamplePass(GLuint &query, GLuint &passedCount, GLint width, GLint height)
901     {
902         glUniform2i(0, width - 1, height - 1);
903         glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
904         glDrawArrays(GL_TRIANGLES, 0, 6);
905         glEndQuery(GL_ANY_SAMPLES_PASSED);
906         glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
907         EXPECT_GT(static_cast<GLint>(passedCount), 0);
908 
909         glUniform2i(0, width - 1, height);
910         glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
911         glDrawArrays(GL_TRIANGLES, 0, 6);
912         glEndQuery(GL_ANY_SAMPLES_PASSED);
913         glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
914         EXPECT_EQ(static_cast<GLint>(passedCount), 0);
915 
916         glUniform2i(0, width, height - 1);
917         glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
918         glDrawArrays(GL_TRIANGLES, 0, 6);
919         glEndQuery(GL_ANY_SAMPLES_PASSED);
920         glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
921         EXPECT_EQ(static_cast<GLint>(passedCount), 0);
922     }
923 };
924 
925 // Test that without attachment, if either the value of FRAMEBUFFER_DEFAULT_WIDTH or
926 // FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is incomplete.
TEST_P(FramebufferTest_ES31,IncompleteMissingAttachmentDefaultParam)927 TEST_P(FramebufferTest_ES31, IncompleteMissingAttachmentDefaultParam)
928 {
929     // anglebug.com/3565
930     ANGLE_SKIP_TEST_IF(IsVulkan());
931 
932     GLFramebuffer mFramebuffer;
933     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
934 
935     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
936     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
937     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
938 
939     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
940     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
941     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
942                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
943 
944     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
945     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
946     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
947                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
948 
949     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
950     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
951     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
952                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
953 
954     ASSERT_GL_NO_ERROR();
955 }
956 
957 // Test that the sample count of a mix of texture and renderbuffer should be same.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleSampleCountMix)958 TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix)
959 {
960     // anglebug.com/3565
961     ANGLE_SKIP_TEST_IF(IsVulkan());
962 
963     GLFramebuffer mFramebuffer;
964     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
965 
966     // Lookup the supported number of sample counts (rely on fact that ANGLE uses the same set of
967     // sample counts for textures and renderbuffers)
968     GLint numSampleCounts = 0;
969     std::vector<GLint> sampleCounts;
970     GLsizei queryBufferSize = 1;
971     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
972                           queryBufferSize, &numSampleCounts);
973     ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
974     sampleCounts.resize(numSampleCounts);
975     queryBufferSize = numSampleCounts;
976     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
977                           sampleCounts.data());
978 
979     GLTexture mTexture;
980     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
981     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
982 
983     GLRenderbuffer mRenderbuffer;
984     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
985     glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCounts[1], GL_RGBA8, 1, 1);
986     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
987                            mTexture.get(), 0);
988     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
989                               mRenderbuffer.get());
990     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
991                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
992 
993     ASSERT_GL_NO_ERROR();
994 }
995 
996 // Test that the sample count of texture attachments should be same.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleSampleCountTex)997 TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex)
998 {
999     // anglebug.com/3565
1000     ANGLE_SKIP_TEST_IF(IsVulkan());
1001 
1002     GLFramebuffer mFramebuffer;
1003     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1004 
1005     // Lookup the supported number of sample counts
1006     GLint numSampleCounts = 0;
1007     std::vector<GLint> sampleCounts;
1008     GLsizei queryBufferSize = 1;
1009     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
1010                           queryBufferSize, &numSampleCounts);
1011     ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
1012     sampleCounts.resize(numSampleCounts);
1013     queryBufferSize = numSampleCounts;
1014     glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
1015                           sampleCounts.data());
1016 
1017     GLTexture mTextures[2];
1018     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
1019     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
1020     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
1021     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[1], GL_RGBA8, 1, 1, true);
1022     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1023                            mTextures[0].get(), 0);
1024     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1025                            mTextures[1].get(), 0);
1026     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1027                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
1028 
1029     ASSERT_GL_NO_ERROR();
1030 }
1031 
1032 // Test that if the attached images are a mix of renderbuffers and textures, the value of
1033 // TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleFixedSampleLocationsMix)1034 TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsMix)
1035 {
1036     // anglebug.com/3565
1037     ANGLE_SKIP_TEST_IF(IsVulkan());
1038 
1039     GLFramebuffer mFramebuffer;
1040     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1041 
1042     GLTexture mTexture;
1043     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
1044     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
1045 
1046     GLRenderbuffer mRenderbuffer;
1047     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
1048     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
1049     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1050                            mTexture.get(), 0);
1051     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
1052                               mRenderbuffer.get());
1053     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1054                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
1055 
1056     ASSERT_GL_NO_ERROR();
1057 }
1058 
1059 // Test that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures.
TEST_P(FramebufferTest_ES31,IncompleteMultisampleFixedSampleLocationsTex)1060 TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsTex)
1061 {
1062     // anglebug.com/3565
1063     ANGLE_SKIP_TEST_IF(IsVulkan());
1064 
1065     GLFramebuffer mFramebuffer;
1066     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1067 
1068     GLTexture mTextures[2];
1069     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
1070     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
1071     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1072                            mTextures[0].get(), 0);
1073     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
1074     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGB8, 1, 1, true);
1075     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1076                            mTextures[1].get(), 0);
1077     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1078                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
1079 
1080     ASSERT_GL_NO_ERROR();
1081 }
1082 
1083 // If there are no attachments, rendering will be limited to a rectangle having a lower left of
1084 // (0, 0) and an upper right of(width, height), where width and height are the framebuffer
1085 // object's default width and height.
TEST_P(FramebufferTest_ES31,RenderingLimitToDefaultFBOSizeWithNoAttachments)1086 TEST_P(FramebufferTest_ES31, RenderingLimitToDefaultFBOSizeWithNoAttachments)
1087 {
1088     // anglebug.com/2253
1089     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
1090     // Occlusion query reports fragments outside the render area are still rendered
1091     ANGLE_SKIP_TEST_IF(IsAndroid() || (IsWindows() && (IsIntel() || IsAMD())));
1092 
1093     constexpr char kVS1[] = R"(#version 310 es
1094 in layout(location = 0) highp vec2 a_position;
1095 void main()
1096 {
1097     gl_Position = vec4(a_position, 0.0, 1.0);
1098 })";
1099 
1100     constexpr char kFS1[] = R"(#version 310 es
1101 uniform layout(location = 0) highp ivec2 u_expectedSize;
1102 out layout(location = 3) mediump vec4 f_color;
1103 void main()
1104 {
1105     if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
1106     f_color = vec4(1.0, 0.5, 0.25, 1.0);
1107 })";
1108 
1109     constexpr char kVS2[] = R"(#version 310 es
1110 in layout(location = 0) highp vec2 a_position;
1111 void main()
1112 {
1113     gl_Position = vec4(a_position, 0.0, 1.0);
1114 })";
1115 
1116     constexpr char kFS2[] = R"(#version 310 es
1117 uniform layout(location = 0) highp ivec2 u_expectedSize;
1118 out layout(location = 2) mediump vec4 f_color;
1119 void main()
1120 {
1121     if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
1122     f_color = vec4(1.0, 0.5, 0.25, 1.0);
1123 })";
1124 
1125     GLuint program1 = CompileProgram(kVS1, kFS1);
1126     ASSERT_NE(program1, 0u);
1127 
1128     GLuint program2 = CompileProgram(kVS2, kFS2);
1129     ASSERT_NE(program2, 0u);
1130 
1131     glUseProgram(program1);
1132 
1133     GLFramebuffer mFramebuffer;
1134     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
1135     GLuint defaultWidth  = 1;
1136     GLuint defaultHeight = 1;
1137 
1138     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
1139     glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
1140     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1141 
1142     const float data[] = {
1143         1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
1144     };
1145 
1146     GLuint vertexArray  = 0;
1147     GLuint vertexBuffer = 0;
1148     GLuint query        = 0;
1149     GLuint passedCount  = 0;
1150 
1151     glGenQueries(1, &query);
1152     glGenVertexArrays(1, &vertexArray);
1153     glBindVertexArray(vertexArray);
1154 
1155     glGenBuffers(1, &vertexBuffer);
1156     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1157     glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1158 
1159     glEnableVertexAttribArray(0);
1160     glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
1161     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1162 
1163     validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1164 
1165     glUseProgram(program2);
1166     validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1167 
1168     glUseProgram(program1);
1169     // If fbo has attachments, the rendering size should be the same as its attachment.
1170     GLTexture mTexture;
1171     GLuint width  = 2;
1172     GLuint height = 2;
1173     glBindTexture(GL_TEXTURE_2D, mTexture.get());
1174     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
1175 
1176     const GLenum bufs[] = {GL_NONE, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT3};
1177 
1178     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, mTexture.get(),
1179                            0);
1180     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1181     glDrawBuffers(4, bufs);
1182 
1183     validateSamplePass(query, passedCount, width, height);
1184 
1185     // If fbo's attachment has been removed, the rendering size should be the same as framebuffer
1186     // default size.
1187     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, 0, 0, 0);
1188     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1189 
1190     validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1191 
1192     glDisableVertexAttribArray(0);
1193     glBindBuffer(GL_ARRAY_BUFFER, 0);
1194     glBindVertexArray(0);
1195     glDeleteBuffers(1, &vertexBuffer);
1196     glDeleteVertexArrays(1, &vertexArray);
1197 
1198     ASSERT_GL_NO_ERROR();
1199 }
1200 
1201 class AddDummyTextureNoRenderTargetTest : public ANGLETest
1202 {
1203   public:
AddDummyTextureNoRenderTargetTest()1204     AddDummyTextureNoRenderTargetTest()
1205     {
1206         setWindowWidth(512);
1207         setWindowHeight(512);
1208         setConfigRedBits(8);
1209         setConfigGreenBits(8);
1210         setConfigBlueBits(8);
1211         setConfigAlphaBits(8);
1212     }
1213 
overrideWorkaroundsD3D(FeaturesD3D * features)1214     void overrideWorkaroundsD3D(FeaturesD3D *features) override
1215     {
1216         features->overrideFeatures({"add_dummy_texture_no_render_target"}, true);
1217     }
1218 };
1219 
1220 // Test to verify workaround succeeds when no program outputs exist http://anglebug.com/2283
TEST_P(AddDummyTextureNoRenderTargetTest,NoProgramOutputWorkaround)1221 TEST_P(AddDummyTextureNoRenderTargetTest, NoProgramOutputWorkaround)
1222 {
1223     constexpr char kVS[] = "void main() {}";
1224     constexpr char kFS[] = "void main() {}";
1225 
1226     ANGLE_GL_PROGRAM(drawProgram, kVS, kFS);
1227 
1228     glUseProgram(drawProgram);
1229 
1230     glDrawArrays(GL_TRIANGLES, 0, 6);
1231 
1232     ASSERT_GL_NO_ERROR();
1233 }
1234 
1235 // Covers a bug in ANGLE's Vulkan back-end framebuffer cache which ignored depth/stencil after
1236 // calls to DrawBuffers.
TEST_P(FramebufferTest_ES3,AttachmentStateChange)1237 TEST_P(FramebufferTest_ES3, AttachmentStateChange)
1238 {
1239     constexpr GLuint kSize = 2;
1240 
1241     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1242 
1243     GLTexture colorTexture;
1244     glBindTexture(GL_TEXTURE_2D, colorTexture);
1245     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1246 
1247     GLFramebuffer fbo;
1248     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1249     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
1250 
1251     ASSERT_GL_NO_ERROR();
1252     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1253 
1254     // First draw without a depth buffer.
1255     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1256 
1257     GLRenderbuffer depthBuffer;
1258     glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
1259     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kSize, kSize);
1260 
1261     // Bind just a renderbuffer and draw.
1262     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
1263 
1264     ASSERT_GL_NO_ERROR();
1265     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1266 
1267     glDrawBuffers(0, nullptr);
1268     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1269 
1270     // Re-enable color buffer and draw one final time. This previously triggered a crash.
1271     GLenum drawBuffs = {GL_COLOR_ATTACHMENT0};
1272     glDrawBuffers(1, &drawBuffs);
1273 
1274     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1275     ASSERT_GL_NO_ERROR();
1276     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1277 }
1278 
1279 // Tests that we can support a feedback loop between a depth textures and the depth buffer.
1280 // Does not totally mirror the case used in Manhattan. The Manhattan case seems to handle
1281 // "clear" specially instead of rendering to depth in the same RP.
TEST_P(FramebufferTest_ES3,DepthFeedbackLoopSupported)1282 TEST_P(FramebufferTest_ES3, DepthFeedbackLoopSupported)
1283 {
1284     // Feedback loops not supported on D3D11 and may not ever be.
1285     ANGLE_SKIP_TEST_IF(IsD3D11());
1286 
1287     // Also this particular test doesn't work on Android despite similar support in Manhattan.
1288     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1289 
1290     constexpr GLuint kSize = 2;
1291     glViewport(0, 0, kSize, kSize);
1292 
1293     constexpr char kFS[] = R"(precision mediump float;
1294 varying vec2 v_texCoord;
1295 uniform sampler2D depth;
1296 void main()
1297 {
1298     if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
1299     {
1300         gl_FragColor = vec4(0, 1, 0, 1);
1301     }
1302     else
1303     {
1304         gl_FragColor = vec4(1, 0, 0, 1);
1305     }
1306 })";
1307 
1308     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
1309 
1310     GLFramebuffer framebuffer;
1311     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1312 
1313     GLTexture colorTexture;
1314     glBindTexture(GL_TEXTURE_2D, colorTexture);
1315     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1316 
1317     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1318     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1319     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
1320 
1321     GLTexture depthTexture;
1322     glBindTexture(GL_TEXTURE_2D, depthTexture);
1323     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
1324                  GL_UNSIGNED_INT, nullptr);
1325     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1326     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1327     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
1328 
1329     ASSERT_GL_NO_ERROR();
1330     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1331 
1332     // Clear depth to 0.5.
1333     glClearDepthf(0.5f);
1334     glClear(GL_DEPTH_BUFFER_BIT);
1335 
1336     // Disable the depth mask. Although this does not remove the feedback loop as defined by the
1337     // spec it mimics what gfxbench does in its rendering tests.
1338     glDepthMask(false);
1339 
1340     // Verify we can sample the depth texture and get 0.5.
1341     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
1342 
1343     ASSERT_GL_NO_ERROR();
1344     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1345 }
1346 
1347 // Covers a bug in ANGLE's Vulkan back-end. Our VkFramebuffer cache would in some cases forget to
1348 // check the draw states when computing a cache key.
TEST_P(FramebufferTest_ES3,DisabledAttachmentRedefinition)1349 TEST_P(FramebufferTest_ES3, DisabledAttachmentRedefinition)
1350 {
1351     constexpr GLuint kSize = 2;
1352 
1353     // Make a Framebuffer with two attachments with one enabled and one disabled.
1354     GLTexture texA, texB;
1355     glBindTexture(GL_TEXTURE_2D, texA);
1356     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1357     glBindTexture(GL_TEXTURE_2D, texB);
1358     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1359 
1360     GLFramebuffer fbo;
1361     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1362     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
1363     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texB, 0);
1364 
1365     // Mask out the second texture.
1366     constexpr GLenum kOneDrawBuf = GL_COLOR_ATTACHMENT0;
1367     glDrawBuffers(1, &kOneDrawBuf);
1368 
1369     ASSERT_GL_NO_ERROR();
1370     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1371 
1372     // Set up a very simple shader.
1373     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1374     glViewport(0, 0, kSize, kSize);
1375 
1376     // Draw
1377     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1378     ASSERT_GL_NO_ERROR();
1379     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1380 
1381     // Update the masked out attachment and draw again.
1382     std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
1383     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
1384                     redPixels.data());
1385 
1386     // Draw
1387     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1388     ASSERT_GL_NO_ERROR();
1389     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1390 
1391     glReadBuffer(GL_COLOR_ATTACHMENT1);
1392     ASSERT_GL_NO_ERROR();
1393     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1394 }
1395 
1396 class FramebufferTest : public ANGLETest
1397 {};
1398 
1399 template <typename T>
FillTexture2D(GLuint texture,GLsizei width,GLsizei height,const T & onePixelData,GLint level,GLint internalFormat,GLenum format,GLenum type)1400 void FillTexture2D(GLuint texture,
1401                    GLsizei width,
1402                    GLsizei height,
1403                    const T &onePixelData,
1404                    GLint level,
1405                    GLint internalFormat,
1406                    GLenum format,
1407                    GLenum type)
1408 {
1409     std::vector<T> allPixelsData(width * height, onePixelData);
1410 
1411     glBindTexture(GL_TEXTURE_2D, texture);
1412     glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
1413                  allPixelsData.data());
1414     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1415     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1416     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1417     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1418 }
1419 
1420 // Multi-context uses of textures should not cause rendering feedback loops.
TEST_P(FramebufferTest,MultiContextNoRenderingFeedbackLoops)1421 TEST_P(FramebufferTest, MultiContextNoRenderingFeedbackLoops)
1422 {
1423     constexpr char kTextureVS[] =
1424         R"(attribute vec4 a_position;
1425 varying vec2 v_texCoord;
1426 void main() {
1427     gl_Position = a_position;
1428     v_texCoord = (a_position.xy * 0.5) + 0.5;
1429 })";
1430 
1431     constexpr char kTextureFS[] =
1432         R"(precision mediump float;
1433 varying vec2 v_texCoord;
1434 uniform sampler2D u_texture;
1435 void main() {
1436     gl_FragColor = texture2D(u_texture, v_texCoord).rgba;
1437 })";
1438 
1439     ANGLE_GL_PROGRAM(textureProgram, kTextureVS, kTextureFS);
1440 
1441     glUseProgram(textureProgram.get());
1442     GLint uniformLoc = glGetUniformLocation(textureProgram.get(), "u_texture");
1443     ASSERT_NE(-1, uniformLoc);
1444     glUniform1i(uniformLoc, 0);
1445 
1446     GLTexture texture;
1447     FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1448     glBindTexture(GL_TEXTURE_2D, texture.get());
1449     // Note that _texture_ is still bound to GL_TEXTURE_2D in this context at this point.
1450 
1451     EGLWindow *window          = getEGLWindow();
1452     EGLDisplay display         = window->getDisplay();
1453     EGLConfig config           = window->getConfig();
1454     EGLSurface surface         = window->getSurface();
1455     EGLint contextAttributes[] = {
1456         EGL_CONTEXT_MAJOR_VERSION_KHR,
1457         GetParam().majorVersion,
1458         EGL_CONTEXT_MINOR_VERSION_KHR,
1459         GetParam().minorVersion,
1460         EGL_NONE,
1461     };
1462     EGLContext context1 = eglGetCurrentContext();
1463     // Create context2, sharing resources with context1.
1464     EGLContext context2 = eglCreateContext(display, config, context1, contextAttributes);
1465     ASSERT_NE(context2, EGL_NO_CONTEXT);
1466     eglMakeCurrent(display, surface, surface, context2);
1467 
1468     constexpr char kVS[] =
1469         R"(attribute vec4 a_position;
1470 void main() {
1471     gl_Position = a_position;
1472 })";
1473 
1474     constexpr char kFS[] =
1475         R"(precision mediump float;
1476 void main() {
1477     gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
1478 })";
1479 
1480     ANGLE_GL_PROGRAM(program, kVS, kFS);
1481     glUseProgram(program.get());
1482 
1483     ASSERT_GL_NO_ERROR();
1484 
1485     // Render to the texture in context2.
1486     GLFramebuffer framebuffer;
1487     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1488     // Texture is still a valid name in context2.
1489     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
1490     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1491     // There is no rendering feedback loop at this point.
1492 
1493     glDisable(GL_BLEND);
1494     glDisable(GL_DEPTH_TEST);
1495     ASSERT_GL_NO_ERROR();
1496 
1497     // If draw is no-op'ed, texture will not be filled appropriately.
1498     drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
1499     ASSERT_GL_NO_ERROR();
1500     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1501 
1502     // Make context1 current again.
1503     eglMakeCurrent(display, surface, surface, context1);
1504 
1505     // Render texture to screen.
1506     drawQuad(textureProgram.get(), "a_position", 0.5f, 1.0f, true);
1507     ASSERT_GL_NO_ERROR();
1508     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1509 
1510     eglDestroyContext(display, context2);
1511 }
1512 
1513 // Ensure cube-incomplete attachments cause incomplete Framebuffers.
TEST_P(FramebufferTest,IncompleteCubeMap)1514 TEST_P(FramebufferTest, IncompleteCubeMap)
1515 {
1516     constexpr GLuint kSize = 2;
1517 
1518     GLTexture srcTex;
1519     glBindTexture(GL_TEXTURE_CUBE_MAP, srcTex);
1520     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
1521                  GL_UNSIGNED_BYTE, nullptr);
1522 
1523     GLFramebuffer fbo;
1524     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1525     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
1526                            srcTex, 0);
1527 
1528     ASSERT_GL_NO_ERROR();
1529     ASSERT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1530                      GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
1531 }
1532 
1533 ANGLE_INSTANTIATE_TEST_ES2(AddDummyTextureNoRenderTargetTest);
1534 ANGLE_INSTANTIATE_TEST_ES2(FramebufferTest);
1535 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
1536 ANGLE_INSTANTIATE_TEST_ES3(FramebufferTest_ES3);
1537 ANGLE_INSTANTIATE_TEST_ES31(FramebufferTest_ES31);
1538