blob: bf69a6c5ade29ab6dda46562b45d12b6c60b0fc5 [file] [log] [blame]
Jamie Madillfa05f602015-05-07 13:47:11 -04001//
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//
Jamie Madill1fbc59f2016-02-24 15:25:51 -05006// Framebuffer tests:
7// Various tests related for Frambuffers.
8//
Jamie Madillfa05f602015-05-07 13:47:11 -04009
Jonah Ryan-Davisbeb0eb22019-06-14 15:10:33 -040010#include "platform/FeaturesD3D.h"
Corentin Wallezd3970de2015-05-14 11:07:48 -040011#include "test_utils/ANGLETest.h"
JiangYizhou461d9a32017-01-04 16:37:26 +080012#include "test_utils/gl_raii.h"
Geoff Langb6a673a2014-06-05 14:19:16 -040013
Jamie Madillfa05f602015-05-07 13:47:11 -040014using namespace angle;
Austin Kinross18b931d2014-09-29 12:58:31 -070015
Geoff Lang857c09d2017-05-16 15:55:04 -040016namespace
17{
18
19void 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
Geoff Langb6a673a2014-06-05 14:19:16 -040027class FramebufferFormatsTest : public ANGLETest
28{
Jamie Madillfa05f602015-05-07 13:47:11 -040029 protected:
Jamie Madill3215b202015-12-15 16:41:39 -050030 FramebufferFormatsTest() : mFramebuffer(0), mTexture(0), mRenderbuffer(0), mProgram(0)
Geoff Langb6a673a2014-06-05 14:19:16 -040031 {
32 setWindowWidth(128);
33 setWindowHeight(128);
34 setConfigRedBits(8);
35 setConfigGreenBits(8);
36 setConfigBlueBits(8);
37 setConfigAlphaBits(8);
38 }
39
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
Jamie Madill1fbc59f2016-02-24 15:25:51 -050057 void testBitCounts(GLuint fbo,
58 GLint minRedBits,
59 GLint minGreenBits,
60 GLint minBlueBits,
61 GLint minAlphaBits,
62 GLint minDepthBits,
63 GLint minStencilBits)
Geoff Langb6a673a2014-06-05 14:19:16 -040064 {
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
Jamie Madill1fbc59f2016-02-24 15:25:51 -050073 void testTextureFormat(GLenum internalFormat,
74 GLint minRedBits,
75 GLint minGreenBits,
76 GLint minBlueBits,
Geoff Langb6a673a2014-06-05 14:19:16 -040077 GLint minAlphaBits)
78 {
Jamie Madill3215b202015-12-15 16:41:39 -050079 glGenTextures(1, &mTexture);
80 glBindTexture(GL_TEXTURE_2D, mTexture);
Geoff Langc4e93662017-05-01 10:45:59 -040081
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 }
Geoff Langb6a673a2014-06-05 14:19:16 -040090
Jamie Madill3215b202015-12-15 16:41:39 -050091 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
Geoff Langb6a673a2014-06-05 14:19:16 -040092
Jamie Madill3215b202015-12-15 16:41:39 -050093 testBitCounts(mFramebuffer, minRedBits, minGreenBits, minBlueBits, minAlphaBits, 0, 0);
Geoff Langb6a673a2014-06-05 14:19:16 -040094 }
95
Jamie Madill1fbc59f2016-02-24 15:25:51 -050096 void testRenderbufferMultisampleFormat(int minESVersion,
97 GLenum attachmentType,
98 GLenum internalFormat)
Corentin Walleze0902642014-11-04 12:32:15 -080099 {
Martin Radev1be913c2016-07-11 17:59:16 +0300100 int clientVersion = getClientMajorVersion();
Jamie Madillfa05f602015-05-07 13:47:11 -0400101 if (clientVersion < minESVersion)
Corentin Walleze0902642014-11-04 12:32:15 -0800102 {
103 return;
104 }
105
106 // Check that multisample is supported with at least two samples (minimum required is 1)
107 bool supports2Samples = false;
108
Jamie Madillfa05f602015-05-07 13:47:11 -0400109 if (clientVersion == 2)
Corentin Walleze0902642014-11-04 12:32:15 -0800110 {
Jamie Madillb8149072019-04-30 16:14:44 -0400111 if (IsGLExtensionEnabled("ANGLE_framebuffer_multisample"))
Corentin Walleze0902642014-11-04 12:32:15 -0800112 {
113 int maxSamples;
114 glGetIntegerv(GL_MAX_SAMPLES_ANGLE, &maxSamples);
115 supports2Samples = maxSamples >= 2;
116 }
117 }
118 else
119 {
Jamie Madillfa05f602015-05-07 13:47:11 -0400120 assert(clientVersion >= 3);
Corentin Walleze0902642014-11-04 12:32:15 -0800121 int maxSamples;
122 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
123 supports2Samples = maxSamples >= 2;
124 }
125
126 if (!supports2Samples)
127 {
128 return;
129 }
130
Jamie Madill3215b202015-12-15 16:41:39 -0500131 glGenRenderbuffers(1, &mRenderbuffer);
132 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
Corentin Walleze0902642014-11-04 12:32:15 -0800133
134 EXPECT_GL_NO_ERROR();
135 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, internalFormat, 128, 128);
136 EXPECT_GL_NO_ERROR();
Jamie Madill3215b202015-12-15 16:41:39 -0500137 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentType, GL_RENDERBUFFER, mRenderbuffer);
Corentin Walleze0902642014-11-04 12:32:15 -0800138 EXPECT_GL_NO_ERROR();
Corentin Walleze0902642014-11-04 12:32:15 -0800139 }
140
Olli Etuahobc21e182016-02-23 16:04:57 +0200141 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
Jamie Madill5cbaa3f2019-05-07 15:49:22 -0400151 void testSetUp() override
Geoff Langb6a673a2014-06-05 14:19:16 -0400152 {
Jamie Madill3215b202015-12-15 16:41:39 -0500153 glGenFramebuffers(1, &mFramebuffer);
154 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
Geoff Langb6a673a2014-06-05 14:19:16 -0400155 }
156
Jamie Madill5cbaa3f2019-05-07 15:49:22 -0400157 void testTearDown() override
Geoff Langb6a673a2014-06-05 14:19:16 -0400158 {
Jamie Madill3215b202015-12-15 16:41:39 -0500159 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 }
Geoff Langb6a673a2014-06-05 14:19:16 -0400182 }
Jamie Madill3215b202015-12-15 16:41:39 -0500183
184 GLuint mFramebuffer;
185 GLuint mTexture;
186 GLuint mRenderbuffer;
187 GLuint mProgram;
Geoff Langb6a673a2014-06-05 14:19:16 -0400188};
189
Jamie Madillfa05f602015-05-07 13:47:11 -0400190TEST_P(FramebufferFormatsTest, RGBA4)
Geoff Langb6a673a2014-06-05 14:19:16 -0400191{
Jamie Madillb8149072019-04-30 16:14:44 -0400192 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
193 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
Geoff Langc4e93662017-05-01 10:45:59 -0400194
Geoff Langb6a673a2014-06-05 14:19:16 -0400195 testTextureFormat(GL_RGBA4, 4, 4, 4, 4);
196}
197
Jamie Madillfa05f602015-05-07 13:47:11 -0400198TEST_P(FramebufferFormatsTest, RGB565)
Geoff Langb6a673a2014-06-05 14:19:16 -0400199{
Jamie Madillb8149072019-04-30 16:14:44 -0400200 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
201 !IsGLExtensionEnabled("GL_EXT_texture_storage"));
Geoff Langc4e93662017-05-01 10:45:59 -0400202
Geoff Langb6a673a2014-06-05 14:19:16 -0400203 testTextureFormat(GL_RGB565, 5, 6, 5, 0);
204}
205
Jamie Madillfa05f602015-05-07 13:47:11 -0400206TEST_P(FramebufferFormatsTest, RGB8)
Geoff Langb6a673a2014-06-05 14:19:16 -0400207{
Jamie Madillb8149072019-04-30 16:14:44 -0400208 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
209 (!IsGLExtensionEnabled("GL_OES_rgb8_rgba8") ||
210 !IsGLExtensionEnabled("GL_EXT_texture_storage")));
Geoff Langf34d1db2015-05-20 14:10:46 -0400211
Geoff Langb6a673a2014-06-05 14:19:16 -0400212 testTextureFormat(GL_RGB8_OES, 8, 8, 8, 0);
213}
214
Jamie Madillfa05f602015-05-07 13:47:11 -0400215TEST_P(FramebufferFormatsTest, BGRA8)
Geoff Langb6a673a2014-06-05 14:19:16 -0400216{
Yunchao He9550c602018-02-13 14:47:05 +0800217 ANGLE_SKIP_TEST_IF(
Jamie Madillb8149072019-04-30 16:14:44 -0400218 !IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888") ||
219 (getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_texture_storage")));
Geoff Langf34d1db2015-05-20 14:10:46 -0400220
Geoff Langb6a673a2014-06-05 14:19:16 -0400221 testTextureFormat(GL_BGRA8_EXT, 8, 8, 8, 8);
222}
223
Jamie Madillfa05f602015-05-07 13:47:11 -0400224TEST_P(FramebufferFormatsTest, RGBA8)
Geoff Langb6a673a2014-06-05 14:19:16 -0400225{
Jamie Madillb8149072019-04-30 16:14:44 -0400226 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
227 (!IsGLExtensionEnabled("GL_OES_rgb8_rgba8") ||
228 !IsGLExtensionEnabled("GL_EXT_texture_storage")));
Geoff Langf34d1db2015-05-20 14:10:46 -0400229
Geoff Langb6a673a2014-06-05 14:19:16 -0400230 testTextureFormat(GL_RGBA8_OES, 8, 8, 8, 8);
231}
232
Jamie Madillfa05f602015-05-07 13:47:11 -0400233TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH16)
Corentin Walleze0902642014-11-04 12:32:15 -0800234{
235 testRenderbufferMultisampleFormat(2, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16);
236}
237
Jamie Madillfa05f602015-05-07 13:47:11 -0400238TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24)
Corentin Walleze0902642014-11-04 12:32:15 -0800239{
240 testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24);
241}
242
Jamie Madillfa05f602015-05-07 13:47:11 -0400243TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F)
Corentin Walleze0902642014-11-04 12:32:15 -0800244{
Yunchao He9550c602018-02-13 14:47:05 +0800245 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
Geoff Langf34d1db2015-05-20 14:10:46 -0400246
Corentin Walleze0902642014-11-04 12:32:15 -0800247 testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT32F);
248}
249
Jamie Madillfa05f602015-05-07 13:47:11 -0400250TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24_STENCIL8)
Corentin Walleze0902642014-11-04 12:32:15 -0800251{
252 testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH24_STENCIL8);
253}
254
Jamie Madillfa05f602015-05-07 13:47:11 -0400255TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F_STENCIL8)
Corentin Walleze0902642014-11-04 12:32:15 -0800256{
Yunchao He9550c602018-02-13 14:47:05 +0800257 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
Geoff Langf34d1db2015-05-20 14:10:46 -0400258
Corentin Walleze0902642014-11-04 12:32:15 -0800259 testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH32F_STENCIL8);
260}
261
Jamie Madillfa05f602015-05-07 13:47:11 -0400262TEST_P(FramebufferFormatsTest, RenderbufferMultisample_STENCIL_INDEX8)
Corentin Walleze0902642014-11-04 12:32:15 -0800263{
Geoff Langf34d1db2015-05-20 14:10:46 -0400264 // TODO(geofflang): Figure out how to support GLSTENCIL_INDEX8 on desktop GL
Yunchao He9550c602018-02-13 14:47:05 +0800265 ANGLE_SKIP_TEST_IF(IsDesktopOpenGL());
Geoff Langf34d1db2015-05-20 14:10:46 -0400266
Corentin Walleze0902642014-11-04 12:32:15 -0800267 testRenderbufferMultisampleFormat(2, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8);
268}
Jamie Madillfa05f602015-05-07 13:47:11 -0400269
Jamie Madill3215b202015-12-15 16:41:39 -0500270// Test that binding an incomplete cube map is rejected by ANGLE.
271TEST_P(FramebufferFormatsTest, IncompleteCubeMap)
272{
Michael Spangd8506c72019-01-29 15:35:09 -0500273 // http://anglebug.com/3145
274 ANGLE_SKIP_TEST_IF(IsFuchsia() && IsIntel() && IsVulkan());
275
Jamie Madill3215b202015-12-15 16:41:39 -0500276 // 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
Jamie Madilld84b6732018-09-06 15:54:35 -0400308 ASSERT_GL_NO_ERROR();
309
Jamie Madill3215b202015-12-15 16:41:39 -0500310 // Verify drawing with the incomplete framebuffer produces a GL error
Olli Etuaho5804dc82018-04-13 14:11:46 +0300311 mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
Jamie Madill3215b202015-12-15 16:41:39 -0500312 ASSERT_NE(0u, mProgram);
Olli Etuaho5804dc82018-04-13 14:11:46 +0300313 drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
Jamie Madill3215b202015-12-15 16:41:39 -0500314 ASSERT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
315}
316
Olli Etuahobc21e182016-02-23 16:04:57 +0200317// Test that a renderbuffer with zero height but nonzero width is handled without crashes/asserts.
318TEST_P(FramebufferFormatsTest, ZeroHeightRenderbuffer)
319{
Yunchao He9550c602018-02-13 14:47:05 +0800320 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
Olli Etuahobc21e182016-02-23 16:04:57 +0200321
322 testZeroHeightRenderbuffer();
323}
324
Geoff Lang9bf86f02018-07-26 11:46:34 -0400325// Test to cover a bug where the read framebuffer affects the completeness of the draw framebuffer.
326TEST_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
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500365// Use this to select which configurations (e.g. which renderer, which GLES major version) these
366// tests should be run against.
Tobin Ehlis1a01b4b2019-11-11 16:41:07 -0700367ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500368
Corentin Wallez57e6d502016-12-09 14:46:39 -0500369class FramebufferTest_ES3 : public ANGLETest
Jamie Madillb980c562018-11-27 11:34:27 -0500370{};
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500371
372// Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error.
Corentin Wallez57e6d502016-12-09 14:46:39 -0500373TEST_P(FramebufferTest_ES3, InvalidateIncomplete)
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500374{
Tim Van Pattene600ac22019-10-04 14:31:57 -0600375 // TODO: anglebug.com/3971
376 ANGLE_SKIP_TEST_IF(IsVulkan());
377
Geoff Lang857c09d2017-05-16 15:55:04 -0400378 GLFramebuffer framebuffer;
379 GLRenderbuffer renderbuffer;
380
381 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
382 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
383 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500384 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
385 glCheckFramebufferStatus(GL_FRAMEBUFFER));
386
387 std::vector<GLenum> attachments;
388 attachments.push_back(GL_COLOR_ATTACHMENT0);
389
390 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
391 EXPECT_GL_NO_ERROR();
392}
393
Corentin Wallez57e6d502016-12-09 14:46:39 -0500394// Test that the framebuffer state tracking robustly handles a depth-only attachment being set
395// as a depth-stencil attachment. It is equivalent to detaching the depth-stencil attachment.
396TEST_P(FramebufferTest_ES3, DepthOnlyAsDepthStencil)
397{
Geoff Lang857c09d2017-05-16 15:55:04 -0400398 GLFramebuffer framebuffer;
399 GLRenderbuffer renderbuffer;
400
401 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
402 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
Corentin Wallez57e6d502016-12-09 14:46:39 -0500403 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 4, 4);
404
405 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
Geoff Lang857c09d2017-05-16 15:55:04 -0400406 renderbuffer);
Corentin Wallez57e6d502016-12-09 14:46:39 -0500407 EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
408}
409
Geoff Lang857c09d2017-05-16 15:55:04 -0400410// Test that the framebuffer correctly returns that it is not complete if invalid texture mip levels
411// are bound
412TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevels)
413{
414 GLFramebuffer framebuffer;
415 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
416
417 GLTexture texture;
418 glBindTexture(GL_TEXTURE_2D, texture);
419
420 // Create a complete mip chain in mips 1 to 3
421 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
422 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
423 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
424
425 // Create another complete mip chain in mips 4 to 5
426 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
427 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
428
429 // Create a non-complete mip chain in mip 6
430 glTexImage2D(GL_TEXTURE_2D, 6, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
431
432 // Incomplete, mipLevel != baseLevel and texture is not mip complete
433 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
434 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
435 glCheckFramebufferStatus(GL_FRAMEBUFFER));
436
437 // Complete, mipLevel == baseLevel
438 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
439 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
440
441 // Complete, mipLevel != baseLevel but texture is now mip complete
442 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2);
443 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
444 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3);
445 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
446
447 // Incomplete, attached level below the base level
448 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
449 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
450 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
451 glCheckFramebufferStatus(GL_FRAMEBUFFER));
452
453 // Incomplete, attached level is beyond effective max level
454 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 4);
455 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
456 glCheckFramebufferStatus(GL_FRAMEBUFFER));
457
458 // Complete, mipLevel == baseLevel
459 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
460 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
461
462 // Complete, mipLevel != baseLevel but texture is now mip complete
463 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 5);
464 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
465
466 // Complete, mipLevel == baseLevel
467 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 6);
468 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 6);
469 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
470}
471
Martin Radevd178aa42017-07-13 14:03:22 +0300472// Test that passing an attachment COLOR_ATTACHMENTm where m is equal to MAX_COLOR_ATTACHMENTS
473// generates an INVALID_OPERATION.
474// OpenGL ES Version 3.0.5 (November 3, 2016), 4.4.2.4 Attaching Texture Images to a Framebuffer, p.
475// 208
476TEST_P(FramebufferTest_ES3, ColorAttachmentIndexOutOfBounds)
477{
478 GLFramebuffer framebuffer;
479 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
480
481 GLint maxColorAttachments = 0;
482 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
483 GLenum attachment = static_cast<GLenum>(maxColorAttachments + GL_COLOR_ATTACHMENT0);
484
485 GLTexture texture;
486 glBindTexture(GL_TEXTURE_2D, texture.get());
487 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
488 glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture.get(), 0);
489 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
490}
491
Jamie Madilla0016b72017-07-14 14:30:46 -0400492// Check that depth-only attachments report the correct number of samples.
493TEST_P(FramebufferTest_ES3, MultisampleDepthOnly)
494{
495 GLRenderbuffer renderbuffer;
496 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
497 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT24, 32, 32);
498
499 GLFramebuffer framebuffer;
500 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
501 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
502 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
503 EXPECT_GL_NO_ERROR();
504
505 GLint samples = 0;
506 glGetIntegerv(GL_SAMPLES, &samples);
507 EXPECT_GL_NO_ERROR();
508 EXPECT_GE(samples, 2);
509}
510
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700511// Check that we only compare width and height of attachments, not depth.
512TEST_P(FramebufferTest_ES3, AttachmentWith3DLayers)
513{
514 GLTexture texA;
515 glBindTexture(GL_TEXTURE_2D, texA);
516 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
517
518 GLTexture texB;
519 glBindTexture(GL_TEXTURE_3D, texB);
520 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
521
522 GLFramebuffer framebuffer;
523 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
524 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
525 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texB, 0, 0);
526 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
527 EXPECT_GL_NO_ERROR();
528}
529
Olli Etuahodbce1f82018-09-19 15:32:17 +0300530// Test that clearing the stencil buffer when the framebuffer only has a color attachment does not
531// crash.
532TEST_P(FramebufferTest_ES3, ClearNonexistentStencil)
533{
534 GLRenderbuffer rbo;
535 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
536 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
537
538 GLFramebuffer fbo;
539 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
540 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
541
542 GLint clearValue = 0;
543 glClearBufferiv(GL_STENCIL, 0, &clearValue);
544
545 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
546 EXPECT_GL_NO_ERROR();
547}
548
549// Test that clearing the depth buffer when the framebuffer only has a color attachment does not
550// crash.
551TEST_P(FramebufferTest_ES3, ClearNonexistentDepth)
552{
553 GLRenderbuffer rbo;
554 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
555 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
556
557 GLFramebuffer fbo;
558 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
559 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
560
561 GLfloat clearValue = 0.0f;
562 glClearBufferfv(GL_DEPTH, 0, &clearValue);
563
564 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
565 EXPECT_GL_NO_ERROR();
566}
567
568// Test that clearing a nonexistent color attachment does not crash.
569TEST_P(FramebufferTest_ES3, ClearNonexistentColor)
570{
571 GLRenderbuffer rbo;
572 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
573 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
574
575 GLFramebuffer fbo;
576 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
577 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
578
579 std::vector<GLfloat> clearValue = {{0.0f, 1.0f, 0.0f, 1.0f}};
580 glClearBufferfv(GL_COLOR, 1, clearValue.data());
581
582 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
583 EXPECT_GL_NO_ERROR();
584}
585
586// Test that clearing the depth and stencil buffers when the framebuffer only has a color attachment
587// does not crash.
588TEST_P(FramebufferTest_ES3, ClearNonexistentDepthStencil)
589{
590 GLRenderbuffer rbo;
591 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
592 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
593
594 GLFramebuffer fbo;
595 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
596 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
597
598 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
599
600 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
601 EXPECT_GL_NO_ERROR();
602}
603
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300604// Test that clearing a color attachment that has been deleted doesn't crash.
605TEST_P(FramebufferTest_ES3, ClearDeletedAttachment)
606{
607 // An INVALID_FRAMEBUFFER_OPERATION error was seen in this test on Mac, not sure where it might
608 // be originating from. http://anglebug.com/2834
609 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
610
611 GLFramebuffer fbo;
612 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
613
614 // There used to be a bug where some draw buffer state used to remain set even after the
615 // attachment was detached via deletion. That's why we create, attach and delete this RBO here.
616 GLuint rbo = 0u;
617 glGenRenderbuffers(1, &rbo);
618 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
619 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
620 glDeleteRenderbuffers(1, &rbo);
621
622 // There needs to be at least one color attachment to prevent early out from the clear calls.
623 GLRenderbuffer rbo2;
624 glBindRenderbuffer(GL_RENDERBUFFER, rbo2);
625 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
626 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rbo2);
627
628 ASSERT_GL_NO_ERROR();
629
630 // There's no error specified for clearing nonexistent buffers, it's simply a no-op, so we
631 // expect no GL errors below.
632 std::array<GLfloat, 4> floatClearValue = {0.0f, 0.0f, 0.0f, 0.0f};
633 glClearBufferfv(GL_COLOR, 0, floatClearValue.data());
634 EXPECT_GL_NO_ERROR();
635 std::array<GLuint, 4> uintClearValue = {0u, 0u, 0u, 0u};
636 glClearBufferuiv(GL_COLOR, 0, uintClearValue.data());
637 EXPECT_GL_NO_ERROR();
638 std::array<GLint, 4> intClearValue = {0, 0, 0, 0};
639 glClearBufferiv(GL_COLOR, 0, intClearValue.data());
640 EXPECT_GL_NO_ERROR();
641}
642
Tim Van Pattene600ac22019-10-04 14:31:57 -0600643// Test that resizing the color attachment is handled correctly.
644TEST_P(FramebufferTest_ES3, ResizeColorAttachmentSmallToLarge)
645{
646 GLFramebuffer fbo;
647 GLTexture smallTexture;
648 GLTexture largeTexture;
649
650 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
651 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
652
653 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
654
655 // Bind the small texture
656 glBindTexture(GL_TEXTURE_2D, smallTexture);
657 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
658 GL_UNSIGNED_BYTE, nullptr);
659 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
660 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
661 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
662 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
663
664 // Draw to FBO backed by the small texture
665 glUseProgram(greenProgram);
666 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
667 ASSERT_GL_NO_ERROR();
668 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
669 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
670
671 // Change the attachment to the larger texture that fills the window
672 glBindTexture(GL_TEXTURE_2D, largeTexture);
673 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
674 GL_UNSIGNED_BYTE, nullptr);
675 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
676 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
677 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
678 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
679
680 // Draw to FBO backed by the large texture
681 glUseProgram(blueProgram);
682 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
683 ASSERT_GL_NO_ERROR();
684 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
685 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
686}
687
688// Test that resizing the color attachment is handled correctly.
689TEST_P(FramebufferTest_ES3, ResizeColorAttachmentLargeToSmall)
690{
691 GLFramebuffer fbo;
692 GLTexture smallTexture;
693 GLTexture largeTexture;
694
695 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
696 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
697
698 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
699
700 // Bind the large texture
701 glBindTexture(GL_TEXTURE_2D, largeTexture);
702 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
703 GL_UNSIGNED_BYTE, nullptr);
704 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
705 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
706 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
707 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
708
709 // Draw to FBO backed by the large texture
710 glUseProgram(blueProgram);
711 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
712 ASSERT_GL_NO_ERROR();
713 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
714 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
715
716 // Change the attachment to the smaller texture
717 glBindTexture(GL_TEXTURE_2D, smallTexture);
718 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
719 GL_UNSIGNED_BYTE, nullptr);
720 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
721 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
722 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
723 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
724
725 // Draw to FBO backed by the small texture
726 glUseProgram(greenProgram);
727 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
728 ASSERT_GL_NO_ERROR();
729 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
730 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
731}
732
733// Test that resizing the texture is handled correctly.
734TEST_P(FramebufferTest_ES3, ResizeTextureLargeToSmall)
735{
736 GLFramebuffer fbo;
737 GLTexture texture;
738
739 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
740 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
741
742 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
743
744 // Allocate a large texture
745 glBindTexture(GL_TEXTURE_2D, texture);
746 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
747 GL_UNSIGNED_BYTE, nullptr);
748 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
749 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
750 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
751 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
752
753 // Draw to FBO backed by the large texture
754 glUseProgram(blueProgram);
755 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
756 ASSERT_GL_NO_ERROR();
757 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
758 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
759
760 // Shrink the texture
761 glBindTexture(GL_TEXTURE_2D, texture);
762 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
763 GL_UNSIGNED_BYTE, nullptr);
764 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
765 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
766 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
767 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
768
769 // Draw to FBO backed by the small texture
770 glUseProgram(greenProgram);
771 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
772 ASSERT_GL_NO_ERROR();
773 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
774 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
775}
776
777// Test that resizing the texture is handled correctly.
778TEST_P(FramebufferTest_ES3, ResizeTextureSmallToLarge)
779{
780 GLFramebuffer fbo;
781 GLTexture texture;
782
783 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
784 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
785
786 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
787
788 // Allocate a small texture
789 glBindTexture(GL_TEXTURE_2D, texture);
790 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
791 GL_UNSIGNED_BYTE, nullptr);
792 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
793 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
794 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
795 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
796
797 // Draw to FBO backed by the large texture
798 glUseProgram(blueProgram);
799 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
800 ASSERT_GL_NO_ERROR();
801 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
802 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::blue);
803
804 // Grow the texture
805 glBindTexture(GL_TEXTURE_2D, texture);
806 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
807 GL_UNSIGNED_BYTE, nullptr);
808 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
809 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
810 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
811 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
812
813 // Draw to FBO backed by the small texture
814 glUseProgram(greenProgram);
815 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
816 ASSERT_GL_NO_ERROR();
817 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
818 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
819}
820
Tobin Ehlis1a01b4b2019-11-11 16:41:07 -0700821ANGLE_INSTANTIATE_TEST_ES3(FramebufferTest_ES3);
JiangYizhou461d9a32017-01-04 16:37:26 +0800822
823class FramebufferTest_ES31 : public ANGLETest
824{
JiangYizhou511937d2017-08-03 15:41:29 +0800825 protected:
826 void validateSamplePass(GLuint &query, GLuint &passedCount, GLint width, GLint height)
827 {
828 glUniform2i(0, width - 1, height - 1);
829 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
830 glDrawArrays(GL_TRIANGLES, 0, 6);
831 glEndQuery(GL_ANY_SAMPLES_PASSED);
832 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
833 EXPECT_GT(static_cast<GLint>(passedCount), 0);
834
835 glUniform2i(0, width - 1, height);
836 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
837 glDrawArrays(GL_TRIANGLES, 0, 6);
838 glEndQuery(GL_ANY_SAMPLES_PASSED);
839 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
840 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
841
842 glUniform2i(0, width, height - 1);
843 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
844 glDrawArrays(GL_TRIANGLES, 0, 6);
845 glEndQuery(GL_ANY_SAMPLES_PASSED);
846 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
847 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
848 }
JiangYizhou461d9a32017-01-04 16:37:26 +0800849};
850
851// Test that without attachment, if either the value of FRAMEBUFFER_DEFAULT_WIDTH or
852// FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is incomplete.
853TEST_P(FramebufferTest_ES31, IncompleteMissingAttachmentDefaultParam)
854{
Tim Van Patten626a7282019-07-08 15:11:59 -0600855 // anglebug.com/3565
856 ANGLE_SKIP_TEST_IF(IsVulkan());
857
JiangYizhou461d9a32017-01-04 16:37:26 +0800858 GLFramebuffer mFramebuffer;
859 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
860
861 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
862 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
863 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
864
865 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
866 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
867 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
868 glCheckFramebufferStatus(GL_FRAMEBUFFER));
869
870 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
871 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
872 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
873 glCheckFramebufferStatus(GL_FRAMEBUFFER));
874
875 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
876 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
877 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
878 glCheckFramebufferStatus(GL_FRAMEBUFFER));
879
880 ASSERT_GL_NO_ERROR();
881}
882
883// Test that the sample count of a mix of texture and renderbuffer should be same.
884TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix)
885{
Tim Van Patten626a7282019-07-08 15:11:59 -0600886 // anglebug.com/3565
887 ANGLE_SKIP_TEST_IF(IsVulkan());
888
JiangYizhou461d9a32017-01-04 16:37:26 +0800889 GLFramebuffer mFramebuffer;
890 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
891
892 GLTexture mTexture;
893 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
894 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, true);
895
896 GLRenderbuffer mRenderbuffer;
897 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
898 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_RGBA8, 1, 1);
899 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
900 mTexture.get(), 0);
901 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
902 mRenderbuffer.get());
903 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
904 glCheckFramebufferStatus(GL_FRAMEBUFFER));
905
906 ASSERT_GL_NO_ERROR();
907}
908
909// Test that the sample count of texture attachments should be same.
910TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex)
911{
Tim Van Patten626a7282019-07-08 15:11:59 -0600912 // anglebug.com/3565
913 ANGLE_SKIP_TEST_IF(IsVulkan());
914
JiangYizhou461d9a32017-01-04 16:37:26 +0800915 GLFramebuffer mFramebuffer;
916 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
917
918 GLTexture mTextures[2];
919 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
920 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, true);
921 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
922 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, 1, 1, true);
923 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
924 mTextures[0].get(), 0);
925 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
926 mTextures[1].get(), 0);
927 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
928 glCheckFramebufferStatus(GL_FRAMEBUFFER));
929
930 ASSERT_GL_NO_ERROR();
931}
932
933// Test that if the attached images are a mix of renderbuffers and textures, the value of
934// TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
935TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsMix)
936{
Tim Van Patten626a7282019-07-08 15:11:59 -0600937 // anglebug.com/3565
938 ANGLE_SKIP_TEST_IF(IsVulkan());
939
JiangYizhou461d9a32017-01-04 16:37:26 +0800940 GLFramebuffer mFramebuffer;
941 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
942
943 GLTexture mTexture;
944 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
945 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
946
947 GLRenderbuffer mRenderbuffer;
948 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
949 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
950 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
951 mTexture.get(), 0);
952 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
953 mRenderbuffer.get());
954 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
955 glCheckFramebufferStatus(GL_FRAMEBUFFER));
956
957 ASSERT_GL_NO_ERROR();
958}
959
960// Test that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures.
961TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsTex)
962{
Tim Van Patten626a7282019-07-08 15:11:59 -0600963 // anglebug.com/3565
964 ANGLE_SKIP_TEST_IF(IsVulkan());
965
JiangYizhou461d9a32017-01-04 16:37:26 +0800966 GLFramebuffer mFramebuffer;
967 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
968
969 GLTexture mTextures[2];
970 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
971 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
972 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
973 mTextures[0].get(), 0);
974 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
975 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGB8, 1, 1, true);
976 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
977 mTextures[1].get(), 0);
978 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
979 glCheckFramebufferStatus(GL_FRAMEBUFFER));
980
981 ASSERT_GL_NO_ERROR();
982}
983
JiangYizhou511937d2017-08-03 15:41:29 +0800984// If there are no attachments, rendering will be limited to a rectangle having a lower left of
985// (0, 0) and an upper right of(width, height), where width and height are the framebuffer
986// object's default width and height.
JiangYizhou3db40722017-08-28 17:59:13 +0800987TEST_P(FramebufferTest_ES31, RenderingLimitToDefaultFBOSizeWithNoAttachments)
JiangYizhou511937d2017-08-03 15:41:29 +0800988{
Yuly Novikov98f9f532017-11-15 19:16:19 -0500989 // anglebug.com/2253
990 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
Tim Van Patten626a7282019-07-08 15:11:59 -0600991 // Occlusion query reports fragments outside the render area are still rendered
992 ANGLE_SKIP_TEST_IF(IsAndroid() || (IsWindows() && (IsIntel() || IsAMD())));
Yuly Novikov98f9f532017-11-15 19:16:19 -0500993
Jamie Madill35cd7332018-12-02 12:03:33 -0500994 constexpr char kVS1[] = R"(#version 310 es
995in layout(location = 0) highp vec2 a_position;
996void main()
997{
998 gl_Position = vec4(a_position, 0.0, 1.0);
999})";
JiangYizhou511937d2017-08-03 15:41:29 +08001000
Jamie Madill35cd7332018-12-02 12:03:33 -05001001 constexpr char kFS1[] = R"(#version 310 es
1002uniform layout(location = 0) highp ivec2 u_expectedSize;
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001003out layout(location = 3) mediump vec4 f_color;
Jamie Madill35cd7332018-12-02 12:03:33 -05001004void main()
1005{
1006 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
1007 f_color = vec4(1.0, 0.5, 0.25, 1.0);
1008})";
JiangYizhou511937d2017-08-03 15:41:29 +08001009
Jamie Madill35cd7332018-12-02 12:03:33 -05001010 constexpr char kVS2[] = R"(#version 310 es
1011in layout(location = 0) highp vec2 a_position;
1012void main()
1013{
1014 gl_Position = vec4(a_position, 0.0, 1.0);
1015})";
JiangYizhou10d41392017-12-18 18:13:36 +08001016
Jamie Madill35cd7332018-12-02 12:03:33 -05001017 constexpr char kFS2[] = R"(#version 310 es
1018uniform layout(location = 0) highp ivec2 u_expectedSize;
1019out layout(location = 2) mediump vec4 f_color;
1020void main()
1021{
1022 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
1023 f_color = vec4(1.0, 0.5, 0.25, 1.0);
1024})";
JiangYizhou10d41392017-12-18 18:13:36 +08001025
Jamie Madill35cd7332018-12-02 12:03:33 -05001026 GLuint program1 = CompileProgram(kVS1, kFS1);
JiangYizhou10d41392017-12-18 18:13:36 +08001027 ASSERT_NE(program1, 0u);
1028
Jamie Madill35cd7332018-12-02 12:03:33 -05001029 GLuint program2 = CompileProgram(kVS2, kFS2);
JiangYizhou10d41392017-12-18 18:13:36 +08001030 ASSERT_NE(program2, 0u);
1031
1032 glUseProgram(program1);
JiangYizhou511937d2017-08-03 15:41:29 +08001033
1034 GLFramebuffer mFramebuffer;
1035 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
1036 GLuint defaultWidth = 1;
1037 GLuint defaultHeight = 1;
1038
1039 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
1040 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
1041 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1042
1043 const float data[] = {
1044 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
1045 };
1046
1047 GLuint vertexArray = 0;
1048 GLuint vertexBuffer = 0;
1049 GLuint query = 0;
1050 GLuint passedCount = 0;
1051
1052 glGenQueries(1, &query);
1053 glGenVertexArrays(1, &vertexArray);
1054 glBindVertexArray(vertexArray);
1055
1056 glGenBuffers(1, &vertexBuffer);
1057 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1058 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1059
1060 glEnableVertexAttribArray(0);
1061 glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
JiangYizhou38d92b52017-09-13 13:47:52 +08001062 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
JiangYizhou511937d2017-08-03 15:41:29 +08001063
1064 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1065
JiangYizhou10d41392017-12-18 18:13:36 +08001066 glUseProgram(program2);
1067 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1068
1069 glUseProgram(program1);
JiangYizhou511937d2017-08-03 15:41:29 +08001070 // If fbo has attachments, the rendering size should be the same as its attachment.
1071 GLTexture mTexture;
1072 GLuint width = 2;
1073 GLuint height = 2;
1074 glBindTexture(GL_TEXTURE_2D, mTexture.get());
1075 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
JiangYizhou38d92b52017-09-13 13:47:52 +08001076
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001077 const GLenum bufs[] = {GL_NONE, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT3};
JiangYizhou38d92b52017-09-13 13:47:52 +08001078
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001079 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, mTexture.get(),
JiangYizhou511937d2017-08-03 15:41:29 +08001080 0);
1081 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001082 glDrawBuffers(4, bufs);
JiangYizhou511937d2017-08-03 15:41:29 +08001083
1084 validateSamplePass(query, passedCount, width, height);
1085
1086 // If fbo's attachment has been removed, the rendering size should be the same as framebuffer
1087 // default size.
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001088 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, 0, 0, 0);
JiangYizhou511937d2017-08-03 15:41:29 +08001089 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1090
1091 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1092
1093 glDisableVertexAttribArray(0);
1094 glBindBuffer(GL_ARRAY_BUFFER, 0);
1095 glBindVertexArray(0);
1096 glDeleteBuffers(1, &vertexBuffer);
1097 glDeleteVertexArrays(1, &vertexArray);
1098
1099 ASSERT_GL_NO_ERROR();
1100}
1101
Tobin Ehlis1a01b4b2019-11-11 16:41:07 -07001102ANGLE_INSTANTIATE_TEST_ES31(FramebufferTest_ES31);
Brandon Jones9fc87332017-12-13 15:46:52 -08001103
1104class AddDummyTextureNoRenderTargetTest : public ANGLETest
1105{
1106 public:
1107 AddDummyTextureNoRenderTargetTest()
1108 {
1109 setWindowWidth(512);
1110 setWindowHeight(512);
1111 setConfigRedBits(8);
1112 setConfigGreenBits(8);
1113 setConfigBlueBits(8);
1114 setConfigAlphaBits(8);
1115 }
1116
Jonah Ryan-Daviseee67c62019-06-18 13:00:43 -04001117 void overrideWorkaroundsD3D(FeaturesD3D *features) override
Brandon Jones9fc87332017-12-13 15:46:52 -08001118 {
Jonah Ryan-Davisbeb0eb22019-06-14 15:10:33 -04001119 features->overrideFeatures({"add_dummy_texture_no_render_target"}, true);
Brandon Jones9fc87332017-12-13 15:46:52 -08001120 }
1121};
1122
1123// Test to verify workaround succeeds when no program outputs exist http://anglebug.com/2283
1124TEST_P(AddDummyTextureNoRenderTargetTest, NoProgramOutputWorkaround)
1125{
Jamie Madill35cd7332018-12-02 12:03:33 -05001126 constexpr char kVS[] = "void main() {}";
1127 constexpr char kFS[] = "void main() {}";
Brandon Jones9fc87332017-12-13 15:46:52 -08001128
Jamie Madill35cd7332018-12-02 12:03:33 -05001129 ANGLE_GL_PROGRAM(drawProgram, kVS, kFS);
Brandon Jones9fc87332017-12-13 15:46:52 -08001130
1131 glUseProgram(drawProgram);
1132
1133 glDrawArrays(GL_TRIANGLES, 0, 6);
1134
1135 ASSERT_GL_NO_ERROR();
1136}
1137
Tobin Ehlis1a01b4b2019-11-11 16:41:07 -07001138ANGLE_INSTANTIATE_TEST_ES2(AddDummyTextureNoRenderTargetTest);