blob: de6b391f22fc03fcd77cb43bbdeb90dd5bfb1b78 [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
Shahbaz Youssefi33f8e4d2020-08-25 12:06:35 -0400409// Covers sub-invalidating an incomplete framebuffer. This should be a no-op, but should not error.
410TEST_P(FramebufferTest_ES3, SubInvalidateIncomplete)
411{
412 GLFramebuffer framebuffer;
413 GLRenderbuffer renderbuffer;
414
415 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
416 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
417 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
418 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
419 glCheckFramebufferStatus(GL_FRAMEBUFFER));
420
421 std::vector<GLenum> attachments;
422 attachments.push_back(GL_COLOR_ATTACHMENT0);
423
424 glInvalidateSubFramebuffer(GL_FRAMEBUFFER, 1, attachments.data(), 5, 5, 10, 10);
425 EXPECT_GL_NO_ERROR();
426}
427
Corentin Wallez57e6d502016-12-09 14:46:39 -0500428// Test that the framebuffer state tracking robustly handles a depth-only attachment being set
429// as a depth-stencil attachment. It is equivalent to detaching the depth-stencil attachment.
430TEST_P(FramebufferTest_ES3, DepthOnlyAsDepthStencil)
431{
Geoff Lang857c09d2017-05-16 15:55:04 -0400432 GLFramebuffer framebuffer;
433 GLRenderbuffer renderbuffer;
434
435 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
436 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
Corentin Wallez57e6d502016-12-09 14:46:39 -0500437 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 4, 4);
438
439 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
Geoff Lang857c09d2017-05-16 15:55:04 -0400440 renderbuffer);
Corentin Wallez57e6d502016-12-09 14:46:39 -0500441 EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
442}
443
Geoff Lang857c09d2017-05-16 15:55:04 -0400444// Test that the framebuffer correctly returns that it is not complete if invalid texture mip levels
445// are bound
446TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevels)
447{
448 GLFramebuffer framebuffer;
449 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
450
451 GLTexture texture;
452 glBindTexture(GL_TEXTURE_2D, texture);
453
454 // Create a complete mip chain in mips 1 to 3
455 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
456 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
457 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
458
459 // Create another complete mip chain in mips 4 to 5
460 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
461 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
462
463 // Create a non-complete mip chain in mip 6
464 glTexImage2D(GL_TEXTURE_2D, 6, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
465
466 // Incomplete, mipLevel != baseLevel and texture is not mip complete
467 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
468 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
469 glCheckFramebufferStatus(GL_FRAMEBUFFER));
470
471 // Complete, mipLevel == baseLevel
472 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
473 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
474
475 // Complete, mipLevel != baseLevel but texture is now mip complete
476 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2);
477 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
478 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3);
479 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
480
481 // Incomplete, attached level below the base level
482 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
483 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
484 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
485 glCheckFramebufferStatus(GL_FRAMEBUFFER));
486
487 // Incomplete, attached level is beyond effective max level
488 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 4);
489 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
490 glCheckFramebufferStatus(GL_FRAMEBUFFER));
491
492 // Complete, mipLevel == baseLevel
493 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
494 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
495
496 // Complete, mipLevel != baseLevel but texture is now mip complete
497 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 5);
498 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
499
500 // Complete, mipLevel == baseLevel
501 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 6);
502 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 6);
503 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
504}
505
Shahbaz Youssefidbb18b52020-06-05 15:23:17 -0400506TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBack)
507{
Kenneth Russell0bd0a912020-06-12 15:24:55 -0700508#if defined(ADDRESS_SANITIZER)
509 // http://anglebug.com/4737
510 ANGLE_SKIP_TEST_IF(IsOSX());
511#endif
512
Shahbaz Youssefidbb18b52020-06-05 15:23:17 -0400513 GLFramebuffer framebuffer;
514 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
515
516 GLTexture texture;
517 glBindTexture(GL_TEXTURE_2D, texture);
518
519 const std::array<GLColor, 2 * 2> mip0Data = {GLColor::red, GLColor::red, GLColor::red,
520 GLColor::red};
521 const std::array<GLColor, 1 * 1> mip1Data = {GLColor::green};
522
523 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data());
524 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data());
525
526 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
527 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
528 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
529
530 glClearColor(0, 0, 1.0f, 1.0f);
531 glClear(GL_COLOR_BUFFER_BIT);
532 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
533}
534
Courtney Goeltzenleuchter9a9ef0a2020-07-15 16:50:32 -0600535// TextureAttachmentMipLevelsReadBackWithDraw is a copy of TextureAttachmentMipLevelsReadBack except
536// for adding a draw after the last clear. The draw forces ANGLE's Vulkan backend to use the
537// framebuffer that is level 1 of the texture which will trigger the mismatch use of the GL level
538// and Vulkan level in referring to that rendertarget.
539TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevelsReadBackWithDraw)
540{
541#if defined(ADDRESS_SANITIZER)
542 // http://anglebug.com/4737
543 ANGLE_SKIP_TEST_IF(IsOSX());
544#endif
545
546 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
547
548 GLFramebuffer framebuffer;
549 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
550
551 GLTexture texture;
552 glBindTexture(GL_TEXTURE_2D, texture);
553
554 const std::array<GLColor, 2 * 2> mip0Data = {GLColor::red, GLColor::red, GLColor::red,
555 GLColor::red};
556 const std::array<GLColor, 1 * 1> mip1Data = {GLColor::green};
557
558 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip0Data.data());
559 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip1Data.data());
560
561 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
562 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
563 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
564
565 glClearColor(0, 0, 1.0f, 1.0f);
566 glClear(GL_COLOR_BUFFER_BIT);
567
568 // This draw triggers the use of the framebuffer
569 glUseProgram(greenProgram);
570 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
571 ASSERT_GL_NO_ERROR();
572 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
573}
574
Martin Radevd178aa42017-07-13 14:03:22 +0300575// Test that passing an attachment COLOR_ATTACHMENTm where m is equal to MAX_COLOR_ATTACHMENTS
576// generates an INVALID_OPERATION.
577// OpenGL ES Version 3.0.5 (November 3, 2016), 4.4.2.4 Attaching Texture Images to a Framebuffer, p.
578// 208
579TEST_P(FramebufferTest_ES3, ColorAttachmentIndexOutOfBounds)
580{
581 GLFramebuffer framebuffer;
582 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
583
584 GLint maxColorAttachments = 0;
585 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
586 GLenum attachment = static_cast<GLenum>(maxColorAttachments + GL_COLOR_ATTACHMENT0);
587
588 GLTexture texture;
589 glBindTexture(GL_TEXTURE_2D, texture.get());
590 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
591 glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture.get(), 0);
592 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
593}
594
Jamie Madilla0016b72017-07-14 14:30:46 -0400595// Check that depth-only attachments report the correct number of samples.
596TEST_P(FramebufferTest_ES3, MultisampleDepthOnly)
597{
598 GLRenderbuffer renderbuffer;
599 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
600 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT24, 32, 32);
601
602 GLFramebuffer framebuffer;
603 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
604 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600605 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Jamie Madilla0016b72017-07-14 14:30:46 -0400606 EXPECT_GL_NO_ERROR();
607
608 GLint samples = 0;
609 glGetIntegerv(GL_SAMPLES, &samples);
610 EXPECT_GL_NO_ERROR();
611 EXPECT_GE(samples, 2);
612}
613
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700614// Check that we only compare width and height of attachments, not depth.
615TEST_P(FramebufferTest_ES3, AttachmentWith3DLayers)
616{
617 GLTexture texA;
618 glBindTexture(GL_TEXTURE_2D, texA);
619 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
620
621 GLTexture texB;
622 glBindTexture(GL_TEXTURE_3D, texB);
623 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 4, 4, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
624
625 GLFramebuffer framebuffer;
626 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
627 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
628 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texB, 0, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600629 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700630 EXPECT_GL_NO_ERROR();
631}
632
Olli Etuahodbce1f82018-09-19 15:32:17 +0300633// Test that clearing the stencil buffer when the framebuffer only has a color attachment does not
634// crash.
635TEST_P(FramebufferTest_ES3, ClearNonexistentStencil)
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 GLint clearValue = 0;
646 glClearBufferiv(GL_STENCIL, 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 the depth buffer when the framebuffer only has a color attachment does not
653// crash.
654TEST_P(FramebufferTest_ES3, ClearNonexistentDepth)
655{
656 GLRenderbuffer rbo;
657 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
658 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
659
660 GLFramebuffer fbo;
661 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
662 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
663
664 GLfloat clearValue = 0.0f;
665 glClearBufferfv(GL_DEPTH, 0, &clearValue);
666
667 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
668 EXPECT_GL_NO_ERROR();
669}
670
671// Test that clearing a nonexistent color attachment does not crash.
672TEST_P(FramebufferTest_ES3, ClearNonexistentColor)
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 std::vector<GLfloat> clearValue = {{0.0f, 1.0f, 0.0f, 1.0f}};
683 glClearBufferfv(GL_COLOR, 1, clearValue.data());
684
685 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
686 EXPECT_GL_NO_ERROR();
687}
688
689// Test that clearing the depth and stencil buffers when the framebuffer only has a color attachment
690// does not crash.
691TEST_P(FramebufferTest_ES3, ClearNonexistentDepthStencil)
692{
693 GLRenderbuffer rbo;
694 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
695 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
696
697 GLFramebuffer fbo;
698 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
699 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
700
701 glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
702
703 // There's no error specified for clearing nonexistent buffers, it's simply a no-op.
704 EXPECT_GL_NO_ERROR();
705}
706
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300707// Test that clearing a color attachment that has been deleted doesn't crash.
708TEST_P(FramebufferTest_ES3, ClearDeletedAttachment)
709{
710 // An INVALID_FRAMEBUFFER_OPERATION error was seen in this test on Mac, not sure where it might
711 // be originating from. http://anglebug.com/2834
712 ANGLE_SKIP_TEST_IF(IsOSX() && IsOpenGL());
713
714 GLFramebuffer fbo;
715 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
716
717 // There used to be a bug where some draw buffer state used to remain set even after the
718 // attachment was detached via deletion. That's why we create, attach and delete this RBO here.
719 GLuint rbo = 0u;
720 glGenRenderbuffers(1, &rbo);
721 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
722 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
723 glDeleteRenderbuffers(1, &rbo);
724
725 // There needs to be at least one color attachment to prevent early out from the clear calls.
726 GLRenderbuffer rbo2;
727 glBindRenderbuffer(GL_RENDERBUFFER, rbo2);
728 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
729 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rbo2);
730
731 ASSERT_GL_NO_ERROR();
732
733 // There's no error specified for clearing nonexistent buffers, it's simply a no-op, so we
734 // expect no GL errors below.
735 std::array<GLfloat, 4> floatClearValue = {0.0f, 0.0f, 0.0f, 0.0f};
736 glClearBufferfv(GL_COLOR, 0, floatClearValue.data());
737 EXPECT_GL_NO_ERROR();
738 std::array<GLuint, 4> uintClearValue = {0u, 0u, 0u, 0u};
739 glClearBufferuiv(GL_COLOR, 0, uintClearValue.data());
740 EXPECT_GL_NO_ERROR();
741 std::array<GLint, 4> intClearValue = {0, 0, 0, 0};
742 glClearBufferiv(GL_COLOR, 0, intClearValue.data());
743 EXPECT_GL_NO_ERROR();
744}
745
Tim Van Pattene600ac22019-10-04 14:31:57 -0600746// Test that resizing the color attachment is handled correctly.
747TEST_P(FramebufferTest_ES3, ResizeColorAttachmentSmallToLarge)
748{
749 GLFramebuffer fbo;
750 GLTexture smallTexture;
751 GLTexture largeTexture;
752
753 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
754 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
755
756 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
757
758 // Bind the small texture
759 glBindTexture(GL_TEXTURE_2D, smallTexture);
760 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
761 GL_UNSIGNED_BYTE, nullptr);
762 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
763 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
764 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600765 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600766
767 // Draw to FBO backed by the small texture
768 glUseProgram(greenProgram);
769 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
770 ASSERT_GL_NO_ERROR();
771 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
772 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
773
774 // Change the attachment to the larger texture that fills the window
775 glBindTexture(GL_TEXTURE_2D, largeTexture);
776 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
777 GL_UNSIGNED_BYTE, nullptr);
778 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
779 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
780 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600781 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600782
783 // Draw to FBO backed by the large texture
784 glUseProgram(blueProgram);
785 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
786 ASSERT_GL_NO_ERROR();
787 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
788 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
789}
790
791// Test that resizing the color attachment is handled correctly.
792TEST_P(FramebufferTest_ES3, ResizeColorAttachmentLargeToSmall)
793{
794 GLFramebuffer fbo;
795 GLTexture smallTexture;
796 GLTexture largeTexture;
797
798 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
799 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
800
801 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
802
803 // Bind the large texture
804 glBindTexture(GL_TEXTURE_2D, largeTexture);
805 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
806 GL_UNSIGNED_BYTE, nullptr);
807 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
808 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
809 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600810 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600811
812 // Draw to FBO backed by the large texture
813 glUseProgram(blueProgram);
814 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
815 ASSERT_GL_NO_ERROR();
816 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
817 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
818
819 // Change the attachment to the smaller texture
820 glBindTexture(GL_TEXTURE_2D, smallTexture);
821 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
822 GL_UNSIGNED_BYTE, nullptr);
823 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
824 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
825 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600826 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600827
828 // Draw to FBO backed by the small texture
829 glUseProgram(greenProgram);
830 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
831 ASSERT_GL_NO_ERROR();
832 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
833 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
834}
835
836// Test that resizing the texture is handled correctly.
837TEST_P(FramebufferTest_ES3, ResizeTextureLargeToSmall)
838{
839 GLFramebuffer fbo;
840 GLTexture texture;
841
842 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
843 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
844
845 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
846
847 // Allocate a large texture
848 glBindTexture(GL_TEXTURE_2D, texture);
849 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
850 GL_UNSIGNED_BYTE, nullptr);
851 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
852 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
853 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600854 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600855
856 // Draw to FBO backed by the large texture
857 glUseProgram(blueProgram);
858 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
859 ASSERT_GL_NO_ERROR();
860 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
861 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::blue);
862
863 // Shrink the texture
864 glBindTexture(GL_TEXTURE_2D, texture);
865 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
866 GL_UNSIGNED_BYTE, nullptr);
867 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
868 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
869 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600870 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600871
872 // Draw to FBO backed by the small texture
873 glUseProgram(greenProgram);
874 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
875 ASSERT_GL_NO_ERROR();
876 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
877 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::green);
878}
879
880// Test that resizing the texture is handled correctly.
881TEST_P(FramebufferTest_ES3, ResizeTextureSmallToLarge)
882{
883 GLFramebuffer fbo;
884 GLTexture texture;
885
886 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
887 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
888
889 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
890
891 // Allocate a small texture
892 glBindTexture(GL_TEXTURE_2D, texture);
893 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth() / 2, getWindowHeight() / 2, 0, GL_RGBA,
894 GL_UNSIGNED_BYTE, nullptr);
895 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
896 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
897 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600898 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600899
900 // Draw to FBO backed by the large texture
901 glUseProgram(blueProgram);
902 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
903 ASSERT_GL_NO_ERROR();
904 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
905 EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 1, (getWindowHeight() / 2) - 1, GLColor::blue);
906
907 // Grow the texture
908 glBindTexture(GL_TEXTURE_2D, texture);
909 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
910 GL_UNSIGNED_BYTE, nullptr);
911 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
912 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
913 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -0600914 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Tim Van Pattene600ac22019-10-04 14:31:57 -0600915
916 // Draw to FBO backed by the small texture
917 glUseProgram(greenProgram);
918 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
919 ASSERT_GL_NO_ERROR();
920 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
921 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
922}
923
Shahbaz Youssefie28883d2020-01-25 23:25:43 -0500924// Test that fewer outputs than framebuffer attachments doesn't crash. This causes a Vulkan
925// validation warning, but should not be fatal.
926TEST_P(FramebufferTest_ES3, FewerShaderOutputsThanAttachments)
927{
928 constexpr char kFS[] = R"(#version 300 es
929precision highp float;
930
931layout(location = 0) out vec4 color0;
932layout(location = 1) out vec4 color1;
933layout(location = 2) out vec4 color2;
934
935void main()
936{
937 color0 = vec4(1.0, 0.0, 0.0, 1.0);
938 color1 = vec4(0.0, 1.0, 0.0, 1.0);
939 color2 = vec4(0.0, 0.0, 1.0, 1.0);
940}
941)";
942
943 ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
944
945 constexpr GLint kDrawBufferCount = 4;
946
947 GLint maxDrawBuffers;
948 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
949 ASSERT_GE(maxDrawBuffers, kDrawBufferCount);
950
951 GLTexture textures[kDrawBufferCount];
952
953 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
954 {
955 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
956 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
957 GL_UNSIGNED_BYTE, nullptr);
958 }
959
960 GLenum allBufs[kDrawBufferCount] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1,
961 GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
962
963 GLFramebuffer fbo;
964 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
965
966 // Enable all draw buffers.
967 for (GLint texIndex = 0; texIndex < kDrawBufferCount; ++texIndex)
968 {
969 glBindTexture(GL_TEXTURE_2D, textures[texIndex]);
970 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + texIndex, GL_TEXTURE_2D,
971 textures[texIndex], 0);
972 }
973 glDrawBuffers(kDrawBufferCount, allBufs);
974
975 // Draw with simple program.
976 drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
977 ASSERT_GL_NO_ERROR();
978}
JiangYizhou461d9a32017-01-04 16:37:26 +0800979
980class FramebufferTest_ES31 : public ANGLETest
981{
JiangYizhou511937d2017-08-03 15:41:29 +0800982 protected:
983 void validateSamplePass(GLuint &query, GLuint &passedCount, GLint width, GLint height)
984 {
985 glUniform2i(0, width - 1, height - 1);
986 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
987 glDrawArrays(GL_TRIANGLES, 0, 6);
988 glEndQuery(GL_ANY_SAMPLES_PASSED);
989 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
990 EXPECT_GT(static_cast<GLint>(passedCount), 0);
991
992 glUniform2i(0, width - 1, height);
993 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
994 glDrawArrays(GL_TRIANGLES, 0, 6);
995 glEndQuery(GL_ANY_SAMPLES_PASSED);
996 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
997 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
998
999 glUniform2i(0, width, height - 1);
1000 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
1001 glDrawArrays(GL_TRIANGLES, 0, 6);
1002 glEndQuery(GL_ANY_SAMPLES_PASSED);
1003 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
1004 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
1005 }
Shahbaz Yousseficba9bbb2020-09-02 09:55:31 -04001006
1007 static constexpr char kFSWriteRedGreen[] = R"(#extension GL_EXT_draw_buffers : enable
1008precision highp float;
1009void main()
1010{
1011 gl_FragData[0] = vec4(1.0, 0.0, 0.0, 1.0); // attachment 0: red
1012 gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0); // attachment 1: green
1013})";
JiangYizhou461d9a32017-01-04 16:37:26 +08001014};
1015
Shahbaz Yousseficba9bbb2020-09-02 09:55:31 -04001016// Until C++17, need to redundantly declare the constexpr array members outside the class.
1017constexpr char FramebufferTest_ES31::kFSWriteRedGreen[];
1018
JiangYizhou461d9a32017-01-04 16:37:26 +08001019// Test that without attachment, if either the value of FRAMEBUFFER_DEFAULT_WIDTH or
1020// FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is incomplete.
1021TEST_P(FramebufferTest_ES31, IncompleteMissingAttachmentDefaultParam)
1022{
1023 GLFramebuffer mFramebuffer;
1024 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1025
1026 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
1027 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
1028 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1029
1030 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
1031 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
1032 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
1033 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1034
1035 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
1036 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
1037 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
1038 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1039
1040 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
1041 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
1042 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
1043 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1044
1045 ASSERT_GL_NO_ERROR();
1046}
1047
1048// Test that the sample count of a mix of texture and renderbuffer should be same.
1049TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix)
1050{
1051 GLFramebuffer mFramebuffer;
1052 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1053
Ian Elliott5f857832019-12-04 15:30:50 -07001054 // Lookup the supported number of sample counts (rely on fact that ANGLE uses the same set of
1055 // sample counts for textures and renderbuffers)
1056 GLint numSampleCounts = 0;
1057 std::vector<GLint> sampleCounts;
1058 GLsizei queryBufferSize = 1;
1059 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
1060 queryBufferSize, &numSampleCounts);
1061 ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
1062 sampleCounts.resize(numSampleCounts);
1063 queryBufferSize = numSampleCounts;
1064 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
1065 sampleCounts.data());
1066
JiangYizhou461d9a32017-01-04 16:37:26 +08001067 GLTexture mTexture;
1068 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
Ian Elliott5f857832019-12-04 15:30:50 -07001069 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
JiangYizhou461d9a32017-01-04 16:37:26 +08001070
1071 GLRenderbuffer mRenderbuffer;
1072 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
Ian Elliott5f857832019-12-04 15:30:50 -07001073 glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCounts[1], GL_RGBA8, 1, 1);
JiangYizhou461d9a32017-01-04 16:37:26 +08001074 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1075 mTexture.get(), 0);
1076 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
1077 mRenderbuffer.get());
1078 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1079 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1080
1081 ASSERT_GL_NO_ERROR();
1082}
1083
1084// Test that the sample count of texture attachments should be same.
1085TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex)
1086{
1087 GLFramebuffer mFramebuffer;
1088 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1089
Ian Elliott5f857832019-12-04 15:30:50 -07001090 // Lookup the supported number of sample counts
1091 GLint numSampleCounts = 0;
1092 std::vector<GLint> sampleCounts;
1093 GLsizei queryBufferSize = 1;
1094 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
1095 queryBufferSize, &numSampleCounts);
1096 ANGLE_SKIP_TEST_IF((numSampleCounts < 2));
1097 sampleCounts.resize(numSampleCounts);
1098 queryBufferSize = numSampleCounts;
1099 glGetInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_RGBA8, GL_SAMPLES, queryBufferSize,
1100 sampleCounts.data());
1101
JiangYizhou461d9a32017-01-04 16:37:26 +08001102 GLTexture mTextures[2];
1103 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
Ian Elliott5f857832019-12-04 15:30:50 -07001104 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[0], GL_RGBA8, 1, 1, true);
JiangYizhou461d9a32017-01-04 16:37:26 +08001105 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
Ian Elliott5f857832019-12-04 15:30:50 -07001106 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, sampleCounts[1], GL_RGBA8, 1, 1, true);
JiangYizhou461d9a32017-01-04 16:37:26 +08001107 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1108 mTextures[0].get(), 0);
1109 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1110 mTextures[1].get(), 0);
1111 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1112 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1113
1114 ASSERT_GL_NO_ERROR();
1115}
1116
1117// Test that if the attached images are a mix of renderbuffers and textures, the value of
1118// TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
1119TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsMix)
1120{
1121 GLFramebuffer mFramebuffer;
1122 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1123
1124 GLTexture mTexture;
1125 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
1126 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
1127
1128 GLRenderbuffer mRenderbuffer;
1129 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
1130 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
1131 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1132 mTexture.get(), 0);
1133 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
1134 mRenderbuffer.get());
1135 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1136 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1137
1138 ASSERT_GL_NO_ERROR();
1139}
1140
1141// Test that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures.
1142TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsTex)
1143{
1144 GLFramebuffer mFramebuffer;
1145 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
1146
1147 GLTexture mTextures[2];
1148 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
1149 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
1150 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1151 mTextures[0].get(), 0);
1152 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
1153 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGB8, 1, 1, true);
1154 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1155 mTextures[1].get(), 0);
1156 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1157 glCheckFramebufferStatus(GL_FRAMEBUFFER));
1158
1159 ASSERT_GL_NO_ERROR();
1160}
1161
Tim Van Pattendff47d52020-07-14 19:10:12 -06001162// Test resolving a multisampled texture with blit
1163TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlit)
1164{
1165 constexpr int kSize = 16;
1166 glViewport(0, 0, kSize, kSize);
1167
1168 GLFramebuffer msaaFBO;
1169 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1170
1171 GLTexture texture;
1172 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
1173 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1174 ASSERT_GL_NO_ERROR();
1175 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1176 texture.get(), 0);
1177 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1178
1179 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1180 essl31_shaders::fs::RedGreenGradient());
1181 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1182 ASSERT_GL_NO_ERROR();
1183
1184 // Create another FBO to resolve the multisample buffer into.
1185 GLTexture resolveTexture;
1186 GLFramebuffer resolveFBO;
1187 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1188 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Tim Van Pattendff47d52020-07-14 19:10:12 -06001189 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1190 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1191 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1192
1193 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1194 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1195 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1196 ASSERT_GL_NO_ERROR();
1197
1198 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1199 EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 255, 1.0); // Black
1200 EXPECT_PIXEL_NEAR(kSize - 1, 1, 239, 0, 0, 255, 1.0); // Red
1201 EXPECT_PIXEL_NEAR(0, kSize - 1, 0, 239, 0, 255, 1.0); // Green
1202 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 239, 239, 0, 255, 1.0); // Yellow
1203}
1204
Shahbaz Youssefid701eae2020-09-02 12:23:21 -04001205// Test resolving a multisampled texture with blit to a different format
1206TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitDifferentFormats)
1207{
1208 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888"));
1209
1210 constexpr int kSize = 16;
1211 glViewport(0, 0, kSize, kSize);
1212
1213 GLFramebuffer msaaFBO;
1214 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1215
1216 GLTexture texture;
1217 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
1218 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1219 ASSERT_GL_NO_ERROR();
1220 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1221 texture.get(), 0);
1222 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1223
1224 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1225 essl31_shaders::fs::RedGreenGradient());
1226 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1227 ASSERT_GL_NO_ERROR();
1228
1229 // Create another FBO to resolve the multisample buffer into.
1230 GLTexture resolveTexture;
1231 GLFramebuffer resolveFBO;
1232 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1233 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA8_EXT, kSize, kSize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
1234 nullptr);
1235 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1236 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1237 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1238
1239 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1240 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1241 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1242 ASSERT_GL_NO_ERROR();
1243
1244 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1245 EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 255, 1.0); // Black
1246 EXPECT_PIXEL_NEAR(kSize - 1, 1, 239, 0, 0, 255, 1.0); // Red
1247 EXPECT_PIXEL_NEAR(0, kSize - 1, 0, 239, 0, 255, 1.0); // Green
1248 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 239, 239, 0, 255, 1.0); // Yellow
1249}
1250
Tim Van Pattendff47d52020-07-14 19:10:12 -06001251// Test resolving a multisampled texture with blit after drawing to mulitiple FBOs.
1252TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitMultipleFBOs)
1253{
1254 // FBO 1 -> multisample draw (red)
1255 // FBO 2 -> multisample draw (green)
1256 // Bind FBO 1 as read
1257 // Bind FBO 3 as draw
1258 // Resolve
1259
1260 constexpr int kSize = 16;
1261 glViewport(0, 0, kSize, kSize);
1262
1263 GLFramebuffer msaaFBORed;
1264 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBORed.get());
1265
1266 GLTexture textureRed;
1267 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureRed.get());
1268 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1269 ASSERT_GL_NO_ERROR();
1270 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1271 textureRed.get(), 0);
1272 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1273
1274 ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
1275 drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1276 ASSERT_GL_NO_ERROR();
1277
1278 GLFramebuffer msaaFBOGreen;
1279 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBOGreen.get());
1280
1281 GLTexture textureGreen;
1282 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureGreen.get());
1283 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1284 ASSERT_GL_NO_ERROR();
1285 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1286 textureGreen.get(), 0);
1287 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1288
1289 ANGLE_GL_PROGRAM(greenProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Green());
1290 drawQuad(greenProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1291 ASSERT_GL_NO_ERROR();
1292
1293 // Create another FBO to resolve the multisample buffer into.
1294 GLTexture resolveTexture;
1295 GLFramebuffer resolveFBO;
1296 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1297 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Tim Van Pattendff47d52020-07-14 19:10:12 -06001298 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1299 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1300 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1301
1302 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
1303 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1304 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1305 ASSERT_GL_NO_ERROR();
1306
1307 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1308 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1309}
1310
1311// Test resolving a multisampled texture with blit after drawing to mulitiple FBOs.
1312TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitMultipleResolves)
1313{
1314 // Draw multisampled in FBO 1
1315 // Bind FBO 1 as read
1316 // Bind FBO 2 as draw
1317 // Resolve
1318 // Bind FBO 3 as draw
1319 // Resolve
1320
1321 constexpr int kSize = 16;
1322 glViewport(0, 0, kSize, kSize);
1323
1324 GLFramebuffer msaaFBORed;
1325 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBORed.get());
1326
1327 GLTexture textureRed;
1328 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureRed.get());
1329 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1330 ASSERT_GL_NO_ERROR();
1331 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1332 textureRed.get(), 0);
1333 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1334
1335 ANGLE_GL_PROGRAM(redProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
1336 drawQuad(redProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1337 ASSERT_GL_NO_ERROR();
1338
1339 // Create another FBO to resolve the multisample buffer into.
1340 GLTexture resolveTexture1;
1341 GLFramebuffer resolveFBO1;
1342 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
1343 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Tim Van Pattendff47d52020-07-14 19:10:12 -06001344 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
1345 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
1346 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1347
1348 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
1349 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
1350 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1351 ASSERT_GL_NO_ERROR();
1352
1353 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
1354 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1355
1356 // Create another FBO to resolve the multisample buffer into.
1357 GLTexture resolveTexture2;
1358 GLFramebuffer resolveFBO2;
1359 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
1360 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Tim Van Pattendff47d52020-07-14 19:10:12 -06001361 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
1362 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
1363 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1364
1365 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBORed);
1366 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
1367 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1368 ASSERT_GL_NO_ERROR();
1369
1370 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
1371 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1372}
1373
Tim Van Patten55593512020-08-11 14:23:32 -06001374// Test resolving a multisampled texture into a mipmaped texture with blit
1375TEST_P(FramebufferTest_ES31, MultisampleResolveIntoMipMapWithBlit)
1376{
1377 // FBO 1 is attached to a 64x64 texture
1378 // FBO 2 attached to level 1 of a 128x128 texture
1379
1380 constexpr int kSize = 64;
1381 glViewport(0, 0, kSize, kSize);
1382
1383 // Create the textures early and call glGenerateMipmap() so it doesn't break the render pass
1384 // between the drawQuad() and glBlitFramebuffer(), so we can test the resolve with subpass path
1385 // in the Vulkan back end.
1386 GLTexture texture;
1387 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
1388 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1389 ASSERT_GL_NO_ERROR();
1390
1391 GLTexture resolveTexture;
1392 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1393 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1394 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1395 ASSERT_GL_NO_ERROR();
Tim Van Patten55593512020-08-11 14:23:32 -06001396
1397 GLFramebuffer msaaFBO;
1398 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1399 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1400 texture.get(), 0);
1401 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1402
1403 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1404 essl31_shaders::fs::RedGreenGradient());
1405 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1406 ASSERT_GL_NO_ERROR();
1407
1408 // Create another FBO to resolve the multisample buffer into.
1409 GLFramebuffer resolveFBO;
1410 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1411 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 1);
1412 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1413
1414 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1415 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1416 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1417 ASSERT_GL_NO_ERROR();
1418
1419 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1420 EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 255, 1.0); // Black
1421 EXPECT_PIXEL_NEAR(kSize - 1, 1, 251, 0, 0, 255, 1.0); // Red
1422 EXPECT_PIXEL_NEAR(0, kSize - 1, 0, 251, 0, 255, 1.0); // Green
1423 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 251, 251, 0, 255, 1.0); // Yellow
1424}
1425
Shahbaz Youssefi543a3962020-09-02 09:40:10 -04001426// Test resolving a multisampled texture with blit after drawing to multiple FBOs.
Tim Van Pattendff47d52020-07-14 19:10:12 -06001427TEST_P(FramebufferTest_ES31, MultipleTextureMultisampleResolveWithBlitMultipleResolves)
1428{
1429 // Attach two MSAA textures to FBO1
1430 // Set read buffer 0
1431 // Resolve into FBO2
1432 // Set read buffer 1
1433 // Resolve into FBO3
1434
1435 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
1436
1437 constexpr int kSize = 16;
1438 glViewport(0, 0, kSize, kSize);
1439
1440 GLFramebuffer msaaFBO;
1441 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1442
1443 GLTexture msaaTextureRed;
1444 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed.get());
1445 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1446 ASSERT_GL_NO_ERROR();
1447 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1448 msaaTextureRed.get(), 0);
1449 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1450
1451 GLTexture msaaTextureGreen;
1452 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen.get());
1453 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1454 ASSERT_GL_NO_ERROR();
1455 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1456 msaaTextureGreen.get(), 0);
1457 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1458
1459 // Setup program to render red into attachment 0 and green into attachment 1.
Shahbaz Yousseficba9bbb2020-09-02 09:55:31 -04001460 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
Tim Van Pattendff47d52020-07-14 19:10:12 -06001461 glUseProgram(program);
1462 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
1463 glDrawBuffers(2, kDrawBuffers);
1464
1465 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1466 ASSERT_GL_NO_ERROR();
1467
1468 // Create another FBO to resolve the multisample buffer into.
1469 GLTexture resolveTexture1;
1470 GLFramebuffer resolveFBO1;
1471 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
1472 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Tim Van Pattendff47d52020-07-14 19:10:12 -06001473 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
1474 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
1475 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1476
1477 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1478 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
1479 glReadBuffer(GL_COLOR_ATTACHMENT0); // Red
1480 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1481 ASSERT_GL_NO_ERROR();
1482
1483 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
1484 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1485
1486 // Create another FBO to resolve the multisample buffer into.
1487 GLTexture resolveTexture2;
1488 GLFramebuffer resolveFBO2;
1489 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
1490 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Tim Van Pattendff47d52020-07-14 19:10:12 -06001491 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
1492 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
1493 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1494
1495 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1496 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
1497 glReadBuffer(GL_COLOR_ATTACHMENT1); // Green
1498 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1499 ASSERT_GL_NO_ERROR();
1500
1501 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
1502 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1503}
1504
Shahbaz Youssefi543a3962020-09-02 09:40:10 -04001505// Test resolving a multisampled texture with blit after drawing to multiple FBOs, with color
1506// attachment 1 resolved first.
1507TEST_P(FramebufferTest_ES31,
1508 MultipleTextureMultisampleResolveWithBlitMultipleResolvesAttachment1First)
1509{
1510 // Attach two MSAA textures to FBO1
1511 // Set read buffer 1
1512 // Resolve into FBO2
1513 // Set read buffer 0
1514 // Resolve into FBO3
1515
1516 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
1517
1518 constexpr int kSize = 16;
1519 glViewport(0, 0, kSize, kSize);
1520
1521 GLFramebuffer msaaFBO;
1522 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1523
1524 GLTexture msaaTextureRed;
1525 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed.get());
1526 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1527 ASSERT_GL_NO_ERROR();
1528 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1529 msaaTextureRed.get(), 0);
1530 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1531
1532 GLTexture msaaTextureGreen;
1533 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen.get());
1534 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1535 ASSERT_GL_NO_ERROR();
1536 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1537 msaaTextureGreen.get(), 0);
1538 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1539
1540 // Setup program to render red into attachment 0 and green into attachment 1.
Shahbaz Yousseficba9bbb2020-09-02 09:55:31 -04001541 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
Shahbaz Youssefi543a3962020-09-02 09:40:10 -04001542 glUseProgram(program);
1543 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
1544 glDrawBuffers(2, kDrawBuffers);
1545
1546 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1547 ASSERT_GL_NO_ERROR();
1548
1549 // Create another FBO to resolve the multisample buffer into.
1550 GLTexture resolveTexture1;
1551 GLFramebuffer resolveFBO1;
1552 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
1553 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1554 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
1555 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
1556 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1557
1558 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1559 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
1560 glReadBuffer(GL_COLOR_ATTACHMENT1); // Green
1561 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1562 ASSERT_GL_NO_ERROR();
1563
1564 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
1565 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1566
1567 // Create another FBO to resolve the multisample buffer into.
1568 GLTexture resolveTexture2;
1569 GLFramebuffer resolveFBO2;
1570 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
1571 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1572 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
1573 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
1574 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1575
1576 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1577 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
1578 glReadBuffer(GL_COLOR_ATTACHMENT0); // Red
1579 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1580 ASSERT_GL_NO_ERROR();
1581
1582 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
1583 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1584}
1585
Shahbaz Yousseficba9bbb2020-09-02 09:55:31 -04001586// Test resolving a multisampled texture with blit, then drawing multisampled again. The latter
1587// should not get re-resolved automatically.
1588TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDraw)
1589{
1590 constexpr int kSize = 16;
1591 glViewport(0, 0, kSize, kSize);
1592
1593 GLFramebuffer msaaFBO;
1594 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1595
1596 GLTexture texture;
1597 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
1598 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1599 ASSERT_GL_NO_ERROR();
1600 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1601 texture.get(), 0);
1602 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1603
1604 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1605 essl31_shaders::fs::RedGreenGradient());
1606 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1607 ASSERT_GL_NO_ERROR();
1608
1609 // Create another FBO to resolve the multisample buffer into.
1610 GLTexture resolveTexture;
1611 GLFramebuffer resolveFBO;
1612 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1613 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1614 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1615 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1616 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1617
1618 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1619 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1620 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1621 ASSERT_GL_NO_ERROR();
1622
1623 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1624 EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 255, 1.0); // Black
1625 EXPECT_PIXEL_NEAR(kSize - 1, 1, 239, 0, 0, 255, 1.0); // Red
1626 EXPECT_PIXEL_NEAR(0, kSize - 1, 0, 239, 0, 255, 1.0); // Green
1627 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 239, 239, 0, 255, 1.0); // Yellow
1628
1629 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
1630 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
1631 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1632 ASSERT_GL_NO_ERROR();
1633
1634 // The resolved FBO should be unaffected by the last draw call.
1635 EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 255, 1.0); // Black
1636 EXPECT_PIXEL_NEAR(kSize - 1, 1, 239, 0, 0, 255, 1.0); // Red
1637 EXPECT_PIXEL_NEAR(0, kSize - 1, 0, 239, 0, 255, 1.0); // Green
1638 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 239, 239, 0, 255, 1.0); // Yellow
1639}
1640
1641// Test resolving a multisampled texture with blit, then drawing multisampled again. The latter
1642// should not get re-resolved automatically. Resoloves color attachment 1.
1643TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawAttachment1)
1644{
1645 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_draw_buffers"));
1646
1647 constexpr int kSize = 16;
1648 glViewport(0, 0, kSize, kSize);
1649
1650 GLFramebuffer msaaFBO;
1651 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1652
1653 GLTexture msaaTextureRed;
1654 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureRed.get());
1655 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1656 ASSERT_GL_NO_ERROR();
1657 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1658 msaaTextureRed.get(), 0);
1659 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1660
1661 GLTexture msaaTextureGreen;
1662 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTextureGreen.get());
1663 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1664 ASSERT_GL_NO_ERROR();
1665 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
1666 msaaTextureGreen.get(), 0);
1667 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1668
1669 // Setup program to render red into attachment 0 and green into attachment 1.
1670 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFSWriteRedGreen);
1671 glUseProgram(program);
1672 constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
1673 glDrawBuffers(2, kDrawBuffers);
1674
1675 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1676 ASSERT_GL_NO_ERROR();
1677
1678 // Create another FBO to resolve the multisample buffer into.
1679 GLTexture resolveTexture;
1680 GLFramebuffer resolveFBO;
1681 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1682 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1683 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1684 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1685 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1686
1687 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1688 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1689 glReadBuffer(GL_COLOR_ATTACHMENT1); // Green
1690 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1691 ASSERT_GL_NO_ERROR();
1692
1693 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1694 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1695 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
1696 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
1697 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
1698
1699 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
1700 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
1701 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1702 ASSERT_GL_NO_ERROR();
1703
1704 // The resolved FBO should be unaffected by the last draw call.
1705 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1706 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::green);
1707 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::green);
1708 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::green);
1709}
1710
1711// Test resolving a multisampled texture with blit, then drawing multisampled again and resolving to
1712// same framebuffer.
1713TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawThenResolveAgain)
1714{
1715 constexpr int kSize = 16;
1716 glViewport(0, 0, kSize, kSize);
1717
1718 GLFramebuffer msaaFBO;
1719 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1720
1721 GLTexture texture;
1722 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
1723 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1724 ASSERT_GL_NO_ERROR();
1725 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1726 texture.get(), 0);
1727 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1728
1729 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1730 essl31_shaders::fs::RedGreenGradient());
1731 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1732 ASSERT_GL_NO_ERROR();
1733
1734 // Create another FBO to resolve the multisample buffer into.
1735 GLTexture resolveTexture;
1736 GLFramebuffer resolveFBO;
1737 glBindTexture(GL_TEXTURE_2D, resolveTexture);
1738 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1739 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
1740 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
1741 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1742
1743 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1744 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1745 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1746 ASSERT_GL_NO_ERROR();
1747
1748 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1749 EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 255, 1.0); // Black
1750 EXPECT_PIXEL_NEAR(kSize - 1, 1, 239, 0, 0, 255, 1.0); // Red
1751 EXPECT_PIXEL_NEAR(0, kSize - 1, 0, 239, 0, 255, 1.0); // Green
1752 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 239, 239, 0, 255, 1.0); // Yellow
1753
1754 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
1755 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
1756 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1757 ASSERT_GL_NO_ERROR();
1758
1759 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1760 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
1761 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1762 ASSERT_GL_NO_ERROR();
1763
1764 // Verify that the resolve happened correctly
1765 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
1766 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1767 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
1768 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
1769 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
1770}
1771
1772// Test resolving a multisampled texture with blit, then drawing multisampled again and resolving to
1773// another framebuffer.
1774TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlitThenDrawThenResolveAgainToDifferentFBO)
1775{
1776 constexpr int kSize = 16;
1777 glViewport(0, 0, kSize, kSize);
1778
1779 GLFramebuffer msaaFBO;
1780 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
1781
1782 GLTexture texture;
1783 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
1784 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
1785 ASSERT_GL_NO_ERROR();
1786 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1787 texture.get(), 0);
1788 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1789
1790 ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
1791 essl31_shaders::fs::RedGreenGradient());
1792 drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1793 ASSERT_GL_NO_ERROR();
1794
1795 // Create another FBO to resolve the multisample buffer into.
1796 GLTexture resolveTexture1;
1797 GLFramebuffer resolveFBO1;
1798 glBindTexture(GL_TEXTURE_2D, resolveTexture1);
1799 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1800 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO1);
1801 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture1, 0);
1802 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1803
1804 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1805 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO1);
1806 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1807 ASSERT_GL_NO_ERROR();
1808
1809 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
1810 EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 255, 1.0); // Black
1811 EXPECT_PIXEL_NEAR(kSize - 1, 1, 239, 0, 0, 255, 1.0); // Red
1812 EXPECT_PIXEL_NEAR(0, kSize - 1, 0, 239, 0, 255, 1.0); // Green
1813 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 239, 239, 0, 255, 1.0); // Yellow
1814
1815 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msaaFBO);
1816 ANGLE_GL_PROGRAM(blueProgram, essl3_shaders::vs::Passthrough(), essl3_shaders::fs::Blue());
1817 drawQuad(blueProgram, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
1818 ASSERT_GL_NO_ERROR();
1819
1820 // Create another FBO to resolve the multisample buffer into.
1821 GLTexture resolveTexture2;
1822 GLFramebuffer resolveFBO2;
1823 glBindTexture(GL_TEXTURE_2D, resolveTexture2);
1824 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1825 glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO2);
1826 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture2, 0);
1827 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1828
1829 glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
1830 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO2);
1831 glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1832 ASSERT_GL_NO_ERROR();
1833
1834 // Verify that the resolve happened to the correct FBO
1835 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO2);
1836 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1837 EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::blue);
1838 EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::blue);
1839 EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::blue);
1840
1841 // The first resolve FBO should be untouched.
1842 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO1);
1843 EXPECT_PIXEL_NEAR(0, 0, 0, 0, 0, 255, 1.0); // Black
1844 EXPECT_PIXEL_NEAR(kSize - 1, 1, 239, 0, 0, 255, 1.0); // Red
1845 EXPECT_PIXEL_NEAR(0, kSize - 1, 0, 239, 0, 255, 1.0); // Green
1846 EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 239, 239, 0, 255, 1.0); // Yellow
1847}
1848
JiangYizhou511937d2017-08-03 15:41:29 +08001849// If there are no attachments, rendering will be limited to a rectangle having a lower left of
1850// (0, 0) and an upper right of(width, height), where width and height are the framebuffer
1851// object's default width and height.
JiangYizhou3db40722017-08-28 17:59:13 +08001852TEST_P(FramebufferTest_ES31, RenderingLimitToDefaultFBOSizeWithNoAttachments)
JiangYizhou511937d2017-08-03 15:41:29 +08001853{
Yuly Novikov98f9f532017-11-15 19:16:19 -05001854 // anglebug.com/2253
1855 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
Tim Van Patten626a7282019-07-08 15:11:59 -06001856 // Occlusion query reports fragments outside the render area are still rendered
1857 ANGLE_SKIP_TEST_IF(IsAndroid() || (IsWindows() && (IsIntel() || IsAMD())));
Yuly Novikov98f9f532017-11-15 19:16:19 -05001858
Jamie Madill35cd7332018-12-02 12:03:33 -05001859 constexpr char kVS1[] = R"(#version 310 es
1860in layout(location = 0) highp vec2 a_position;
1861void main()
1862{
1863 gl_Position = vec4(a_position, 0.0, 1.0);
1864})";
JiangYizhou511937d2017-08-03 15:41:29 +08001865
Jamie Madill35cd7332018-12-02 12:03:33 -05001866 constexpr char kFS1[] = R"(#version 310 es
1867uniform layout(location = 0) highp ivec2 u_expectedSize;
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001868out layout(location = 3) mediump vec4 f_color;
Jamie Madill35cd7332018-12-02 12:03:33 -05001869void main()
1870{
1871 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
1872 f_color = vec4(1.0, 0.5, 0.25, 1.0);
1873})";
JiangYizhou511937d2017-08-03 15:41:29 +08001874
Jamie Madill35cd7332018-12-02 12:03:33 -05001875 constexpr char kVS2[] = R"(#version 310 es
1876in layout(location = 0) highp vec2 a_position;
1877void main()
1878{
1879 gl_Position = vec4(a_position, 0.0, 1.0);
1880})";
JiangYizhou10d41392017-12-18 18:13:36 +08001881
Jamie Madill35cd7332018-12-02 12:03:33 -05001882 constexpr char kFS2[] = R"(#version 310 es
1883uniform layout(location = 0) highp ivec2 u_expectedSize;
1884out layout(location = 2) mediump vec4 f_color;
1885void main()
1886{
1887 if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;
1888 f_color = vec4(1.0, 0.5, 0.25, 1.0);
1889})";
JiangYizhou10d41392017-12-18 18:13:36 +08001890
Tim Van Pattendff47d52020-07-14 19:10:12 -06001891 ANGLE_GL_PROGRAM(program1, kVS1, kFS1);
1892 ANGLE_GL_PROGRAM(program2, kVS2, kFS2);
JiangYizhou10d41392017-12-18 18:13:36 +08001893
1894 glUseProgram(program1);
JiangYizhou511937d2017-08-03 15:41:29 +08001895
1896 GLFramebuffer mFramebuffer;
1897 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
1898 GLuint defaultWidth = 1;
1899 GLuint defaultHeight = 1;
1900
1901 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
1902 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
1903 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1904
1905 const float data[] = {
1906 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
1907 };
1908
1909 GLuint vertexArray = 0;
1910 GLuint vertexBuffer = 0;
1911 GLuint query = 0;
1912 GLuint passedCount = 0;
1913
1914 glGenQueries(1, &query);
1915 glGenVertexArrays(1, &vertexArray);
1916 glBindVertexArray(vertexArray);
1917
1918 glGenBuffers(1, &vertexBuffer);
1919 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1920 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1921
1922 glEnableVertexAttribArray(0);
1923 glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
JiangYizhou38d92b52017-09-13 13:47:52 +08001924 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
JiangYizhou511937d2017-08-03 15:41:29 +08001925
1926 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1927
JiangYizhou10d41392017-12-18 18:13:36 +08001928 glUseProgram(program2);
1929 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1930
1931 glUseProgram(program1);
JiangYizhou511937d2017-08-03 15:41:29 +08001932 // If fbo has attachments, the rendering size should be the same as its attachment.
1933 GLTexture mTexture;
1934 GLuint width = 2;
1935 GLuint height = 2;
1936 glBindTexture(GL_TEXTURE_2D, mTexture.get());
1937 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
JiangYizhou38d92b52017-09-13 13:47:52 +08001938
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001939 const GLenum bufs[] = {GL_NONE, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT3};
JiangYizhou38d92b52017-09-13 13:47:52 +08001940
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001941 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, mTexture.get(),
JiangYizhou511937d2017-08-03 15:41:29 +08001942 0);
1943 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001944 glDrawBuffers(4, bufs);
JiangYizhou511937d2017-08-03 15:41:29 +08001945
1946 validateSamplePass(query, passedCount, width, height);
1947
1948 // If fbo's attachment has been removed, the rendering size should be the same as framebuffer
1949 // default size.
Shahbaz Youssefi190d9a82019-11-29 09:57:40 -05001950 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, 0, 0, 0);
JiangYizhou511937d2017-08-03 15:41:29 +08001951 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1952
1953 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
1954
1955 glDisableVertexAttribArray(0);
1956 glBindBuffer(GL_ARRAY_BUFFER, 0);
1957 glBindVertexArray(0);
1958 glDeleteBuffers(1, &vertexBuffer);
1959 glDeleteVertexArrays(1, &vertexArray);
1960
1961 ASSERT_GL_NO_ERROR();
1962}
1963
Brandon Jones9fc87332017-12-13 15:46:52 -08001964class AddDummyTextureNoRenderTargetTest : public ANGLETest
1965{
1966 public:
1967 AddDummyTextureNoRenderTargetTest()
1968 {
1969 setWindowWidth(512);
1970 setWindowHeight(512);
1971 setConfigRedBits(8);
1972 setConfigGreenBits(8);
1973 setConfigBlueBits(8);
1974 setConfigAlphaBits(8);
1975 }
1976
Jonah Ryan-Daviseee67c62019-06-18 13:00:43 -04001977 void overrideWorkaroundsD3D(FeaturesD3D *features) override
Brandon Jones9fc87332017-12-13 15:46:52 -08001978 {
Jonah Ryan-Davisbeb0eb22019-06-14 15:10:33 -04001979 features->overrideFeatures({"add_dummy_texture_no_render_target"}, true);
Brandon Jones9fc87332017-12-13 15:46:52 -08001980 }
1981};
1982
1983// Test to verify workaround succeeds when no program outputs exist http://anglebug.com/2283
1984TEST_P(AddDummyTextureNoRenderTargetTest, NoProgramOutputWorkaround)
1985{
Jamie Madill35cd7332018-12-02 12:03:33 -05001986 constexpr char kVS[] = "void main() {}";
1987 constexpr char kFS[] = "void main() {}";
Brandon Jones9fc87332017-12-13 15:46:52 -08001988
Jamie Madill35cd7332018-12-02 12:03:33 -05001989 ANGLE_GL_PROGRAM(drawProgram, kVS, kFS);
Brandon Jones9fc87332017-12-13 15:46:52 -08001990
1991 glUseProgram(drawProgram);
1992
1993 glDrawArrays(GL_TRIANGLES, 0, 6);
1994
1995 ASSERT_GL_NO_ERROR();
1996}
1997
Jamie Madill4fb3c282020-03-19 19:10:45 -04001998// Covers a bug in ANGLE's Vulkan back-end framebuffer cache which ignored depth/stencil after
1999// calls to DrawBuffers.
2000TEST_P(FramebufferTest_ES3, AttachmentStateChange)
2001{
2002 constexpr GLuint kSize = 2;
2003
2004 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2005
2006 GLTexture colorTexture;
2007 glBindTexture(GL_TEXTURE_2D, colorTexture);
2008 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2009
2010 GLFramebuffer fbo;
2011 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2012 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
2013
2014 ASSERT_GL_NO_ERROR();
2015 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2016
2017 // First draw without a depth buffer.
2018 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2019
2020 GLRenderbuffer depthBuffer;
2021 glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
2022 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kSize, kSize);
2023
2024 // Bind just a renderbuffer and draw.
2025 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
2026
2027 ASSERT_GL_NO_ERROR();
2028 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2029
2030 glDrawBuffers(0, nullptr);
2031 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2032
2033 // Re-enable color buffer and draw one final time. This previously triggered a crash.
2034 GLenum drawBuffs = {GL_COLOR_ATTACHMENT0};
2035 glDrawBuffers(1, &drawBuffs);
2036
2037 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2038 ASSERT_GL_NO_ERROR();
2039 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2040}
2041
Jamie Madilld03b15b2020-03-26 17:22:18 -04002042// Tests that we can support a feedback loop between a depth textures and the depth buffer.
Jamie Madille689d312020-08-14 22:51:03 -04002043// The test emulates the read-only feedback loop in Manhattan.
2044TEST_P(FramebufferTest_ES3, ReadOnlyDepthFeedbackLoopSupported)
Jamie Madilld03b15b2020-03-26 17:22:18 -04002045{
Jamie Madill682f9142020-08-18 10:57:40 -04002046 // Feedback loops are only supported on Vulkan.
2047 // TODO(jmadill): Make GL extension. http://anglebug.com/4969
2048 ANGLE_SKIP_TEST_IF(!IsVulkan());
Jamie Madilld03b15b2020-03-26 17:22:18 -04002049
2050 constexpr GLuint kSize = 2;
2051 glViewport(0, 0, kSize, kSize);
2052
2053 constexpr char kFS[] = R"(precision mediump float;
2054varying vec2 v_texCoord;
2055uniform sampler2D depth;
2056void main()
2057{
2058 if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
2059 {
2060 gl_FragColor = vec4(0, 1, 0, 1);
2061 }
2062 else
2063 {
2064 gl_FragColor = vec4(1, 0, 0, 1);
2065 }
2066})";
2067
2068 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
2069
2070 GLFramebuffer framebuffer;
2071 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
2072
2073 GLTexture colorTexture;
2074 glBindTexture(GL_TEXTURE_2D, colorTexture);
2075 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2076
2077 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2078 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2079 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
2080
2081 GLTexture depthTexture;
2082 glBindTexture(GL_TEXTURE_2D, depthTexture);
2083 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
2084 GL_UNSIGNED_INT, nullptr);
2085 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2086 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2087 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
2088
2089 ASSERT_GL_NO_ERROR();
2090 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2091
2092 // Clear depth to 0.5.
2093 glClearDepthf(0.5f);
2094 glClear(GL_DEPTH_BUFFER_BIT);
2095
Jamie Madille689d312020-08-14 22:51:03 -04002096 // Disable depth. Although this does not remove the feedback loop as defined by the
Jamie Madilld03b15b2020-03-26 17:22:18 -04002097 // spec it mimics what gfxbench does in its rendering tests.
2098 glDepthMask(false);
Jamie Madille689d312020-08-14 22:51:03 -04002099 glDisable(GL_DEPTH_TEST);
Jamie Madilld03b15b2020-03-26 17:22:18 -04002100
2101 // Verify we can sample the depth texture and get 0.5.
2102 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
2103
2104 ASSERT_GL_NO_ERROR();
2105 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2106}
2107
Jamie Madilld3e800e2020-08-15 17:26:04 -04002108// Tests corner cases with read-only depth-stencil feedback loops.
2109TEST_P(FramebufferTest_ES3, ReadOnlyDepthFeedbackLoopStateChanges)
2110{
Jamie Madill682f9142020-08-18 10:57:40 -04002111 // Feedback loops are only supported on Vulkan.
2112 // TODO(jmadill): Make GL extension. http://anglebug.com/4969
2113 ANGLE_SKIP_TEST_IF(!IsVulkan());
Jamie Madilld3e800e2020-08-15 17:26:04 -04002114
2115 constexpr GLuint kSize = 2;
2116 glViewport(0, 0, kSize, kSize);
2117
2118 constexpr char kFS[] = R"(precision mediump float;
2119varying vec2 v_texCoord;
2120uniform sampler2D depth;
2121void main()
2122{
2123 if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
2124 {
2125 gl_FragColor = vec4(0, 1, 0, 1);
2126 }
2127 else
2128 {
2129 gl_FragColor = vec4(1, 0, 0, 1);
2130 }
2131})";
2132
2133 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
2134 glUseProgram(program);
2135
2136 setupQuadVertexBuffer(0.5f, 1.0f);
2137 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
2138 glEnableVertexAttribArray(0);
2139
2140 GLFramebuffer framebuffer1;
2141 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
2142
2143 GLTexture colorTexture;
2144 glBindTexture(GL_TEXTURE_2D, colorTexture);
2145 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2146
2147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2149 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
2150
2151 GLTexture depthTexture;
2152 glBindTexture(GL_TEXTURE_2D, depthTexture);
2153 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
2154 GL_UNSIGNED_INT, nullptr);
2155 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2156 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2157 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
2158 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2159
2160 GLFramebuffer framebuffer2;
2161 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
2162 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
2163 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2164
2165 ASSERT_GL_NO_ERROR();
2166
2167 // Clear depth to 0.5.
2168 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
2169 glClearDepthf(0.5f);
2170 glClear(GL_DEPTH_BUFFER_BIT);
2171 glFlush();
2172
2173 // Disable depth. Although this does not remove the feedback loop as defined by the
2174 // spec it mimics what gfxbench does in its rendering tests.
2175 glDepthMask(false);
2176 glDisable(GL_DEPTH_TEST);
2177
2178 // Draw with loop.
2179 glDrawArrays(GL_TRIANGLES, 0, 6);
2180 ASSERT_GL_NO_ERROR();
2181
2182 // Draw with no loop and second FBO. Starts RP in writable mode.
2183 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
2184 glBindTexture(GL_TEXTURE_2D, 0);
2185 glDrawArrays(GL_TRIANGLES, 0, 6);
2186 ASSERT_GL_NO_ERROR();
2187
2188 // Draw with loop, restarts RP.
2189 glBindTexture(GL_TEXTURE_2D, depthTexture);
2190 glDrawArrays(GL_TRIANGLES, 0, 6);
2191 ASSERT_GL_NO_ERROR();
2192}
2193
Jamie Madilldd00f162020-04-02 14:04:44 -04002194// Covers a bug in ANGLE's Vulkan back-end. Our VkFramebuffer cache would in some cases forget to
2195// check the draw states when computing a cache key.
2196TEST_P(FramebufferTest_ES3, DisabledAttachmentRedefinition)
2197{
2198 constexpr GLuint kSize = 2;
2199
2200 // Make a Framebuffer with two attachments with one enabled and one disabled.
2201 GLTexture texA, texB;
2202 glBindTexture(GL_TEXTURE_2D, texA);
2203 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2204 glBindTexture(GL_TEXTURE_2D, texB);
2205 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2206
2207 GLFramebuffer fbo;
2208 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2209 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
2210 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texB, 0);
2211
2212 // Mask out the second texture.
2213 constexpr GLenum kOneDrawBuf = GL_COLOR_ATTACHMENT0;
2214 glDrawBuffers(1, &kOneDrawBuf);
2215
2216 ASSERT_GL_NO_ERROR();
2217 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2218
2219 // Set up a very simple shader.
2220 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2221 glViewport(0, 0, kSize, kSize);
2222
2223 // Draw
2224 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2225 ASSERT_GL_NO_ERROR();
2226 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2227
2228 // Update the masked out attachment and draw again.
2229 std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
2230 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
2231 redPixels.data());
2232
2233 // Draw
2234 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
2235 ASSERT_GL_NO_ERROR();
2236 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2237
2238 glReadBuffer(GL_COLOR_ATTACHMENT1);
2239 ASSERT_GL_NO_ERROR();
2240 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2241}
2242
Jamie Madillc9c4e4e2020-04-02 10:29:52 -04002243class FramebufferTest : public ANGLETest
2244{};
2245
2246template <typename T>
2247void FillTexture2D(GLuint texture,
2248 GLsizei width,
2249 GLsizei height,
2250 const T &onePixelData,
2251 GLint level,
2252 GLint internalFormat,
2253 GLenum format,
2254 GLenum type)
2255{
2256 std::vector<T> allPixelsData(width * height, onePixelData);
2257
2258 glBindTexture(GL_TEXTURE_2D, texture);
2259 glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
2260 allPixelsData.data());
2261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2262 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2263 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2264 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2265}
2266
2267// Multi-context uses of textures should not cause rendering feedback loops.
2268TEST_P(FramebufferTest, MultiContextNoRenderingFeedbackLoops)
2269{
2270 constexpr char kTextureVS[] =
2271 R"(attribute vec4 a_position;
2272varying vec2 v_texCoord;
2273void main() {
2274 gl_Position = a_position;
2275 v_texCoord = (a_position.xy * 0.5) + 0.5;
2276})";
2277
2278 constexpr char kTextureFS[] =
2279 R"(precision mediump float;
2280varying vec2 v_texCoord;
2281uniform sampler2D u_texture;
2282void main() {
2283 gl_FragColor = texture2D(u_texture, v_texCoord).rgba;
2284})";
2285
2286 ANGLE_GL_PROGRAM(textureProgram, kTextureVS, kTextureFS);
2287
2288 glUseProgram(textureProgram.get());
2289 GLint uniformLoc = glGetUniformLocation(textureProgram.get(), "u_texture");
2290 ASSERT_NE(-1, uniformLoc);
2291 glUniform1i(uniformLoc, 0);
2292
2293 GLTexture texture;
2294 FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
2295 glBindTexture(GL_TEXTURE_2D, texture.get());
2296 // Note that _texture_ is still bound to GL_TEXTURE_2D in this context at this point.
2297
2298 EGLWindow *window = getEGLWindow();
2299 EGLDisplay display = window->getDisplay();
2300 EGLConfig config = window->getConfig();
2301 EGLSurface surface = window->getSurface();
2302 EGLint contextAttributes[] = {
2303 EGL_CONTEXT_MAJOR_VERSION_KHR,
2304 GetParam().majorVersion,
2305 EGL_CONTEXT_MINOR_VERSION_KHR,
2306 GetParam().minorVersion,
2307 EGL_NONE,
2308 };
2309 EGLContext context1 = eglGetCurrentContext();
2310 // Create context2, sharing resources with context1.
2311 EGLContext context2 = eglCreateContext(display, config, context1, contextAttributes);
2312 ASSERT_NE(context2, EGL_NO_CONTEXT);
2313 eglMakeCurrent(display, surface, surface, context2);
2314
2315 constexpr char kVS[] =
2316 R"(attribute vec4 a_position;
2317void main() {
2318 gl_Position = a_position;
2319})";
2320
2321 constexpr char kFS[] =
2322 R"(precision mediump float;
2323void main() {
2324 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
2325})";
2326
2327 ANGLE_GL_PROGRAM(program, kVS, kFS);
2328 glUseProgram(program.get());
2329
2330 ASSERT_GL_NO_ERROR();
2331
2332 // Render to the texture in context2.
2333 GLFramebuffer framebuffer;
2334 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
2335 // Texture is still a valid name in context2.
2336 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
Tim Van Pattene8789a52020-07-29 12:01:49 -06002337 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
Jamie Madillc9c4e4e2020-04-02 10:29:52 -04002338 // There is no rendering feedback loop at this point.
2339
2340 glDisable(GL_BLEND);
2341 glDisable(GL_DEPTH_TEST);
2342 ASSERT_GL_NO_ERROR();
2343
2344 // If draw is no-op'ed, texture will not be filled appropriately.
2345 drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
2346 ASSERT_GL_NO_ERROR();
2347 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2348
2349 // Make context1 current again.
2350 eglMakeCurrent(display, surface, surface, context1);
2351
2352 // Render texture to screen.
2353 drawQuad(textureProgram.get(), "a_position", 0.5f, 1.0f, true);
2354 ASSERT_GL_NO_ERROR();
2355 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2356
2357 eglDestroyContext(display, context2);
2358}
2359
Jamie Madill2a0c3592020-03-31 15:36:45 -04002360// Ensure cube-incomplete attachments cause incomplete Framebuffers.
2361TEST_P(FramebufferTest, IncompleteCubeMap)
2362{
2363 constexpr GLuint kSize = 2;
2364
2365 GLTexture srcTex;
2366 glBindTexture(GL_TEXTURE_CUBE_MAP, srcTex);
2367 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
2368 GL_UNSIGNED_BYTE, nullptr);
2369
2370 GLFramebuffer fbo;
2371 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2372 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
2373 srcTex, 0);
2374
2375 ASSERT_GL_NO_ERROR();
2376 ASSERT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
2377 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
2378}
2379
Tim Van Pattene8789a52020-07-29 12:01:49 -06002380// Test FBOs with different sizes are drawn correctly
2381TEST_P(FramebufferTest, BindAndDrawDifferentSizedFBOs)
2382{
2383 // 1. Create FBO 1 with dimensions 16x16
2384 // 2. Draw red into FBO 1 (note, FramebufferVk::syncState is called)
2385 // 3. Create FBO 2 with dimensions 8x8
2386 // 4. Draw green into FBO 2 (note, FramebufferVk::syncState is called)
2387 // 5. Bind FBO 1 (note, it's not dirty)
2388 // 6. Draw blue into FBO 1
2389 // 7. Verify FBO 1 is entirely blue
2390
2391 GLFramebuffer smallFbo;
2392 GLFramebuffer largeFbo;
2393 GLTexture smallTexture;
2394 GLTexture largeTexture;
2395 constexpr GLsizei kLargeWidth = 16;
2396 constexpr GLsizei kLargeHeight = 16;
2397 constexpr GLsizei kSmallWidth = 8;
2398 constexpr GLsizei kSmallHeight = 8;
2399
2400 ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
2401 ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2402 ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
2403
2404 // 1. Create FBO 1 with dimensions 16x16
2405 glBindFramebuffer(GL_FRAMEBUFFER, largeFbo);
2406 glBindTexture(GL_TEXTURE_2D, largeTexture);
2407 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kLargeWidth, kLargeHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2408 nullptr);
2409 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2410 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2411 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, largeTexture, 0);
2412 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2413
2414 // 2. Draw red into FBO 1 (note, FramebufferVk::syncState is called)
2415 glUseProgram(redProgram);
2416 drawQuad(redProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
2417 ASSERT_GL_NO_ERROR();
2418
2419 // 3. Create FBO 2 with dimensions 8x8
2420 glBindFramebuffer(GL_FRAMEBUFFER, smallFbo);
2421 glBindTexture(GL_TEXTURE_2D, smallTexture);
2422 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallWidth, kSmallHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2423 nullptr);
2424 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2425 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2426 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, smallTexture, 0);
2427 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2428
2429 // 4. Draw green into FBO 2 (note, FramebufferVk::syncState is called)
2430 glUseProgram(greenProgram);
2431 drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
2432 ASSERT_GL_NO_ERROR();
2433
2434 // 5. Bind FBO 1 (note, it's not dirty)
2435 glBindFramebuffer(GL_FRAMEBUFFER, largeFbo);
2436
2437 // 6. Draw blue into FBO 1
2438 glUseProgram(blueProgram);
2439 drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
2440 ASSERT_GL_NO_ERROR();
2441
2442 // 7. Verify FBO 1 is entirely blue
2443 EXPECT_PIXEL_RECT_EQ(0, 0, kLargeWidth, kLargeHeight, GLColor::blue);
2444}
2445
Tobin Ehlis1a01b4b2019-11-11 16:41:07 -07002446ANGLE_INSTANTIATE_TEST_ES2(AddDummyTextureNoRenderTargetTest);
Jamie Madillc9c4e4e2020-04-02 10:29:52 -04002447ANGLE_INSTANTIATE_TEST_ES2(FramebufferTest);
Shahbaz Youssefie28883d2020-01-25 23:25:43 -05002448ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
2449ANGLE_INSTANTIATE_TEST_ES3(FramebufferTest_ES3);
2450ANGLE_INSTANTIATE_TEST_ES31(FramebufferTest_ES31);