blob: f2e3a4f694827253079175e9598ab6be564b4d07 [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.
Tim Van Pattene8789a52020-07-29 12:01:49 -0600298 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Jamie Madill3215b202015-12-15 16:41:39 -0500299
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
Le Hoang Quyen349b6612020-07-08 12:50:00 +0800365// Test that a renderbuffer with RGB565 format works as expected. This test is intended for some
366// back-end having no support for native RGB565 renderbuffer and thus having to emulate using RGBA
367// format.
368TEST_P(FramebufferFormatsTest, RGB565Renderbuffer)
369{
370 GLRenderbuffer rbo;
371 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
372 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB565, 1, 1);
373
374 GLFramebuffer completeFBO;
375 glBindFramebuffer(GL_FRAMEBUFFER, completeFBO);
376 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
377
378 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
379
380 ASSERT_GL_NO_ERROR();
381
382 glClearColor(1, 0, 0, 0.5f);
383 glClear(GL_COLOR_BUFFER_BIT);
384 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
385}
386
Corentin Wallez57e6d502016-12-09 14:46:39 -0500387class FramebufferTest_ES3 : public ANGLETest
Jamie Madillb980c562018-11-27 11:34:27 -0500388{};
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500389
390// Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error.
Corentin Wallez57e6d502016-12-09 14:46:39 -0500391TEST_P(FramebufferTest_ES3, InvalidateIncomplete)
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500392{
Geoff Lang857c09d2017-05-16 15:55:04 -0400393 GLFramebuffer framebuffer;
394 GLRenderbuffer renderbuffer;
395
396 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
397 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
398 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500399 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
400 glCheckFramebufferStatus(GL_FRAMEBUFFER));
401
402 std::vector<GLenum> attachments;
403 attachments.push_back(GL_COLOR_ATTACHMENT0);
404
405 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
406 EXPECT_GL_NO_ERROR();
407}
408
Corentin Wallez57e6d502016-12-09 14:46:39 -0500409// Test that the framebuffer state tracking robustly handles a depth-only attachment being set
410// as a depth-stencil attachment. It is equivalent to detaching the depth-stencil attachment.
411TEST_P(FramebufferTest_ES3, DepthOnlyAsDepthStencil)
412{
Geoff Lang857c09d2017-05-16 15:55:04 -0400413 GLFramebuffer framebuffer;
414 GLRenderbuffer renderbuffer;
415
416 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
417 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
Corentin Wallez57e6d502016-12-09 14:46:39 -0500418 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 4, 4);
419
420 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
Geoff Lang857c09d2017-05-16 15:55:04 -0400421 renderbuffer);
Corentin Wallez57e6d502016-12-09 14:46:39 -0500422 EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
423}
424
Geoff Lang857c09d2017-05-16 15:55:04 -0400425// Test that the framebuffer correctly returns that it is not complete if invalid texture mip levels
426// are bound
427TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevels)
428{
429 GLFramebuffer framebuffer;
430 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
431
432 GLTexture texture;
433 glBindTexture(GL_TEXTURE_2D, texture);
434
435 // Create a complete mip chain in mips 1 to 3
436 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
437 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
438 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
439
440 // Create another complete mip chain in mips 4 to 5
441 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
442 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
443
444 // Create a non-complete mip chain in mip 6
445 glTexImage2D(GL_TEXTURE_2D, 6, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
446
447 // Incomplete, mipLevel != baseLevel and texture is not mip complete
448 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
449 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
450 glCheckFramebufferStatus(GL_FRAMEBUFFER));
451
452 // Complete, mipLevel == baseLevel
453 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
454 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
455
456 // Complete, mipLevel != baseLevel but texture is now mip complete
457 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2);
458 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
459 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3);
460 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
461
462 // Incomplete, attached level below the base level
463 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
464 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
465 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
466 glCheckFramebufferStatus(GL_FRAMEBUFFER));
467
468 // Incomplete, attached level is beyond effective max level
469 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 4);
470 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
471 glCheckFramebufferStatus(GL_FRAMEBUFFER));
472
473 // Complete, mipLevel == baseLevel
474 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
475 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
476
477 // Complete, mipLevel != baseLevel but texture is now mip complete
478 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 5);
479 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
480
481 // Complete, mipLevel == baseLevel
482 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 6);
483 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 6);
484 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
485}
486
Shahbaz Youssefidbb18b52020-06-05 15:23:17 -0400487TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBack)
488{
Kenneth Russell0bd0a912020-06-12 15:24:55 -0700489#if defined(ADDRESS_SANITIZER)
490 // http://anglebug.com/4737
491 ANGLE_SKIP_TEST_IF(IsOSX());
492#endif
493
Shahbaz Youssefidbb18b52020-06-05 15:23:17 -0400494 GLFramebuffer framebuffer;
495 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
496
497 GLTexture texture;
498 glBindTexture(GL_TEXTURE_2D, texture);
499
500 const std::array<GLColor, 2 * 2> mip0Data = {GLColor::red, GLColor::red, GLColor::red,
501 GLColor::red};
502 const std::array<GLColor, 1 * 1> mip1Data = {GLColor::green};
503
504 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data());
505 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data());
506
507 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
508 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
509 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
510
511 glClearColor(0, 0, 1.0f, 1.0f);
512 glClear(GL_COLOR_BUFFER_BIT);
513 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
514}
515
Courtney Goeltzenleuchter9a9ef0a2020-07-15 16:50:32 -0600516// TextureAttachmentMipLevelsReadBackWithDraw is a copy of TextureAttachmentMipLevelsReadBack except
517// for adding a draw after the last clear. The draw forces ANGLE's Vulkan backend to use the
518// framebuffer that is level 1 of the texture which will trigger the mismatch use of the GL level
519// and Vulkan level in referring to that rendertarget.
520TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBackWithDraw)
521{
522#if defined(ADDRESS_SANITIZER)
523 // http://anglebug.com/4737
524 ANGLE_SKIP_TEST_IF(IsOSX());
525#endif
526
527 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
528
529 GLFramebuffer framebuffer;
530 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
531
532 GLTexture texture;
533 glBindTexture(GL_TEXTURE_2D, texture);
534
535 const std::array<GLColor, 2 * 2> mip0Data = {GLColor::red, GLColor::red, GLColor::red,
536 GLColor::red};
537 const std::array<GLColor, 1 * 1> mip1Data = {GLColor::green};
538
539 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data());
540 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data());
541
542 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
543 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
544 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
545
546 glClearColor(0, 0, 1.0f, 1.0f);
547 glClear(GL_COLOR_BUFFER_BIT);
548
549 // This draw triggers the use of the framebuffer
550 glUseProgram(greenProgram);
551 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
552 ASSERT_GL_NO_ERROR();
553 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
554}
555
Martin Radevd178aa42017-07-13 14:03:22 +0300556// Test that passing an attachment COLOR_ATTACHMENTm where m is equal to MAX_COLOR_ATTACHMENTS
557// generates an INVALID_OPERATION.
558// OpenGL ES Version 3.0.5 (November 3, 2016), 4.4.2.4 Attaching Texture Images to a Framebuffer, p.
559// 208
560TEST_P(FramebufferTest_ES3, ColorAttachmentIndexOutOfBounds)
561{
562 GLFramebuffer framebuffer;
563 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
564
565 GLint maxColorAttachments = 0;
566 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
567 GLenum attachment = static_cast<GLenum>(maxColorAttachments + GL_COLOR_ATTACHMENT0);
568
569 GLTexture texture;
570 glBindTexture(GL_TEXTURE_2D, texture.get());
571 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
572 glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture.get(), 0);
573 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
574}
575
Jamie Madilla0016b72017-07-14 14:30:46 -0400576// Check that depth-only attachments report the correct number of samples.
577TEST_P(FramebufferTest_ES3, MultisampleDepthOnly)
578{
579 GLRenderbuffer renderbuffer;
580 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
581 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT24, 32, 32);
582
583 GLFramebuffer framebuffer;
584 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
585 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600586 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Jamie Madilla0016b72017-07-14 14:30:46 -0400587 EXPECT_GL_NO_ERROR();
588
589 GLint samples = 0;
590 glGetIntegerv(GL_SAMPLES, &samples);
591 EXPECT_GL_NO_ERROR();
592 EXPECT_GE(samples, 2);
593}
594
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700595// Check that we only compare width and height of attachments, not depth.
596TEST_P(FramebufferTest_ES3, AttachmentWith3DLayers)
597{
598 GLTexture texA;
599 glBindTexture(GL_TEXTURE_2D, texA);
600 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
601
602 GLTexture texB;
603 glBindTexture(GL_TEXTURE_3D, texB);
604 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
605
606 GLFramebuffer framebuffer;
607 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
608 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
609 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texB, 0, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600610 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700611 EXPECT_GL_NO_ERROR();
612}
613
Olli Etuahodbce1f82018-09-19 15:32:17 +0300614// Test that clearing the stencil buffer when the framebuffer only has a color attachment does not
615// crash.
616TEST_P(FramebufferTest_ES3, ClearNonexistentStencil)
617{
618 GLRenderbuffer rbo;
619 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
620 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
621
622 GLFramebuffer fbo;
623 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
624 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
625
626 GLint clearValue = 0;
627 glClearBufferiv(GL_STENCIL, 0, &clearValue);
628
629 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
630 EXPECT_GL_NO_ERROR();
631}
632
633// Test that clearing the depth buffer when the framebuffer only has a color attachment does not
634// crash.
635TEST_P(FramebufferTest_ES3, ClearNonexistentDepth)
636{
637 GLRenderbuffer rbo;
638 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
639 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
640
641 GLFramebuffer fbo;
642 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
643 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
644
645 GLfloat clearValue = 0.0f;
646 glClearBufferfv(GL_DEPTH, 0, &clearValue);
647
648 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
649 EXPECT_GL_NO_ERROR();
650}
651
652// Test that clearing a nonexistent color attachment does not crash.
653TEST_P(FramebufferTest_ES3, ClearNonexistentColor)
654{
655 GLRenderbuffer rbo;
656 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
657 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
658
659 GLFramebuffer fbo;
660 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
661 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
662
663 std::vector<GLfloat> clearValue = {{0.0f, 1.0f, 0.0f, 1.0f}};
664 glClearBufferfv(GL_COLOR, 1, clearValue.data());
665
666 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
667 EXPECT_GL_NO_ERROR();
668}
669
670// Test that clearing the depth and stencil buffers when the framebuffer only has a color attachment
671// does not crash.
672TEST_P(FramebufferTest_ES3, ClearNonexistentDepthStencil)
673{
674 GLRenderbuffer rbo;
675 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
676 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
677
678 GLFramebuffer fbo;
679 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
680 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
681
682 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
683
684 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
685 EXPECT_GL_NO_ERROR();
686}
687
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300688// Test that clearing a color attachment that has been deleted doesn't crash.
689TEST_P(FramebufferTest_ES3, ClearDeletedAttachment)
690{
691 // An INVALID_FRAMEBUFFER_OPERATION error was seen in this test on Mac, not sure where it might
692 // be originating from. http://anglebug.com/2834
693 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
694
695 GLFramebuffer fbo;
696 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
697
698 // There used to be a bug where some draw buffer state used to remain set even after the
699 // attachment was detached via deletion. That's why we create, attach and delete this RBO here.
700 GLuint rbo = 0u;
701 glGenRenderbuffers(1, &rbo);
702 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
703 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
704 glDeleteRenderbuffers(1, &rbo);
705
706 // There needs to be at least one color attachment to prevent early out from the clear calls.
707 GLRenderbuffer rbo2;
708 glBindRenderbuffer(GL_RENDERBUFFER, rbo2);
709 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
710 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rbo2);
711
712 ASSERT_GL_NO_ERROR();
713
714 // There's no error specified for clearing nonexistent buffers, it's simply a no-op, so we
715 // expect no GL errors below.
716 std::array<GLfloat, 4> floatClearValue = {0.0f, 0.0f, 0.0f, 0.0f};
717 glClearBufferfv(GL_COLOR, 0, floatClearValue.data());
718 EXPECT_GL_NO_ERROR();
719 std::array<GLuint, 4> uintClearValue = {0u, 0u, 0u, 0u};
720 glClearBufferuiv(GL_COLOR, 0, uintClearValue.data());
721 EXPECT_GL_NO_ERROR();
722 std::array<GLint, 4> intClearValue = {0, 0, 0, 0};
723 glClearBufferiv(GL_COLOR, 0, intClearValue.data());
724 EXPECT_GL_NO_ERROR();
725}
726
Tim Van Pattene600ac22019-10-04 14:31:57 -0600727// Test that resizing the color attachment is handled correctly.
728TEST_P(FramebufferTest_ES3, ResizeColorAttachmentSmallToLarge)
729{
730 GLFramebuffer fbo;
731 GLTexture smallTexture;
732 GLTexture largeTexture;
733
734 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
735 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
736
737 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
738
739 // Bind the small texture
740 glBindTexture(GL_TEXTURE_2D, smallTexture);
741 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
742 GL_UNSIGNED_BYTE, nullptr);
743 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
744 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
745 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600746 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600747
748 // Draw to FBO backed by the small texture
749 glUseProgram(greenProgram);
750 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
751 ASSERT_GL_NO_ERROR();
752 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
753 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
754
755 // Change the attachment to the larger texture that fills the window
756 glBindTexture(GL_TEXTURE_2D, largeTexture);
757 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
758 GL_UNSIGNED_BYTE, nullptr);
759 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
760 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
761 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600762 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600763
764 // Draw to FBO backed by the large texture
765 glUseProgram(blueProgram);
766 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
767 ASSERT_GL_NO_ERROR();
768 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
769 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
770}
771
772// Test that resizing the color attachment is handled correctly.
773TEST_P(FramebufferTest_ES3, ResizeColorAttachmentLargeToSmall)
774{
775 GLFramebuffer fbo;
776 GLTexture smallTexture;
777 GLTexture largeTexture;
778
779 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
780 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
781
782 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
783
784 // Bind the large texture
785 glBindTexture(GL_TEXTURE_2D, largeTexture);
786 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
787 GL_UNSIGNED_BYTE, nullptr);
788 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
789 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
790 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600791 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600792
793 // Draw to FBO backed by the large texture
794 glUseProgram(blueProgram);
795 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
796 ASSERT_GL_NO_ERROR();
797 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
798 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
799
800 // Change the attachment to the smaller texture
801 glBindTexture(GL_TEXTURE_2D, smallTexture);
802 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
803 GL_UNSIGNED_BYTE, nullptr);
804 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
805 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
806 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600807 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600808
809 // Draw to FBO backed by the small texture
810 glUseProgram(greenProgram);
811 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
812 ASSERT_GL_NO_ERROR();
813 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
814 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
815}
816
817// Test that resizing the texture is handled correctly.
818TEST_P(FramebufferTest_ES3, ResizeTextureLargeToSmall)
819{
820 GLFramebuffer fbo;
821 GLTexture texture;
822
823 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
824 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
825
826 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
827
828 // Allocate a large texture
829 glBindTexture(GL_TEXTURE_2D, texture);
830 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
831 GL_UNSIGNED_BYTE, nullptr);
832 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
833 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
834 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600835 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600836
837 // Draw to FBO backed by the large texture
838 glUseProgram(blueProgram);
839 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
840 ASSERT_GL_NO_ERROR();
841 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
842 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
843
844 // Shrink the texture
845 glBindTexture(GL_TEXTURE_2D, texture);
846 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
847 GL_UNSIGNED_BYTE, nullptr);
848 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
849 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
850 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600851 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600852
853 // Draw to FBO backed by the small texture
854 glUseProgram(greenProgram);
855 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
856 ASSERT_GL_NO_ERROR();
857 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
858 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
859}
860
861// Test that resizing the texture is handled correctly.
862TEST_P(FramebufferTest_ES3, ResizeTextureSmallToLarge)
863{
864 GLFramebuffer fbo;
865 GLTexture texture;
866
867 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
868 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
869
870 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
871
872 // Allocate a small texture
873 glBindTexture(GL_TEXTURE_2D, texture);
874 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
875 GL_UNSIGNED_BYTE, nullptr);
876 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
877 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
878 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600879 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600880
881 // Draw to FBO backed by the large texture
882 glUseProgram(blueProgram);
883 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
884 ASSERT_GL_NO_ERROR();
885 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
886 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::blue);
887
888 // Grow the texture
889 glBindTexture(GL_TEXTURE_2D, texture);
890 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
891 GL_UNSIGNED_BYTE, nullptr);
892 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
893 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
894 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600895 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600896
897 // Draw to FBO backed by the small texture
898 glUseProgram(greenProgram);
899 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
900 ASSERT_GL_NO_ERROR();
901 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
902 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
903}
904
Shahbaz Youssefie28883d2020-01-25 23:25:43 -0500905// Test that fewer outputs than framebuffer attachments doesn't crash. This causes a Vulkan
906// validation warning, but should not be fatal.
907TEST_P(FramebufferTest_ES3, FewerShaderOutputsThanAttachments)
908{
909 constexpr char kFS[] = R"(#version 300 es
910precision highp float;
911
912layout(location = 0) out vec4 color0;
913layout(location = 1) out vec4 color1;
914layout(location = 2) out vec4 color2;
915
916void main()
917{
918 color0 = vec4(1.0, 0.0, 0.0, 1.0);
919 color1 = vec4(0.0, 1.0, 0.0, 1.0);
920 color2 = vec4(0.0, 0.0, 1.0, 1.0);
921}
922)";
923
924 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
925
926 constexpr GLint kDrawBufferCount = 4;
927
928 GLint maxDrawBuffers;
929 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
930 ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
931
932 GLTexture textures[kDrawBufferCount];
933
934 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
935 {
936 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
937 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
938 GL_UNSIGNED_BYTE, nullptr);
939 }
940
941 GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,
942 GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
943
944 GLFramebuffer fbo;
945 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
946
947 // Enable all draw buffers.
948 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
949 {
950 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
951 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
952 textures[texIndex], 0);
953 }
954 glDrawBuffers(kDrawBufferCount, allBufs);
955
956 // Draw with simple program.
957 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
958 ASSERT_GL_NO_ERROR();
959}
JiangYizhou461d9a32017-01-04 16:37:26 +0800960
961class FramebufferTest_ES31 : public ANGLETest
962{
JiangYizhou511937d2017-08-03 15:41:29 +0800963 protected:
964 void validateSamplePass(GLuint &query, GLuint &passedCount, GLint width, GLint height)
965 {
966 glUniform2i(0, width - 1, height - 1);
967 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
968 glDrawArrays(GL_TRIANGLES, 0, 6);
969 glEndQuery(GL_ANY_SAMPLES_PASSED);
970 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
971 EXPECT_GT(static_cast<GLint>(passedCount), 0);
972
973 glUniform2i(0, width - 1, height);
974 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
975 glDrawArrays(GL_TRIANGLES, 0, 6);
976 glEndQuery(GL_ANY_SAMPLES_PASSED);
977 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
978 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
979
980 glUniform2i(0, width, height - 1);
981 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
982 glDrawArrays(GL_TRIANGLES, 0, 6);
983 glEndQuery(GL_ANY_SAMPLES_PASSED);
984 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
985 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
986 }
JiangYizhou461d9a32017-01-04 16:37:26 +0800987};
988
989// Test that without attachment, if either the value of FRAMEBUFFER_DEFAULT_WIDTH or
990// FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is incomplete.
991TEST_P(FramebufferTest_ES31, IncompleteMissingAttachmentDefaultParam)
992{
993 GLFramebuffer mFramebuffer;
994 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
995
996 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
997 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
998 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
999
1000 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
1001 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
1002 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
1003 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1004
1005 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
1006 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
1007 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
1008 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1009
1010 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
1011 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
1012 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
1013 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1014
1015 ASSERT_GL_NO_ERROR();
1016}
1017
1018// Test that the sample count of a mix of texture and renderbuffer should be same.
1019TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix)
1020{
1021 GLFramebuffer mFramebuffer;
1022 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1023
Ian Elliott5f857832019-12-04 15:30:50 -07001024 // Lookup the supported number of sample counts (rely on fact that ANGLE uses the same set of
1025 // sample counts for textures and renderbuffers)
1026 GLint numSampleCounts = 0;
1027 std::vector<GLint> sampleCounts;
1028 GLsizei queryBufferSize = 1;
1029 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
1030 queryBufferSize, &numSampleCounts);
1031 ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
1032 sampleCounts.resize(numSampleCounts);
1033 queryBufferSize = numSampleCounts;
1034 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
1035 sampleCounts.data());
1036
JiangYizhou461d9a32017-01-04 16:37:26 +08001037 GLTexture mTexture;
1038 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
Ian Elliott5f857832019-12-04 15:30:50 -07001039 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
JiangYizhou461d9a32017-01-04 16:37:26 +08001040
1041 GLRenderbuffer mRenderbuffer;
1042 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
Ian Elliott5f857832019-12-04 15:30:50 -07001043 glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCounts[1], GL_RGBA8, 1, 1);
JiangYizhou461d9a32017-01-04 16:37:26 +08001044 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1045 mTexture.get(), 0);
1046 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
1047 mRenderbuffer.get());
1048 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1049 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1050
1051 ASSERT_GL_NO_ERROR();
1052}
1053
1054// Test that the sample count of texture attachments should be same.
1055TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex)
1056{
1057 GLFramebuffer mFramebuffer;
1058 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1059
Ian Elliott5f857832019-12-04 15:30:50 -07001060 // Lookup the supported number of sample counts
1061 GLint numSampleCounts = 0;
1062 std::vector<GLint> sampleCounts;
1063 GLsizei queryBufferSize = 1;
1064 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
1065 queryBufferSize, &numSampleCounts);
1066 ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
1067 sampleCounts.resize(numSampleCounts);
1068 queryBufferSize = numSampleCounts;
1069 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
1070 sampleCounts.data());
1071
JiangYizhou461d9a32017-01-04 16:37:26 +08001072 GLTexture mTextures[2];
1073 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
Ian Elliott5f857832019-12-04 15:30:50 -07001074 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
JiangYizhou461d9a32017-01-04 16:37:26 +08001075 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
Ian Elliott5f857832019-12-04 15:30:50 -07001076 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[1], GL_RGBA8, 1, 1, true);
JiangYizhou461d9a32017-01-04 16:37:26 +08001077 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1078 mTextures[0].get(), 0);
1079 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1080 mTextures[1].get(), 0);
1081 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1082 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1083
1084 ASSERT_GL_NO_ERROR();
1085}
1086
1087// Test that if the attached images are a mix of renderbuffers and textures, the value of
1088// TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
1089TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsMix)
1090{
1091 GLFramebuffer mFramebuffer;
1092 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1093
1094 GLTexture mTexture;
1095 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
1096 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
1097
1098 GLRenderbuffer mRenderbuffer;
1099 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
1100 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
1101 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1102 mTexture.get(), 0);
1103 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
1104 mRenderbuffer.get());
1105 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1106 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1107
1108 ASSERT_GL_NO_ERROR();
1109}
1110
1111// Test that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures.
1112TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsTex)
1113{
1114 GLFramebuffer mFramebuffer;
1115 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1116
1117 GLTexture mTextures[2];
1118 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
1119 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
1120 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1121 mTextures[0].get(), 0);
1122 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
1123 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGB8, 1, 1, true);
1124 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1125 mTextures[1].get(), 0);
1126 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1127 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1128
1129 ASSERT_GL_NO_ERROR();
1130}
1131
Tim Van Pattendff47d52020-07-14 19:10:12 -06001132// Test resolving a multisampled texture with blit
1133TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlit)
1134{
1135 constexpr int kSize = 16;
1136 glViewport(0, 0, kSize, kSize);
1137
1138 GLFramebuffer msaaFBO;
1139 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1140
1141 GLTexture texture;
1142 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
1143 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1144 ASSERT_GL_NO_ERROR();
1145 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1146 texture.get(), 0);
1147 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1148
1149 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1150 essl31_shaders::fs::RedGreenGradient());
1151 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1152 ASSERT_GL_NO_ERROR();
1153
1154 // Create another FBO to resolve the multisample buffer into.
1155 GLTexture resolveTexture;
1156 GLFramebuffer resolveFBO;
1157 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1158 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1159 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1160 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1161 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1162 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1163 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1164 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1165 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1166
1167 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1168 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1169 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1170 ASSERT_GL_NO_ERROR();
1171
1172 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1173 EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 255, 1.0); // Black
1174 EXPECT_PIXEL_NEAR(kSize - 1, 1, 239, 0, 0, 255, 1.0); // Red
1175 EXPECT_PIXEL_NEAR(0, kSize - 1, 0, 239, 0, 255, 1.0); // Green
1176 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 239, 239, 0, 255, 1.0); // Yellow
1177}
1178
1179// Test resolving a multisampled texture with blit after drawing to mulitiple FBOs.
1180TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitMultipleFBOs)
1181{
1182 // FBO 1 -> multisample draw (red)
1183 // FBO 2 -> multisample draw (green)
1184 // Bind FBO 1 as read
1185 // Bind FBO 3 as draw
1186 // Resolve
1187
1188 constexpr int kSize = 16;
1189 glViewport(0, 0, kSize, kSize);
1190
1191 GLFramebuffer msaaFBORed;
1192 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBORed.get());
1193
1194 GLTexture textureRed;
1195 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureRed.get());
1196 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1197 ASSERT_GL_NO_ERROR();
1198 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1199 textureRed.get(), 0);
1200 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1201
1202 ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
1203 drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1204 ASSERT_GL_NO_ERROR();
1205
1206 GLFramebuffer msaaFBOGreen;
1207 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBOGreen.get());
1208
1209 GLTexture textureGreen;
1210 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureGreen.get());
1211 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1212 ASSERT_GL_NO_ERROR();
1213 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1214 textureGreen.get(), 0);
1215 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1216
1217 ANGLE_GL_PROGRAM(greenProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Green());
1218 drawQuad(greenProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1219 ASSERT_GL_NO_ERROR();
1220
1221 // Create another FBO to resolve the multisample buffer into.
1222 GLTexture resolveTexture;
1223 GLFramebuffer resolveFBO;
1224 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1225 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1226 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1227 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1229 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1230 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1231 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1232 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1233
1234 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
1235 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1236 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1237 ASSERT_GL_NO_ERROR();
1238
1239 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1240 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1241}
1242
1243// Test resolving a multisampled texture with blit after drawing to mulitiple FBOs.
1244TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitMultipleResolves)
1245{
1246 // Draw multisampled in FBO 1
1247 // Bind FBO 1 as read
1248 // Bind FBO 2 as draw
1249 // Resolve
1250 // Bind FBO 3 as draw
1251 // Resolve
1252
1253 constexpr int kSize = 16;
1254 glViewport(0, 0, kSize, kSize);
1255
1256 GLFramebuffer msaaFBORed;
1257 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBORed.get());
1258
1259 GLTexture textureRed;
1260 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureRed.get());
1261 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1262 ASSERT_GL_NO_ERROR();
1263 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1264 textureRed.get(), 0);
1265 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1266
1267 ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
1268 drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1269 ASSERT_GL_NO_ERROR();
1270
1271 // Create another FBO to resolve the multisample buffer into.
1272 GLTexture resolveTexture1;
1273 GLFramebuffer resolveFBO1;
1274 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
1275 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1276 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1277 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1278 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1280 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
1281 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
1282 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1283
1284 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
1285 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
1286 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1287 ASSERT_GL_NO_ERROR();
1288
1289 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
1290 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1291
1292 // Create another FBO to resolve the multisample buffer into.
1293 GLTexture resolveTexture2;
1294 GLFramebuffer resolveFBO2;
1295 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
1296 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1297 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1301 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
1302 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
1303 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1304
1305 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
1306 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
1307 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1308 ASSERT_GL_NO_ERROR();
1309
1310 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
1311 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1312}
1313
Tim Van Patten55593512020-08-11 14:23:32 -06001314// Test resolving a multisampled texture into a mipmaped texture with blit
1315TEST_P(FramebufferTest_ES31, MultisampleResolveIntoMipMapWithBlit)
1316{
1317 // FBO 1 is attached to a 64x64 texture
1318 // FBO 2 attached to level 1 of a 128x128 texture
1319
1320 constexpr int kSize = 64;
1321 glViewport(0, 0, kSize, kSize);
1322
1323 // Create the textures early and call glGenerateMipmap() so it doesn't break the render pass
1324 // between the drawQuad() and glBlitFramebuffer(), so we can test the resolve with subpass path
1325 // in the Vulkan back end.
1326 GLTexture texture;
1327 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
1328 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1329 ASSERT_GL_NO_ERROR();
1330
1331 GLTexture resolveTexture;
1332 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1333 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1334 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1335 ASSERT_GL_NO_ERROR();
1336 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1338 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1339 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1340
1341 GLFramebuffer msaaFBO;
1342 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1343 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1344 texture.get(), 0);
1345 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1346
1347 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1348 essl31_shaders::fs::RedGreenGradient());
1349 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1350 ASSERT_GL_NO_ERROR();
1351
1352 // Create another FBO to resolve the multisample buffer into.
1353 GLFramebuffer resolveFBO;
1354 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1355 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
1356 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1357
1358 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1359 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1360 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1361 ASSERT_GL_NO_ERROR();
1362
1363 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1364 EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 255, 1.0); // Black
1365 EXPECT_PIXEL_NEAR(kSize - 1, 1, 251, 0, 0, 255, 1.0); // Red
1366 EXPECT_PIXEL_NEAR(0, kSize - 1, 0, 251, 0, 255, 1.0); // Green
1367 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 251, 251, 0, 255, 1.0); // Yellow
1368}
1369
Tim Van Pattendff47d52020-07-14 19:10:12 -06001370// Test resolving a multisampled texture with blit after drawing to mulitiple FBOs.
1371TEST_P(FramebufferTest_ES31, MultipleTextureMultisampleResolveWithBlitMultipleResolves)
1372{
1373 // Attach two MSAA textures to FBO1
1374 // Set read buffer 0
1375 // Resolve into FBO2
1376 // Set read buffer 1
1377 // Resolve into FBO3
1378
1379 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
1380
1381 constexpr int kSize = 16;
1382 glViewport(0, 0, kSize, kSize);
1383
1384 GLFramebuffer msaaFBO;
1385 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1386
1387 GLTexture msaaTextureRed;
1388 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed.get());
1389 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1390 ASSERT_GL_NO_ERROR();
1391 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1392 msaaTextureRed.get(), 0);
1393 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1394
1395 GLTexture msaaTextureGreen;
1396 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen.get());
1397 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1398 ASSERT_GL_NO_ERROR();
1399 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1400 msaaTextureGreen.get(), 0);
1401 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1402
1403 // Setup program to render red into attachment 0 and green into attachment 1.
1404 const char *fs = R"(#extension GL_EXT_draw_buffers : enable
1405precision highp float;
1406void main()
1407{
1408 gl_FragData[0] = vec4(1.0, 0.0, 0.0, 1.0); // attachment 0: red
1409 gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0); // attachment 1: green
1410})";
1411 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fs);
1412 glUseProgram(program);
1413 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
1414 glDrawBuffers(2, kDrawBuffers);
1415
1416 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1417 ASSERT_GL_NO_ERROR();
1418
1419 // Create another FBO to resolve the multisample buffer into.
1420 GLTexture resolveTexture1;
1421 GLFramebuffer resolveFBO1;
1422 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
1423 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1424 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1425 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1426 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1427 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1428 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
1429 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
1430 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1431
1432 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1433 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
1434 glReadBuffer(GL_COLOR_ATTACHMENT0); // Red
1435 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1436 ASSERT_GL_NO_ERROR();
1437
1438 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
1439 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1440
1441 // Create another FBO to resolve the multisample buffer into.
1442 GLTexture resolveTexture2;
1443 GLFramebuffer resolveFBO2;
1444 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
1445 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1446 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1447 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1448 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1449 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1450 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
1451 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
1452 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1453
1454 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1455 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
1456 glReadBuffer(GL_COLOR_ATTACHMENT1); // Green
1457 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1458 ASSERT_GL_NO_ERROR();
1459
1460 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
1461 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1462}
1463
JiangYizhou511937d2017-08-03 15:41:29 +08001464// If there are no attachments, rendering will be limited to a rectangle having a lower left of
1465// (0, 0) and an upper right of(width, height), where width and height are the framebuffer
1466// object's default width and height.
JiangYizhou3db40722017-08-28 17:59:13 +08001467TEST_P(FramebufferTest_ES31, RenderingLimitToDefaultFBOSizeWithNoAttachments)
JiangYizhou511937d2017-08-03 15:41:29 +08001468{
Yuly Novikov98f9f532017-11-15 19:16:19 -05001469 // anglebug.com/2253
1470 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
Tim Van Patten626a7282019-07-08 15:11:59 -06001471 // Occlusion query reports fragments outside the render area are still rendered
1472 ANGLE_SKIP_TEST_IF(IsAndroid() || (IsWindows() && (IsIntel() || IsAMD())));
Yuly Novikov98f9f532017-11-15 19:16:19 -05001473
Jamie Madill35cd7332018-12-02 12:03:33 -05001474 constexpr char kVS1[] = R"(#version 310 es
1475in layout(location = 0) highp vec2 a_position;
1476void main()
1477{
1478 gl_Position = vec4(a_position, 0.0, 1.0);
1479})";
JiangYizhou511937d2017-08-03 15:41:29 +08001480
Jamie Madill35cd7332018-12-02 12:03:33 -05001481 constexpr char kFS1[] = R"(#version 310 es
1482uniform layout(location = 0) highp ivec2 u_expectedSize;
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001483out layout(location = 3) mediump vec4 f_color;
Jamie Madill35cd7332018-12-02 12:03:33 -05001484void main()
1485{
1486 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
1487 f_color = vec4(1.0, 0.5, 0.25, 1.0);
1488})";
JiangYizhou511937d2017-08-03 15:41:29 +08001489
Jamie Madill35cd7332018-12-02 12:03:33 -05001490 constexpr char kVS2[] = R"(#version 310 es
1491in layout(location = 0) highp vec2 a_position;
1492void main()
1493{
1494 gl_Position = vec4(a_position, 0.0, 1.0);
1495})";
JiangYizhou10d41392017-12-18 18:13:36 +08001496
Jamie Madill35cd7332018-12-02 12:03:33 -05001497 constexpr char kFS2[] = R"(#version 310 es
1498uniform layout(location = 0) highp ivec2 u_expectedSize;
1499out layout(location = 2) mediump vec4 f_color;
1500void main()
1501{
1502 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
1503 f_color = vec4(1.0, 0.5, 0.25, 1.0);
1504})";
JiangYizhou10d41392017-12-18 18:13:36 +08001505
Tim Van Pattendff47d52020-07-14 19:10:12 -06001506 ANGLE_GL_PROGRAM(program1, kVS1, kFS1);
1507 ANGLE_GL_PROGRAM(program2, kVS2, kFS2);
JiangYizhou10d41392017-12-18 18:13:36 +08001508
1509 glUseProgram(program1);
JiangYizhou511937d2017-08-03 15:41:29 +08001510
1511 GLFramebuffer mFramebuffer;
1512 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
1513 GLuint defaultWidth = 1;
1514 GLuint defaultHeight = 1;
1515
1516 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
1517 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
1518 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1519
1520 const float data[] = {
1521 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
1522 };
1523
1524 GLuint vertexArray = 0;
1525 GLuint vertexBuffer = 0;
1526 GLuint query = 0;
1527 GLuint passedCount = 0;
1528
1529 glGenQueries(1, &query);
1530 glGenVertexArrays(1, &vertexArray);
1531 glBindVertexArray(vertexArray);
1532
1533 glGenBuffers(1, &vertexBuffer);
1534 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1535 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1536
1537 glEnableVertexAttribArray(0);
1538 glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
JiangYizhou38d92b52017-09-13 13:47:52 +08001539 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
JiangYizhou511937d2017-08-03 15:41:29 +08001540
1541 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1542
JiangYizhou10d41392017-12-18 18:13:36 +08001543 glUseProgram(program2);
1544 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1545
1546 glUseProgram(program1);
JiangYizhou511937d2017-08-03 15:41:29 +08001547 // If fbo has attachments, the rendering size should be the same as its attachment.
1548 GLTexture mTexture;
1549 GLuint width = 2;
1550 GLuint height = 2;
1551 glBindTexture(GL_TEXTURE_2D, mTexture.get());
1552 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
JiangYizhou38d92b52017-09-13 13:47:52 +08001553
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001554 const GLenum bufs[] = {GL_NONE, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT3};
JiangYizhou38d92b52017-09-13 13:47:52 +08001555
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001556 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, mTexture.get(),
JiangYizhou511937d2017-08-03 15:41:29 +08001557 0);
1558 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001559 glDrawBuffers(4, bufs);
JiangYizhou511937d2017-08-03 15:41:29 +08001560
1561 validateSamplePass(query, passedCount, width, height);
1562
1563 // If fbo's attachment has been removed, the rendering size should be the same as framebuffer
1564 // default size.
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001565 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, 0, 0, 0);
JiangYizhou511937d2017-08-03 15:41:29 +08001566 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1567
1568 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1569
1570 glDisableVertexAttribArray(0);
1571 glBindBuffer(GL_ARRAY_BUFFER, 0);
1572 glBindVertexArray(0);
1573 glDeleteBuffers(1, &vertexBuffer);
1574 glDeleteVertexArrays(1, &vertexArray);
1575
1576 ASSERT_GL_NO_ERROR();
1577}
1578
Brandon Jones9fc87332017-12-13 15:46:52 -08001579class AddDummyTextureNoRenderTargetTest : public ANGLETest
1580{
1581 public:
1582 AddDummyTextureNoRenderTargetTest()
1583 {
1584 setWindowWidth(512);
1585 setWindowHeight(512);
1586 setConfigRedBits(8);
1587 setConfigGreenBits(8);
1588 setConfigBlueBits(8);
1589 setConfigAlphaBits(8);
1590 }
1591
Jonah Ryan-Daviseee67c62019-06-18 13:00:43 -04001592 void overrideWorkaroundsD3D(FeaturesD3D *features) override
Brandon Jones9fc87332017-12-13 15:46:52 -08001593 {
Jonah Ryan-Davisbeb0eb22019-06-14 15:10:33 -04001594 features->overrideFeatures({"add_dummy_texture_no_render_target"}, true);
Brandon Jones9fc87332017-12-13 15:46:52 -08001595 }
1596};
1597
1598// Test to verify workaround succeeds when no program outputs exist http://anglebug.com/2283
1599TEST_P(AddDummyTextureNoRenderTargetTest, NoProgramOutputWorkaround)
1600{
Jamie Madill35cd7332018-12-02 12:03:33 -05001601 constexpr char kVS[] = "void main() {}";
1602 constexpr char kFS[] = "void main() {}";
Brandon Jones9fc87332017-12-13 15:46:52 -08001603
Jamie Madill35cd7332018-12-02 12:03:33 -05001604 ANGLE_GL_PROGRAM(drawProgram, kVS, kFS);
Brandon Jones9fc87332017-12-13 15:46:52 -08001605
1606 glUseProgram(drawProgram);
1607
1608 glDrawArrays(GL_TRIANGLES, 0, 6);
1609
1610 ASSERT_GL_NO_ERROR();
1611}
1612
Jamie Madill4fb3c282020-03-19 19:10:45 -04001613// Covers a bug in ANGLE's Vulkan back-end framebuffer cache which ignored depth/stencil after
1614// calls to DrawBuffers.
1615TEST_P(FramebufferTest_ES3, AttachmentStateChange)
1616{
1617 constexpr GLuint kSize = 2;
1618
1619 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1620
1621 GLTexture colorTexture;
1622 glBindTexture(GL_TEXTURE_2D, colorTexture);
1623 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1624
1625 GLFramebuffer fbo;
1626 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1627 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
1628
1629 ASSERT_GL_NO_ERROR();
1630 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1631
1632 // First draw without a depth buffer.
1633 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1634
1635 GLRenderbuffer depthBuffer;
1636 glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
1637 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kSize, kSize);
1638
1639 // Bind just a renderbuffer and draw.
1640 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
1641
1642 ASSERT_GL_NO_ERROR();
1643 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1644
1645 glDrawBuffers(0, nullptr);
1646 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1647
1648 // Re-enable color buffer and draw one final time. This previously triggered a crash.
1649 GLenum drawBuffs = {GL_COLOR_ATTACHMENT0};
1650 glDrawBuffers(1, &drawBuffs);
1651
1652 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1653 ASSERT_GL_NO_ERROR();
1654 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1655}
1656
Jamie Madilld03b15b2020-03-26 17:22:18 -04001657// Tests that we can support a feedback loop between a depth textures and the depth buffer.
Jamie Madille689d312020-08-14 22:51:03 -04001658// The test emulates the read-only feedback loop in Manhattan.
1659TEST_P(FramebufferTest_ES3, ReadOnlyDepthFeedbackLoopSupported)
Jamie Madilld03b15b2020-03-26 17:22:18 -04001660{
1661 // Feedback loops not supported on D3D11 and may not ever be.
1662 ANGLE_SKIP_TEST_IF(IsD3D11());
1663
1664 // Also this particular test doesn't work on Android despite similar support in Manhattan.
1665 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1666
1667 constexpr GLuint kSize = 2;
1668 glViewport(0, 0, kSize, kSize);
1669
1670 constexpr char kFS[] = R"(precision mediump float;
1671varying vec2 v_texCoord;
1672uniform sampler2D depth;
1673void main()
1674{
1675 if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
1676 {
1677 gl_FragColor = vec4(0, 1, 0, 1);
1678 }
1679 else
1680 {
1681 gl_FragColor = vec4(1, 0, 0, 1);
1682 }
1683})";
1684
1685 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
1686
1687 GLFramebuffer framebuffer;
1688 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1689
1690 GLTexture colorTexture;
1691 glBindTexture(GL_TEXTURE_2D, colorTexture);
1692 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1693
1694 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1695 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1696 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
1697
1698 GLTexture depthTexture;
1699 glBindTexture(GL_TEXTURE_2D, depthTexture);
1700 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
1701 GL_UNSIGNED_INT, nullptr);
1702 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1703 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1704 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
1705
1706 ASSERT_GL_NO_ERROR();
1707 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1708
1709 // Clear depth to 0.5.
1710 glClearDepthf(0.5f);
1711 glClear(GL_DEPTH_BUFFER_BIT);
1712
Jamie Madille689d312020-08-14 22:51:03 -04001713 // Disable depth. Although this does not remove the feedback loop as defined by the
Jamie Madilld03b15b2020-03-26 17:22:18 -04001714 // spec it mimics what gfxbench does in its rendering tests.
1715 glDepthMask(false);
Jamie Madille689d312020-08-14 22:51:03 -04001716 glDisable(GL_DEPTH_TEST);
Jamie Madilld03b15b2020-03-26 17:22:18 -04001717
1718 // Verify we can sample the depth texture and get 0.5.
1719 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
1720
1721 ASSERT_GL_NO_ERROR();
1722 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1723}
1724
Jamie Madilldd00f162020-04-02 14:04:44 -04001725// Covers a bug in ANGLE's Vulkan back-end. Our VkFramebuffer cache would in some cases forget to
1726// check the draw states when computing a cache key.
1727TEST_P(FramebufferTest_ES3, DisabledAttachmentRedefinition)
1728{
1729 constexpr GLuint kSize = 2;
1730
1731 // Make a Framebuffer with two attachments with one enabled and one disabled.
1732 GLTexture texA, texB;
1733 glBindTexture(GL_TEXTURE_2D, texA);
1734 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1735 glBindTexture(GL_TEXTURE_2D, texB);
1736 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1737
1738 GLFramebuffer fbo;
1739 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1740 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
1741 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texB, 0);
1742
1743 // Mask out the second texture.
1744 constexpr GLenum kOneDrawBuf = GL_COLOR_ATTACHMENT0;
1745 glDrawBuffers(1, &kOneDrawBuf);
1746
1747 ASSERT_GL_NO_ERROR();
1748 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1749
1750 // Set up a very simple shader.
1751 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1752 glViewport(0, 0, kSize, kSize);
1753
1754 // Draw
1755 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1756 ASSERT_GL_NO_ERROR();
1757 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1758
1759 // Update the masked out attachment and draw again.
1760 std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
1761 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
1762 redPixels.data());
1763
1764 // Draw
1765 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1766 ASSERT_GL_NO_ERROR();
1767 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1768
1769 glReadBuffer(GL_COLOR_ATTACHMENT1);
1770 ASSERT_GL_NO_ERROR();
1771 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1772}
1773
Jamie Madillc9c4e4e2020-04-02 10:29:52 -04001774class FramebufferTest : public ANGLETest
1775{};
1776
1777template <typename T>
1778void FillTexture2D(GLuint texture,
1779 GLsizei width,
1780 GLsizei height,
1781 const T &onePixelData,
1782 GLint level,
1783 GLint internalFormat,
1784 GLenum format,
1785 GLenum type)
1786{
1787 std::vector<T> allPixelsData(width * height, onePixelData);
1788
1789 glBindTexture(GL_TEXTURE_2D, texture);
1790 glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
1791 allPixelsData.data());
1792 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1793 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1794 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1795 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1796}
1797
1798// Multi-context uses of textures should not cause rendering feedback loops.
1799TEST_P(FramebufferTest, MultiContextNoRenderingFeedbackLoops)
1800{
1801 constexpr char kTextureVS[] =
1802 R"(attribute vec4 a_position;
1803varying vec2 v_texCoord;
1804void main() {
1805 gl_Position = a_position;
1806 v_texCoord = (a_position.xy * 0.5) + 0.5;
1807})";
1808
1809 constexpr char kTextureFS[] =
1810 R"(precision mediump float;
1811varying vec2 v_texCoord;
1812uniform sampler2D u_texture;
1813void main() {
1814 gl_FragColor = texture2D(u_texture, v_texCoord).rgba;
1815})";
1816
1817 ANGLE_GL_PROGRAM(textureProgram, kTextureVS, kTextureFS);
1818
1819 glUseProgram(textureProgram.get());
1820 GLint uniformLoc = glGetUniformLocation(textureProgram.get(), "u_texture");
1821 ASSERT_NE(-1, uniformLoc);
1822 glUniform1i(uniformLoc, 0);
1823
1824 GLTexture texture;
1825 FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
1826 glBindTexture(GL_TEXTURE_2D, texture.get());
1827 // Note that _texture_ is still bound to GL_TEXTURE_2D in this context at this point.
1828
1829 EGLWindow *window = getEGLWindow();
1830 EGLDisplay display = window->getDisplay();
1831 EGLConfig config = window->getConfig();
1832 EGLSurface surface = window->getSurface();
1833 EGLint contextAttributes[] = {
1834 EGL_CONTEXT_MAJOR_VERSION_KHR,
1835 GetParam().majorVersion,
1836 EGL_CONTEXT_MINOR_VERSION_KHR,
1837 GetParam().minorVersion,
1838 EGL_NONE,
1839 };
1840 EGLContext context1 = eglGetCurrentContext();
1841 // Create context2, sharing resources with context1.
1842 EGLContext context2 = eglCreateContext(display, config, context1, contextAttributes);
1843 ASSERT_NE(context2, EGL_NO_CONTEXT);
1844 eglMakeCurrent(display, surface, surface, context2);
1845
1846 constexpr char kVS[] =
1847 R"(attribute vec4 a_position;
1848void main() {
1849 gl_Position = a_position;
1850})";
1851
1852 constexpr char kFS[] =
1853 R"(precision mediump float;
1854void main() {
1855 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
1856})";
1857
1858 ANGLE_GL_PROGRAM(program, kVS, kFS);
1859 glUseProgram(program.get());
1860
1861 ASSERT_GL_NO_ERROR();
1862
1863 // Render to the texture in context2.
1864 GLFramebuffer framebuffer;
1865 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
1866 // Texture is still a valid name in context2.
1867 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -06001868 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Jamie Madillc9c4e4e2020-04-02 10:29:52 -04001869 // There is no rendering feedback loop at this point.
1870
1871 glDisable(GL_BLEND);
1872 glDisable(GL_DEPTH_TEST);
1873 ASSERT_GL_NO_ERROR();
1874
1875 // If draw is no-op'ed, texture will not be filled appropriately.
1876 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
1877 ASSERT_GL_NO_ERROR();
1878 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1879
1880 // Make context1 current again.
1881 eglMakeCurrent(display, surface, surface, context1);
1882
1883 // Render texture to screen.
1884 drawQuad(textureProgram.get(), "a_position", 0.5f, 1.0f, true);
1885 ASSERT_GL_NO_ERROR();
1886 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1887
1888 eglDestroyContext(display, context2);
1889}
1890
Jamie Madill2a0c3592020-03-31 15:36:45 -04001891// Ensure cube-incomplete attachments cause incomplete Framebuffers.
1892TEST_P(FramebufferTest, IncompleteCubeMap)
1893{
1894 constexpr GLuint kSize = 2;
1895
1896 GLTexture srcTex;
1897 glBindTexture(GL_TEXTURE_CUBE_MAP, srcTex);
1898 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
1899 GL_UNSIGNED_BYTE, nullptr);
1900
1901 GLFramebuffer fbo;
1902 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1903 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
1904 srcTex, 0);
1905
1906 ASSERT_GL_NO_ERROR();
1907 ASSERT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
1908 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
1909}
1910
Tim Van Pattene8789a52020-07-29 12:01:49 -06001911// Test FBOs with different sizes are drawn correctly
1912TEST_P(FramebufferTest, BindAndDrawDifferentSizedFBOs)
1913{
1914 // 1. Create FBO 1 with dimensions 16x16
1915 // 2. Draw red into FBO 1 (note, FramebufferVk::syncState is called)
1916 // 3. Create FBO 2 with dimensions 8x8
1917 // 4. Draw green into FBO 2 (note, FramebufferVk::syncState is called)
1918 // 5. Bind FBO 1 (note, it's not dirty)
1919 // 6. Draw blue into FBO 1
1920 // 7. Verify FBO 1 is entirely blue
1921
1922 GLFramebuffer smallFbo;
1923 GLFramebuffer largeFbo;
1924 GLTexture smallTexture;
1925 GLTexture largeTexture;
1926 constexpr GLsizei kLargeWidth = 16;
1927 constexpr GLsizei kLargeHeight = 16;
1928 constexpr GLsizei kSmallWidth = 8;
1929 constexpr GLsizei kSmallHeight = 8;
1930
1931 ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1932 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1933 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1934
1935 // 1. Create FBO 1 with dimensions 16x16
1936 glBindFramebuffer(GL_FRAMEBUFFER, largeFbo);
1937 glBindTexture(GL_TEXTURE_2D, largeTexture);
1938 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kLargeWidth, kLargeHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1939 nullptr);
1940 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1941 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1942 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
1943 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1944
1945 // 2. Draw red into FBO 1 (note, FramebufferVk::syncState is called)
1946 glUseProgram(redProgram);
1947 drawQuad(redProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
1948 ASSERT_GL_NO_ERROR();
1949
1950 // 3. Create FBO 2 with dimensions 8x8
1951 glBindFramebuffer(GL_FRAMEBUFFER, smallFbo);
1952 glBindTexture(GL_TEXTURE_2D, smallTexture);
1953 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallWidth, kSmallHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1954 nullptr);
1955 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1956 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1957 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
1958 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1959
1960 // 4. Draw green into FBO 2 (note, FramebufferVk::syncState is called)
1961 glUseProgram(greenProgram);
1962 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
1963 ASSERT_GL_NO_ERROR();
1964
1965 // 5. Bind FBO 1 (note, it's not dirty)
1966 glBindFramebuffer(GL_FRAMEBUFFER, largeFbo);
1967
1968 // 6. Draw blue into FBO 1
1969 glUseProgram(blueProgram);
1970 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
1971 ASSERT_GL_NO_ERROR();
1972
1973 // 7. Verify FBO 1 is entirely blue
1974 EXPECT_PIXEL_RECT_EQ(0, 0, kLargeWidth, kLargeHeight, GLColor::blue);
1975}
1976
Tobin Ehlis1a01b4b2019-11-11 16:41:07 -07001977ANGLE_INSTANTIATE_TEST_ES2(AddDummyTextureNoRenderTargetTest);
Jamie Madillc9c4e4e2020-04-02 10:29:52 -04001978ANGLE_INSTANTIATE_TEST_ES2(FramebufferTest);
Shahbaz Youssefie28883d2020-01-25 23:25:43 -05001979ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
1980ANGLE_INSTANTIATE_TEST_ES3(FramebufferTest_ES3);
1981ANGLE_INSTANTIATE_TEST_ES31(FramebufferTest_ES31);