blob: 86e24bb1223c2e9e299fb057cbbf30d7b9c1ebc9 [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
Corentin Wallez57e6d502016-12-09 14:46:39 -0500365class FramebufferTest_ES3 : public ANGLETest
Jamie Madillb980c562018-11-27 11:34:27 -0500366{};
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500367
368// Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error.
Corentin Wallez57e6d502016-12-09 14:46:39 -0500369TEST_P(FramebufferTest_ES3, InvalidateIncomplete)
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500370{
Geoff Lang857c09d2017-05-16 15:55:04 -0400371 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);
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500377 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
Corentin Wallez57e6d502016-12-09 14:46:39 -0500387// 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.
389TEST_P(FramebufferTest_ES3, DepthOnlyAsDepthStencil)
390{
Geoff Lang857c09d2017-05-16 15:55:04 -0400391 GLFramebuffer framebuffer;
392 GLRenderbuffer renderbuffer;
393
394 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
395 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
Corentin Wallez57e6d502016-12-09 14:46:39 -0500396 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 4, 4);
397
398 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
Geoff Lang857c09d2017-05-16 15:55:04 -0400399 renderbuffer);
Corentin Wallez57e6d502016-12-09 14:46:39 -0500400 EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
401}
402
Geoff Lang857c09d2017-05-16 15:55:04 -0400403// Test that the framebuffer correctly returns that it is not complete if invalid texture mip levels
404// are bound
405TEST_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
Martin Radevd178aa42017-07-13 14:03:22 +0300465// Test that passing an attachment COLOR_ATTACHMENTm where m is equal to MAX_COLOR_ATTACHMENTS
466// generates an INVALID_OPERATION.
467// OpenGL ES Version 3.0.5 (November 3, 2016), 4.4.2.4 Attaching Texture Images to a Framebuffer, p.
468// 208
469TEST_P(FramebufferTest_ES3, ColorAttachmentIndexOutOfBounds)
470{
471 GLFramebuffer framebuffer;
472 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
473
474 GLint maxColorAttachments = 0;
475 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
476 GLenum attachment = static_cast<GLenum>(maxColorAttachments + GL_COLOR_ATTACHMENT0);
477
478 GLTexture texture;
479 glBindTexture(GL_TEXTURE_2D, texture.get());
480 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
481 glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture.get(), 0);
482 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
483}
484
Jamie Madilla0016b72017-07-14 14:30:46 -0400485// Check that depth-only attachments report the correct number of samples.
486TEST_P(FramebufferTest_ES3, MultisampleDepthOnly)
487{
488 GLRenderbuffer renderbuffer;
489 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
490 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT24, 32, 32);
491
492 GLFramebuffer framebuffer;
493 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
494 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
495 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
496 EXPECT_GL_NO_ERROR();
497
498 GLint samples = 0;
499 glGetIntegerv(GL_SAMPLES, &samples);
500 EXPECT_GL_NO_ERROR();
501 EXPECT_GE(samples, 2);
502}
503
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700504// Check that we only compare width and height of attachments, not depth.
505TEST_P(FramebufferTest_ES3, AttachmentWith3DLayers)
506{
507 GLTexture texA;
508 glBindTexture(GL_TEXTURE_2D, texA);
509 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
510
511 GLTexture texB;
512 glBindTexture(GL_TEXTURE_3D, texB);
513 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
514
515 GLFramebuffer framebuffer;
516 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
517 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
518 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texB, 0, 0);
519 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
520 EXPECT_GL_NO_ERROR();
521}
522
Olli Etuahodbce1f82018-09-19 15:32:17 +0300523// Test that clearing the stencil buffer when the framebuffer only has a color attachment does not
524// crash.
525TEST_P(FramebufferTest_ES3, ClearNonexistentStencil)
526{
527 GLRenderbuffer rbo;
528 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
529 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
530
531 GLFramebuffer fbo;
532 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
533 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
534
535 GLint clearValue = 0;
536 glClearBufferiv(GL_STENCIL, 0, &clearValue);
537
538 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
539 EXPECT_GL_NO_ERROR();
540}
541
542// Test that clearing the depth buffer when the framebuffer only has a color attachment does not
543// crash.
544TEST_P(FramebufferTest_ES3, ClearNonexistentDepth)
545{
546 GLRenderbuffer rbo;
547 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
548 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
549
550 GLFramebuffer fbo;
551 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
552 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
553
554 GLfloat clearValue = 0.0f;
555 glClearBufferfv(GL_DEPTH, 0, &clearValue);
556
557 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
558 EXPECT_GL_NO_ERROR();
559}
560
561// Test that clearing a nonexistent color attachment does not crash.
562TEST_P(FramebufferTest_ES3, ClearNonexistentColor)
563{
564 GLRenderbuffer rbo;
565 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
566 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
567
568 GLFramebuffer fbo;
569 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
570 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
571
572 std::vector<GLfloat> clearValue = {{0.0f, 1.0f, 0.0f, 1.0f}};
573 glClearBufferfv(GL_COLOR, 1, clearValue.data());
574
575 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
576 EXPECT_GL_NO_ERROR();
577}
578
579// Test that clearing the depth and stencil buffers when the framebuffer only has a color attachment
580// does not crash.
581TEST_P(FramebufferTest_ES3, ClearNonexistentDepthStencil)
582{
583 GLRenderbuffer rbo;
584 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
585 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
586
587 GLFramebuffer fbo;
588 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
589 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
590
591 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
592
593 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
594 EXPECT_GL_NO_ERROR();
595}
596
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300597// Test that clearing a color attachment that has been deleted doesn't crash.
598TEST_P(FramebufferTest_ES3, ClearDeletedAttachment)
599{
600 // An INVALID_FRAMEBUFFER_OPERATION error was seen in this test on Mac, not sure where it might
601 // be originating from. http://anglebug.com/2834
602 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
603
604 GLFramebuffer fbo;
605 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
606
607 // There used to be a bug where some draw buffer state used to remain set even after the
608 // attachment was detached via deletion. That's why we create, attach and delete this RBO here.
609 GLuint rbo = 0u;
610 glGenRenderbuffers(1, &rbo);
611 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
612 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
613 glDeleteRenderbuffers(1, &rbo);
614
615 // There needs to be at least one color attachment to prevent early out from the clear calls.
616 GLRenderbuffer rbo2;
617 glBindRenderbuffer(GL_RENDERBUFFER, rbo2);
618 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
619 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rbo2);
620
621 ASSERT_GL_NO_ERROR();
622
623 // There's no error specified for clearing nonexistent buffers, it's simply a no-op, so we
624 // expect no GL errors below.
625 std::array<GLfloat, 4> floatClearValue = {0.0f, 0.0f, 0.0f, 0.0f};
626 glClearBufferfv(GL_COLOR, 0, floatClearValue.data());
627 EXPECT_GL_NO_ERROR();
628 std::array<GLuint, 4> uintClearValue = {0u, 0u, 0u, 0u};
629 glClearBufferuiv(GL_COLOR, 0, uintClearValue.data());
630 EXPECT_GL_NO_ERROR();
631 std::array<GLint, 4> intClearValue = {0, 0, 0, 0};
632 glClearBufferiv(GL_COLOR, 0, intClearValue.data());
633 EXPECT_GL_NO_ERROR();
634}
635
Tim Van Pattene600ac22019-10-04 14:31:57 -0600636// Test that resizing the color attachment is handled correctly.
637TEST_P(FramebufferTest_ES3, ResizeColorAttachmentSmallToLarge)
638{
639 GLFramebuffer fbo;
640 GLTexture smallTexture;
641 GLTexture largeTexture;
642
643 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
644 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
645
646 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
647
648 // Bind the small texture
649 glBindTexture(GL_TEXTURE_2D, smallTexture);
650 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
651 GL_UNSIGNED_BYTE, nullptr);
652 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
653 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
654 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
655 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
656
657 // Draw to FBO backed by the small texture
658 glUseProgram(greenProgram);
659 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
660 ASSERT_GL_NO_ERROR();
661 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
662 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
663
664 // Change the attachment to the larger texture that fills the window
665 glBindTexture(GL_TEXTURE_2D, largeTexture);
666 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
667 GL_UNSIGNED_BYTE, nullptr);
668 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
669 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
670 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
671 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
672
673 // Draw to FBO backed by the large texture
674 glUseProgram(blueProgram);
675 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
676 ASSERT_GL_NO_ERROR();
677 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
678 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
679}
680
681// Test that resizing the color attachment is handled correctly.
682TEST_P(FramebufferTest_ES3, ResizeColorAttachmentLargeToSmall)
683{
684 GLFramebuffer fbo;
685 GLTexture smallTexture;
686 GLTexture largeTexture;
687
688 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
689 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
690
691 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
692
693 // Bind the large texture
694 glBindTexture(GL_TEXTURE_2D, largeTexture);
695 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
696 GL_UNSIGNED_BYTE, nullptr);
697 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
698 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
699 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
700 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
701
702 // Draw to FBO backed by the large texture
703 glUseProgram(blueProgram);
704 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
705 ASSERT_GL_NO_ERROR();
706 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
707 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
708
709 // Change the attachment to the smaller texture
710 glBindTexture(GL_TEXTURE_2D, smallTexture);
711 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
712 GL_UNSIGNED_BYTE, nullptr);
713 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
714 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
715 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
716 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
717
718 // Draw to FBO backed by the small texture
719 glUseProgram(greenProgram);
720 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
721 ASSERT_GL_NO_ERROR();
722 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
723 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
724}
725
726// Test that resizing the texture is handled correctly.
727TEST_P(FramebufferTest_ES3, ResizeTextureLargeToSmall)
728{
729 GLFramebuffer fbo;
730 GLTexture texture;
731
732 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
733 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
734
735 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
736
737 // Allocate a large texture
738 glBindTexture(GL_TEXTURE_2D, texture);
739 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
740 GL_UNSIGNED_BYTE, nullptr);
741 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
742 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
743 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
744 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
745
746 // Draw to FBO backed by the large texture
747 glUseProgram(blueProgram);
748 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
749 ASSERT_GL_NO_ERROR();
750 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
751 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
752
753 // Shrink the texture
754 glBindTexture(GL_TEXTURE_2D, texture);
755 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
756 GL_UNSIGNED_BYTE, nullptr);
757 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
758 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
759 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
760 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
761
762 // Draw to FBO backed by the small texture
763 glUseProgram(greenProgram);
764 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
765 ASSERT_GL_NO_ERROR();
766 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
767 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
768}
769
770// Test that resizing the texture is handled correctly.
771TEST_P(FramebufferTest_ES3, ResizeTextureSmallToLarge)
772{
773 GLFramebuffer fbo;
774 GLTexture texture;
775
776 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
777 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
778
779 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
780
781 // Allocate a small texture
782 glBindTexture(GL_TEXTURE_2D, texture);
783 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
784 GL_UNSIGNED_BYTE, nullptr);
785 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
786 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
787 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
788 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
789
790 // Draw to FBO backed by the large texture
791 glUseProgram(blueProgram);
792 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
793 ASSERT_GL_NO_ERROR();
794 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
795 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::blue);
796
797 // Grow the texture
798 glBindTexture(GL_TEXTURE_2D, texture);
799 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
800 GL_UNSIGNED_BYTE, nullptr);
801 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
802 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
803 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
804 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
805
806 // Draw to FBO backed by the small texture
807 glUseProgram(greenProgram);
808 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
809 ASSERT_GL_NO_ERROR();
810 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
811 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
812}
813
Shahbaz Youssefie28883d2020-01-25 23:25:43 -0500814// Test that fewer outputs than framebuffer attachments doesn't crash. This causes a Vulkan
815// validation warning, but should not be fatal.
816TEST_P(FramebufferTest_ES3, FewerShaderOutputsThanAttachments)
817{
818 constexpr char kFS[] = R"(#version 300 es
819precision highp float;
820
821layout(location = 0) out vec4 color0;
822layout(location = 1) out vec4 color1;
823layout(location = 2) out vec4 color2;
824
825void main()
826{
827 color0 = vec4(1.0, 0.0, 0.0, 1.0);
828 color1 = vec4(0.0, 1.0, 0.0, 1.0);
829 color2 = vec4(0.0, 0.0, 1.0, 1.0);
830}
831)";
832
833 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
834
835 constexpr GLint kDrawBufferCount = 4;
836
837 GLint maxDrawBuffers;
838 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
839 ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
840
841 GLTexture textures[kDrawBufferCount];
842
843 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
844 {
845 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
846 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
847 GL_UNSIGNED_BYTE, nullptr);
848 }
849
850 GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,
851 GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
852
853 GLFramebuffer fbo;
854 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
855
856 // Enable all draw buffers.
857 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
858 {
859 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
860 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
861 textures[texIndex], 0);
862 }
863 glDrawBuffers(kDrawBufferCount, allBufs);
864
865 // Draw with simple program.
866 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
867 ASSERT_GL_NO_ERROR();
868}
JiangYizhou461d9a32017-01-04 16:37:26 +0800869
870class FramebufferTest_ES31 : public ANGLETest
871{
JiangYizhou511937d2017-08-03 15:41:29 +0800872 protected:
873 void validateSamplePass(GLuint &query, GLuint &passedCount, GLint width, GLint height)
874 {
875 glUniform2i(0, width - 1, height - 1);
876 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
877 glDrawArrays(GL_TRIANGLES, 0, 6);
878 glEndQuery(GL_ANY_SAMPLES_PASSED);
879 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
880 EXPECT_GT(static_cast<GLint>(passedCount), 0);
881
882 glUniform2i(0, width - 1, height);
883 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
884 glDrawArrays(GL_TRIANGLES, 0, 6);
885 glEndQuery(GL_ANY_SAMPLES_PASSED);
886 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
887 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
888
889 glUniform2i(0, width, height - 1);
890 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
891 glDrawArrays(GL_TRIANGLES, 0, 6);
892 glEndQuery(GL_ANY_SAMPLES_PASSED);
893 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
894 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
895 }
JiangYizhou461d9a32017-01-04 16:37:26 +0800896};
897
898// Test that without attachment, if either the value of FRAMEBUFFER_DEFAULT_WIDTH or
899// FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is incomplete.
900TEST_P(FramebufferTest_ES31, IncompleteMissingAttachmentDefaultParam)
901{
Tim Van Patten626a7282019-07-08 15:11:59 -0600902 // anglebug.com/3565
903 ANGLE_SKIP_TEST_IF(IsVulkan());
904
JiangYizhou461d9a32017-01-04 16:37:26 +0800905 GLFramebuffer mFramebuffer;
906 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
907
908 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
909 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
910 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
911
912 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
913 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
914 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
915 glCheckFramebufferStatus(GL_FRAMEBUFFER));
916
917 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
918 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
919 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
920 glCheckFramebufferStatus(GL_FRAMEBUFFER));
921
922 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
923 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
924 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
925 glCheckFramebufferStatus(GL_FRAMEBUFFER));
926
927 ASSERT_GL_NO_ERROR();
928}
929
930// Test that the sample count of a mix of texture and renderbuffer should be same.
931TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix)
932{
Tim Van Patten626a7282019-07-08 15:11:59 -0600933 // anglebug.com/3565
934 ANGLE_SKIP_TEST_IF(IsVulkan());
935
JiangYizhou461d9a32017-01-04 16:37:26 +0800936 GLFramebuffer mFramebuffer;
937 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
938
Ian Elliott5f857832019-12-04 15:30:50 -0700939 // Lookup the supported number of sample counts (rely on fact that ANGLE uses the same set of
940 // sample counts for textures and renderbuffers)
941 GLint numSampleCounts = 0;
942 std::vector<GLint> sampleCounts;
943 GLsizei queryBufferSize = 1;
944 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
945 queryBufferSize, &numSampleCounts);
946 ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
947 sampleCounts.resize(numSampleCounts);
948 queryBufferSize = numSampleCounts;
949 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
950 sampleCounts.data());
951
JiangYizhou461d9a32017-01-04 16:37:26 +0800952 GLTexture mTexture;
953 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
Ian Elliott5f857832019-12-04 15:30:50 -0700954 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
JiangYizhou461d9a32017-01-04 16:37:26 +0800955
956 GLRenderbuffer mRenderbuffer;
957 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
Ian Elliott5f857832019-12-04 15:30:50 -0700958 glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCounts[1], GL_RGBA8, 1, 1);
JiangYizhou461d9a32017-01-04 16:37:26 +0800959 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
960 mTexture.get(), 0);
961 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
962 mRenderbuffer.get());
963 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
964 glCheckFramebufferStatus(GL_FRAMEBUFFER));
965
966 ASSERT_GL_NO_ERROR();
967}
968
969// Test that the sample count of texture attachments should be same.
970TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex)
971{
Tim Van Patten626a7282019-07-08 15:11:59 -0600972 // anglebug.com/3565
973 ANGLE_SKIP_TEST_IF(IsVulkan());
974
JiangYizhou461d9a32017-01-04 16:37:26 +0800975 GLFramebuffer mFramebuffer;
976 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
977
Ian Elliott5f857832019-12-04 15:30:50 -0700978 // Lookup the supported number of sample counts
979 GLint numSampleCounts = 0;
980 std::vector<GLint> sampleCounts;
981 GLsizei queryBufferSize = 1;
982 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
983 queryBufferSize, &numSampleCounts);
984 ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
985 sampleCounts.resize(numSampleCounts);
986 queryBufferSize = numSampleCounts;
987 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
988 sampleCounts.data());
989
JiangYizhou461d9a32017-01-04 16:37:26 +0800990 GLTexture mTextures[2];
991 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
Ian Elliott5f857832019-12-04 15:30:50 -0700992 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
JiangYizhou461d9a32017-01-04 16:37:26 +0800993 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
Ian Elliott5f857832019-12-04 15:30:50 -0700994 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[1], GL_RGBA8, 1, 1, true);
JiangYizhou461d9a32017-01-04 16:37:26 +0800995 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
996 mTextures[0].get(), 0);
997 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
998 mTextures[1].get(), 0);
999 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1000 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1001
1002 ASSERT_GL_NO_ERROR();
1003}
1004
1005// Test that if the attached images are a mix of renderbuffers and textures, the value of
1006// TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
1007TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsMix)
1008{
Tim Van Patten626a7282019-07-08 15:11:59 -06001009 // anglebug.com/3565
1010 ANGLE_SKIP_TEST_IF(IsVulkan());
1011
JiangYizhou461d9a32017-01-04 16:37:26 +08001012 GLFramebuffer mFramebuffer;
1013 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1014
1015 GLTexture mTexture;
1016 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
1017 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
1018
1019 GLRenderbuffer mRenderbuffer;
1020 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
1021 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
1022 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1023 mTexture.get(), 0);
1024 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
1025 mRenderbuffer.get());
1026 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1027 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1028
1029 ASSERT_GL_NO_ERROR();
1030}
1031
1032// Test that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures.
1033TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsTex)
1034{
Tim Van Patten626a7282019-07-08 15:11:59 -06001035 // anglebug.com/3565
1036 ANGLE_SKIP_TEST_IF(IsVulkan());
1037
JiangYizhou461d9a32017-01-04 16:37:26 +08001038 GLFramebuffer mFramebuffer;
1039 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1040
1041 GLTexture mTextures[2];
1042 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
1043 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
1044 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1045 mTextures[0].get(), 0);
1046 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
1047 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGB8, 1, 1, true);
1048 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1049 mTextures[1].get(), 0);
1050 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1051 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1052
1053 ASSERT_GL_NO_ERROR();
1054}
1055
JiangYizhou511937d2017-08-03 15:41:29 +08001056// If there are no attachments, rendering will be limited to a rectangle having a lower left of
1057// (0, 0) and an upper right of(width, height), where width and height are the framebuffer
1058// object's default width and height.
JiangYizhou3db40722017-08-28 17:59:13 +08001059TEST_P(FramebufferTest_ES31, RenderingLimitToDefaultFBOSizeWithNoAttachments)
JiangYizhou511937d2017-08-03 15:41:29 +08001060{
Yuly Novikov98f9f532017-11-15 19:16:19 -05001061 // anglebug.com/2253
1062 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
Tim Van Patten626a7282019-07-08 15:11:59 -06001063 // Occlusion query reports fragments outside the render area are still rendered
1064 ANGLE_SKIP_TEST_IF(IsAndroid() || (IsWindows() && (IsIntel() || IsAMD())));
Yuly Novikov98f9f532017-11-15 19:16:19 -05001065
Jamie Madill35cd7332018-12-02 12:03:33 -05001066 constexpr char kVS1[] = R"(#version 310 es
1067in layout(location = 0) highp vec2 a_position;
1068void main()
1069{
1070 gl_Position = vec4(a_position, 0.0, 1.0);
1071})";
JiangYizhou511937d2017-08-03 15:41:29 +08001072
Jamie Madill35cd7332018-12-02 12:03:33 -05001073 constexpr char kFS1[] = R"(#version 310 es
1074uniform layout(location = 0) highp ivec2 u_expectedSize;
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001075out layout(location = 3) mediump vec4 f_color;
Jamie Madill35cd7332018-12-02 12:03:33 -05001076void main()
1077{
1078 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
1079 f_color = vec4(1.0, 0.5, 0.25, 1.0);
1080})";
JiangYizhou511937d2017-08-03 15:41:29 +08001081
Jamie Madill35cd7332018-12-02 12:03:33 -05001082 constexpr char kVS2[] = R"(#version 310 es
1083in layout(location = 0) highp vec2 a_position;
1084void main()
1085{
1086 gl_Position = vec4(a_position, 0.0, 1.0);
1087})";
JiangYizhou10d41392017-12-18 18:13:36 +08001088
Jamie Madill35cd7332018-12-02 12:03:33 -05001089 constexpr char kFS2[] = R"(#version 310 es
1090uniform layout(location = 0) highp ivec2 u_expectedSize;
1091out layout(location = 2) mediump vec4 f_color;
1092void main()
1093{
1094 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
1095 f_color = vec4(1.0, 0.5, 0.25, 1.0);
1096})";
JiangYizhou10d41392017-12-18 18:13:36 +08001097
Jamie Madill35cd7332018-12-02 12:03:33 -05001098 GLuint program1 = CompileProgram(kVS1, kFS1);
JiangYizhou10d41392017-12-18 18:13:36 +08001099 ASSERT_NE(program1, 0u);
1100
Jamie Madill35cd7332018-12-02 12:03:33 -05001101 GLuint program2 = CompileProgram(kVS2, kFS2);
JiangYizhou10d41392017-12-18 18:13:36 +08001102 ASSERT_NE(program2, 0u);
1103
1104 glUseProgram(program1);
JiangYizhou511937d2017-08-03 15:41:29 +08001105
1106 GLFramebuffer mFramebuffer;
1107 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
1108 GLuint defaultWidth = 1;
1109 GLuint defaultHeight = 1;
1110
1111 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
1112 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
1113 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1114
1115 const float data[] = {
1116 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
1117 };
1118
1119 GLuint vertexArray = 0;
1120 GLuint vertexBuffer = 0;
1121 GLuint query = 0;
1122 GLuint passedCount = 0;
1123
1124 glGenQueries(1, &query);
1125 glGenVertexArrays(1, &vertexArray);
1126 glBindVertexArray(vertexArray);
1127
1128 glGenBuffers(1, &vertexBuffer);
1129 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1130 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1131
1132 glEnableVertexAttribArray(0);
1133 glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
JiangYizhou38d92b52017-09-13 13:47:52 +08001134 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
JiangYizhou511937d2017-08-03 15:41:29 +08001135
1136 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1137
JiangYizhou10d41392017-12-18 18:13:36 +08001138 glUseProgram(program2);
1139 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1140
1141 glUseProgram(program1);
JiangYizhou511937d2017-08-03 15:41:29 +08001142 // If fbo has attachments, the rendering size should be the same as its attachment.
1143 GLTexture mTexture;
1144 GLuint width = 2;
1145 GLuint height = 2;
1146 glBindTexture(GL_TEXTURE_2D, mTexture.get());
1147 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
JiangYizhou38d92b52017-09-13 13:47:52 +08001148
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001149 const GLenum bufs[] = {GL_NONE, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT3};
JiangYizhou38d92b52017-09-13 13:47:52 +08001150
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001151 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, mTexture.get(),
JiangYizhou511937d2017-08-03 15:41:29 +08001152 0);
1153 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001154 glDrawBuffers(4, bufs);
JiangYizhou511937d2017-08-03 15:41:29 +08001155
1156 validateSamplePass(query, passedCount, width, height);
1157
1158 // If fbo's attachment has been removed, the rendering size should be the same as framebuffer
1159 // default size.
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001160 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, 0, 0, 0);
JiangYizhou511937d2017-08-03 15:41:29 +08001161 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1162
1163 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1164
1165 glDisableVertexAttribArray(0);
1166 glBindBuffer(GL_ARRAY_BUFFER, 0);
1167 glBindVertexArray(0);
1168 glDeleteBuffers(1, &vertexBuffer);
1169 glDeleteVertexArrays(1, &vertexArray);
1170
1171 ASSERT_GL_NO_ERROR();
1172}
1173
Brandon Jones9fc87332017-12-13 15:46:52 -08001174class AddDummyTextureNoRenderTargetTest : public ANGLETest
1175{
1176 public:
1177 AddDummyTextureNoRenderTargetTest()
1178 {
1179 setWindowWidth(512);
1180 setWindowHeight(512);
1181 setConfigRedBits(8);
1182 setConfigGreenBits(8);
1183 setConfigBlueBits(8);
1184 setConfigAlphaBits(8);
1185 }
1186
Jonah Ryan-Daviseee67c62019-06-18 13:00:43 -04001187 void overrideWorkaroundsD3D(FeaturesD3D *features) override
Brandon Jones9fc87332017-12-13 15:46:52 -08001188 {
Jonah Ryan-Davisbeb0eb22019-06-14 15:10:33 -04001189 features->overrideFeatures({"add_dummy_texture_no_render_target"}, true);
Brandon Jones9fc87332017-12-13 15:46:52 -08001190 }
1191};
1192
1193// Test to verify workaround succeeds when no program outputs exist http://anglebug.com/2283
1194TEST_P(AddDummyTextureNoRenderTargetTest, NoProgramOutputWorkaround)
1195{
Jamie Madill35cd7332018-12-02 12:03:33 -05001196 constexpr char kVS[] = "void main() {}";
1197 constexpr char kFS[] = "void main() {}";
Brandon Jones9fc87332017-12-13 15:46:52 -08001198
Jamie Madill35cd7332018-12-02 12:03:33 -05001199 ANGLE_GL_PROGRAM(drawProgram, kVS, kFS);
Brandon Jones9fc87332017-12-13 15:46:52 -08001200
1201 glUseProgram(drawProgram);
1202
1203 glDrawArrays(GL_TRIANGLES, 0, 6);
1204
1205 ASSERT_GL_NO_ERROR();
1206}
1207
Jamie Madill4fb3c282020-03-19 19:10:45 -04001208// Covers a bug in ANGLE's Vulkan back-end framebuffer cache which ignored depth/stencil after
1209// calls to DrawBuffers.
1210TEST_P(FramebufferTest_ES3, AttachmentStateChange)
1211{
1212 constexpr GLuint kSize = 2;
1213
1214 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1215
1216 GLTexture colorTexture;
1217 glBindTexture(GL_TEXTURE_2D, colorTexture);
1218 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1219
1220 GLFramebuffer fbo;
1221 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1222 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
1223
1224 ASSERT_GL_NO_ERROR();
1225 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1226
1227 // First draw without a depth buffer.
1228 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1229
1230 GLRenderbuffer depthBuffer;
1231 glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
1232 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kSize, kSize);
1233
1234 // Bind just a renderbuffer and draw.
1235 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
1236
1237 ASSERT_GL_NO_ERROR();
1238 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1239
1240 glDrawBuffers(0, nullptr);
1241 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1242
1243 // Re-enable color buffer and draw one final time. This previously triggered a crash.
1244 GLenum drawBuffs = {GL_COLOR_ATTACHMENT0};
1245 glDrawBuffers(1, &drawBuffs);
1246
1247 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1248 ASSERT_GL_NO_ERROR();
1249 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1250}
1251
Jamie Madilld03b15b2020-03-26 17:22:18 -04001252// Tests that we can support a feedback loop between a depth textures and the depth buffer.
1253// Does not totally mirror the case used in Manhattan. The Manhattan case seems to handle
1254// "clear" specially instead of rendering to depth in the same RP.
1255TEST_P(FramebufferTest_ES3, DepthFeedbackLoopSupported)
1256{
1257 // Feedback loops not supported on D3D11 and may not ever be.
1258 ANGLE_SKIP_TEST_IF(IsD3D11());
1259
1260 // Also this particular test doesn't work on Android despite similar support in Manhattan.
1261 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1262
1263 constexpr GLuint kSize = 2;
1264 glViewport(0, 0, kSize, kSize);
1265
1266 constexpr char kFS[] = R"(precision mediump float;
1267varying vec2 v_texCoord;
1268uniform sampler2D depth;
1269void main()
1270{
1271 if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
1272 {
1273 gl_FragColor = vec4(0, 1, 0, 1);
1274 }
1275 else
1276 {
1277 gl_FragColor = vec4(1, 0, 0, 1);
1278 }
1279})";
1280
1281 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
1282
1283 GLFramebuffer framebuffer;
1284 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1285
1286 GLTexture colorTexture;
1287 glBindTexture(GL_TEXTURE_2D, colorTexture);
1288 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1289
1290 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1291 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1292 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
1293
1294 GLTexture depthTexture;
1295 glBindTexture(GL_TEXTURE_2D, depthTexture);
1296 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
1297 GL_UNSIGNED_INT, nullptr);
1298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1300 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
1301
1302 ASSERT_GL_NO_ERROR();
1303 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1304
1305 // Clear depth to 0.5.
1306 glClearDepthf(0.5f);
1307 glClear(GL_DEPTH_BUFFER_BIT);
1308
1309 // Disable the depth mask. Although this does not remove the feedback loop as defined by the
1310 // spec it mimics what gfxbench does in its rendering tests.
1311 glDepthMask(false);
1312
1313 // Verify we can sample the depth texture and get 0.5.
1314 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
1315
1316 ASSERT_GL_NO_ERROR();
1317 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1318}
1319
Jamie Madilldd00f162020-04-02 14:04:44 -04001320// Covers a bug in ANGLE's Vulkan back-end. Our VkFramebuffer cache would in some cases forget to
1321// check the draw states when computing a cache key.
1322TEST_P(FramebufferTest_ES3, DisabledAttachmentRedefinition)
1323{
1324 constexpr GLuint kSize = 2;
1325
1326 // Make a Framebuffer with two attachments with one enabled and one disabled.
1327 GLTexture texA, texB;
1328 glBindTexture(GL_TEXTURE_2D, texA);
1329 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1330 glBindTexture(GL_TEXTURE_2D, texB);
1331 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1332
1333 GLFramebuffer fbo;
1334 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1335 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
1336 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texB, 0);
1337
1338 // Mask out the second texture.
1339 constexpr GLenum kOneDrawBuf = GL_COLOR_ATTACHMENT0;
1340 glDrawBuffers(1, &kOneDrawBuf);
1341
1342 ASSERT_GL_NO_ERROR();
1343 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1344
1345 // Set up a very simple shader.
1346 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1347 glViewport(0, 0, kSize, kSize);
1348
1349 // Draw
1350 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1351 ASSERT_GL_NO_ERROR();
1352 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1353
1354 // Update the masked out attachment and draw again.
1355 std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
1356 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
1357 redPixels.data());
1358
1359 // Draw
1360 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1361 ASSERT_GL_NO_ERROR();
1362 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1363
1364 glReadBuffer(GL_COLOR_ATTACHMENT1);
1365 ASSERT_GL_NO_ERROR();
1366 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1367}
1368
Jamie Madillc9c4e4e2020-04-02 10:29:52 -04001369class FramebufferTest : public ANGLETest
1370{};
1371
1372template <typename T>
1373void FillTexture2D(GLuint texture,
1374 GLsizei width,
1375 GLsizei height,
1376 const T &onePixelData,
1377 GLint level,
1378 GLint internalFormat,
1379 GLenum format,
1380 GLenum type)
1381{
1382 std::vector<T> allPixelsData(width * height, onePixelData);
1383
1384 glBindTexture(GL_TEXTURE_2D, texture);
1385 glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
1386 allPixelsData.data());
1387 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1388 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1389 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1390 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1391}
1392
1393// Multi-context uses of textures should not cause rendering feedback loops.
1394TEST_P(FramebufferTest, MultiContextNoRenderingFeedbackLoops)
1395{
1396 constexpr char kTextureVS[] =
1397 R"(attribute vec4 a_position;
1398varying vec2 v_texCoord;
1399void main() {
1400 gl_Position = a_position;
1401 v_texCoord = (a_position.xy * 0.5) + 0.5;
1402})";
1403
1404 constexpr char kTextureFS[] =
1405 R"(precision mediump float;
1406varying vec2 v_texCoord;
1407uniform sampler2D u_texture;
1408void main() {
1409 gl_FragColor = texture2D(u_texture, v_texCoord).rgba;
1410})";
1411
1412 ANGLE_GL_PROGRAM(textureProgram, kTextureVS, kTextureFS);
1413
1414 glUseProgram(textureProgram.get());
1415 GLint uniformLoc = glGetUniformLocation(textureProgram.get(), "u_texture");
1416 ASSERT_NE(-1, uniformLoc);
1417 glUniform1i(uniformLoc, 0);
1418
1419 GLTexture texture;
1420 FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1421 glBindTexture(GL_TEXTURE_2D, texture.get());
1422 // Note that _texture_ is still bound to GL_TEXTURE_2D in this context at this point.
1423
1424 EGLWindow *window = getEGLWindow();
1425 EGLDisplay display = window->getDisplay();
1426 EGLConfig config = window->getConfig();
1427 EGLSurface surface = window->getSurface();
1428 EGLint contextAttributes[] = {
1429 EGL_CONTEXT_MAJOR_VERSION_KHR,
1430 GetParam().majorVersion,
1431 EGL_CONTEXT_MINOR_VERSION_KHR,
1432 GetParam().minorVersion,
1433 EGL_NONE,
1434 };
1435 EGLContext context1 = eglGetCurrentContext();
1436 // Create context2, sharing resources with context1.
1437 EGLContext context2 = eglCreateContext(display, config, context1, contextAttributes);
1438 ASSERT_NE(context2, EGL_NO_CONTEXT);
1439 eglMakeCurrent(display, surface, surface, context2);
1440
1441 constexpr char kVS[] =
1442 R"(attribute vec4 a_position;
1443void main() {
1444 gl_Position = a_position;
1445})";
1446
1447 constexpr char kFS[] =
1448 R"(precision mediump float;
1449void main() {
1450 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
1451})";
1452
1453 ANGLE_GL_PROGRAM(program, kVS, kFS);
1454 glUseProgram(program.get());
1455
1456 ASSERT_GL_NO_ERROR();
1457
1458 // Render to the texture in context2.
1459 GLFramebuffer framebuffer;
1460 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1461 // Texture is still a valid name in context2.
1462 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
1463 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1464 // There is no rendering feedback loop at this point.
1465
1466 glDisable(GL_BLEND);
1467 glDisable(GL_DEPTH_TEST);
1468 ASSERT_GL_NO_ERROR();
1469
1470 // If draw is no-op'ed, texture will not be filled appropriately.
1471 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
1472 ASSERT_GL_NO_ERROR();
1473 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1474
1475 // Make context1 current again.
1476 eglMakeCurrent(display, surface, surface, context1);
1477
1478 // Render texture to screen.
1479 drawQuad(textureProgram.get(), "a_position", 0.5f, 1.0f, true);
1480 ASSERT_GL_NO_ERROR();
1481 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1482
1483 eglDestroyContext(display, context2);
1484}
1485
Jamie Madill2a0c3592020-03-31 15:36:45 -04001486// Ensure cube-incomplete attachments cause incomplete Framebuffers.
1487TEST_P(FramebufferTest, IncompleteCubeMap)
1488{
1489 constexpr GLuint kSize = 2;
1490
1491 GLTexture srcTex;
1492 glBindTexture(GL_TEXTURE_CUBE_MAP, srcTex);
1493 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
1494 GL_UNSIGNED_BYTE, nullptr);
1495
1496 GLFramebuffer fbo;
1497 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1498 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
1499 srcTex, 0);
1500
1501 ASSERT_GL_NO_ERROR();
1502 ASSERT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1503 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
1504}
1505
Tobin Ehlis1a01b4b2019-11-11 16:41:07 -07001506ANGLE_INSTANTIATE_TEST_ES2(AddDummyTextureNoRenderTargetTest);
Jamie Madillc9c4e4e2020-04-02 10:29:52 -04001507ANGLE_INSTANTIATE_TEST_ES2(FramebufferTest);
Shahbaz Youssefie28883d2020-01-25 23:25:43 -05001508ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
1509ANGLE_INSTANTIATE_TEST_ES3(FramebufferTest_ES3);
1510ANGLE_INSTANTIATE_TEST_ES31(FramebufferTest_ES31);