blob: cc1fed0339844625d03084456fc62927b760f74b [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
Corentin Wallezd3970de2015-05-14 11:07:48 -040010#include "test_utils/ANGLETest.h"
JiangYizhou461d9a32017-01-04 16:37:26 +080011#include "test_utils/gl_raii.h"
Geoff Langb6a673a2014-06-05 14:19:16 -040012
Jamie Madillfa05f602015-05-07 13:47:11 -040013using namespace angle;
Austin Kinross18b931d2014-09-29 12:58:31 -070014
Geoff Lang857c09d2017-05-16 15:55:04 -040015namespace
16{
17
18void ExpectFramebufferCompleteOrUnsupported(GLenum binding)
19{
20 GLenum status = glCheckFramebufferStatus(binding);
21 EXPECT_TRUE(status == GL_FRAMEBUFFER_COMPLETE || status == GL_FRAMEBUFFER_UNSUPPORTED);
22}
23
24} // anonymous namespace
25
Geoff Langb6a673a2014-06-05 14:19:16 -040026class FramebufferFormatsTest : public ANGLETest
27{
Jamie Madillfa05f602015-05-07 13:47:11 -040028 protected:
Jamie Madill3215b202015-12-15 16:41:39 -050029 FramebufferFormatsTest() : mFramebuffer(0), mTexture(0), mRenderbuffer(0), mProgram(0)
Geoff Langb6a673a2014-06-05 14:19:16 -040030 {
31 setWindowWidth(128);
32 setWindowHeight(128);
33 setConfigRedBits(8);
34 setConfigGreenBits(8);
35 setConfigBlueBits(8);
36 setConfigAlphaBits(8);
37 }
38
39 void checkBitCount(GLuint fbo, GLenum channel, GLint minBits)
40 {
41 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
42
43 GLint bits = 0;
44 glGetIntegerv(channel, &bits);
45
46 if (minBits == 0)
47 {
48 EXPECT_EQ(minBits, bits);
49 }
50 else
51 {
52 EXPECT_GE(bits, minBits);
53 }
54 }
55
Jamie Madill1fbc59f2016-02-24 15:25:51 -050056 void testBitCounts(GLuint fbo,
57 GLint minRedBits,
58 GLint minGreenBits,
59 GLint minBlueBits,
60 GLint minAlphaBits,
61 GLint minDepthBits,
62 GLint minStencilBits)
Geoff Langb6a673a2014-06-05 14:19:16 -040063 {
64 checkBitCount(fbo, GL_RED_BITS, minRedBits);
65 checkBitCount(fbo, GL_GREEN_BITS, minGreenBits);
66 checkBitCount(fbo, GL_BLUE_BITS, minBlueBits);
67 checkBitCount(fbo, GL_ALPHA_BITS, minAlphaBits);
68 checkBitCount(fbo, GL_DEPTH_BITS, minDepthBits);
69 checkBitCount(fbo, GL_STENCIL_BITS, minStencilBits);
70 }
71
Jamie Madill1fbc59f2016-02-24 15:25:51 -050072 void testTextureFormat(GLenum internalFormat,
73 GLint minRedBits,
74 GLint minGreenBits,
75 GLint minBlueBits,
Geoff Langb6a673a2014-06-05 14:19:16 -040076 GLint minAlphaBits)
77 {
Jamie Madill3215b202015-12-15 16:41:39 -050078 glGenTextures(1, &mTexture);
79 glBindTexture(GL_TEXTURE_2D, mTexture);
Geoff Langc4e93662017-05-01 10:45:59 -040080
81 if (getClientMajorVersion() >= 3)
82 {
83 glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
84 }
85 else
86 {
87 glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
88 }
Geoff Langb6a673a2014-06-05 14:19:16 -040089
Jamie Madill3215b202015-12-15 16:41:39 -050090 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
Geoff Langb6a673a2014-06-05 14:19:16 -040091
Jamie Madill3215b202015-12-15 16:41:39 -050092 testBitCounts(mFramebuffer, minRedBits, minGreenBits, minBlueBits, minAlphaBits, 0, 0);
Geoff Langb6a673a2014-06-05 14:19:16 -040093 }
94
Jamie Madill1fbc59f2016-02-24 15:25:51 -050095 void testRenderbufferMultisampleFormat(int minESVersion,
96 GLenum attachmentType,
97 GLenum internalFormat)
Corentin Walleze0902642014-11-04 12:32:15 -080098 {
Geoff Langc4222072015-05-25 13:19:48 -040099 // TODO(geofflang): Figure out why this is broken on Intel OpenGL
Jamie Madill518b9fa2016-03-02 11:26:02 -0500100 if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Langc4222072015-05-25 13:19:48 -0400101 {
102 std::cout << "Test skipped on Intel OpenGL." << std::endl;
103 return;
104 }
105
Martin Radev1be913c2016-07-11 17:59:16 +0300106 int clientVersion = getClientMajorVersion();
Jamie Madillfa05f602015-05-07 13:47:11 -0400107 if (clientVersion < minESVersion)
Corentin Walleze0902642014-11-04 12:32:15 -0800108 {
109 return;
110 }
111
112 // Check that multisample is supported with at least two samples (minimum required is 1)
113 bool supports2Samples = false;
114
Jamie Madillfa05f602015-05-07 13:47:11 -0400115 if (clientVersion == 2)
Corentin Walleze0902642014-11-04 12:32:15 -0800116 {
117 if (extensionEnabled("ANGLE_framebuffer_multisample"))
118 {
119 int maxSamples;
120 glGetIntegerv(GL_MAX_SAMPLES_ANGLE, &maxSamples);
121 supports2Samples = maxSamples >= 2;
122 }
123 }
124 else
125 {
Jamie Madillfa05f602015-05-07 13:47:11 -0400126 assert(clientVersion >= 3);
Corentin Walleze0902642014-11-04 12:32:15 -0800127 int maxSamples;
128 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
129 supports2Samples = maxSamples >= 2;
130 }
131
132 if (!supports2Samples)
133 {
134 return;
135 }
136
Jamie Madill3215b202015-12-15 16:41:39 -0500137 glGenRenderbuffers(1, &mRenderbuffer);
138 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
Corentin Walleze0902642014-11-04 12:32:15 -0800139
140 EXPECT_GL_NO_ERROR();
141 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, internalFormat, 128, 128);
142 EXPECT_GL_NO_ERROR();
Jamie Madill3215b202015-12-15 16:41:39 -0500143 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentType, GL_RENDERBUFFER, mRenderbuffer);
Corentin Walleze0902642014-11-04 12:32:15 -0800144 EXPECT_GL_NO_ERROR();
Corentin Walleze0902642014-11-04 12:32:15 -0800145 }
146
Olli Etuahobc21e182016-02-23 16:04:57 +0200147 void testZeroHeightRenderbuffer()
148 {
149 glGenRenderbuffers(1, &mRenderbuffer);
150 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
151 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 0);
152 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
153 mRenderbuffer);
154 EXPECT_GL_NO_ERROR();
155 }
156
Jamie Madill3215b202015-12-15 16:41:39 -0500157 void SetUp() override
Geoff Langb6a673a2014-06-05 14:19:16 -0400158 {
159 ANGLETest::SetUp();
Jamie Madill3215b202015-12-15 16:41:39 -0500160
161 glGenFramebuffers(1, &mFramebuffer);
162 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
Geoff Langb6a673a2014-06-05 14:19:16 -0400163 }
164
Jamie Madill3215b202015-12-15 16:41:39 -0500165 void TearDown() override
Geoff Langb6a673a2014-06-05 14:19:16 -0400166 {
167 ANGLETest::TearDown();
Jamie Madill3215b202015-12-15 16:41:39 -0500168
169 if (mTexture != 0)
170 {
171 glDeleteTextures(1, &mTexture);
172 mTexture = 0;
173 }
174
175 if (mRenderbuffer != 0)
176 {
177 glDeleteRenderbuffers(1, &mRenderbuffer);
178 mRenderbuffer = 0;
179 }
180
181 if (mFramebuffer != 0)
182 {
183 glDeleteFramebuffers(1, &mFramebuffer);
184 mFramebuffer = 0;
185 }
186
187 if (mProgram != 0)
188 {
189 glDeleteProgram(mProgram);
190 mProgram = 0;
191 }
Geoff Langb6a673a2014-06-05 14:19:16 -0400192 }
Jamie Madill3215b202015-12-15 16:41:39 -0500193
194 GLuint mFramebuffer;
195 GLuint mTexture;
196 GLuint mRenderbuffer;
197 GLuint mProgram;
Geoff Langb6a673a2014-06-05 14:19:16 -0400198};
199
Jamie Madillfa05f602015-05-07 13:47:11 -0400200TEST_P(FramebufferFormatsTest, RGBA4)
Geoff Langb6a673a2014-06-05 14:19:16 -0400201{
Geoff Langc4e93662017-05-01 10:45:59 -0400202 if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_texture_storage"))
203 {
204 std::cout << "Test skipped due to missing ES3 or GL_EXT_texture_storage." << std::endl;
205 return;
206 }
207
Geoff Langb6a673a2014-06-05 14:19:16 -0400208 testTextureFormat(GL_RGBA4, 4, 4, 4, 4);
209}
210
Jamie Madillfa05f602015-05-07 13:47:11 -0400211TEST_P(FramebufferFormatsTest, RGB565)
Geoff Langb6a673a2014-06-05 14:19:16 -0400212{
Geoff Langc4e93662017-05-01 10:45:59 -0400213 if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_texture_storage"))
214 {
215 std::cout << "Test skipped due to missing ES3 or GL_EXT_texture_storage." << std::endl;
216 return;
217 }
218
Geoff Langb6a673a2014-06-05 14:19:16 -0400219 testTextureFormat(GL_RGB565, 5, 6, 5, 0);
220}
221
Jamie Madillfa05f602015-05-07 13:47:11 -0400222TEST_P(FramebufferFormatsTest, RGB8)
Geoff Langb6a673a2014-06-05 14:19:16 -0400223{
Geoff Langc4e93662017-05-01 10:45:59 -0400224 if (getClientMajorVersion() < 3 &&
225 (!extensionEnabled("GL_OES_rgb8_rgba8") || !extensionEnabled("GL_EXT_texture_storage")))
Geoff Langf34d1db2015-05-20 14:10:46 -0400226 {
Geoff Langc4e93662017-05-01 10:45:59 -0400227 std::cout
228 << "Test skipped due to missing ES3 or GL_OES_rgb8_rgba8 and GL_EXT_texture_storage."
229 << std::endl;
Geoff Langf34d1db2015-05-20 14:10:46 -0400230 return;
231 }
232
Geoff Langb6a673a2014-06-05 14:19:16 -0400233 testTextureFormat(GL_RGB8_OES, 8, 8, 8, 0);
234}
235
Jamie Madillfa05f602015-05-07 13:47:11 -0400236TEST_P(FramebufferFormatsTest, BGRA8)
Geoff Langb6a673a2014-06-05 14:19:16 -0400237{
Geoff Langc4e93662017-05-01 10:45:59 -0400238 if (!extensionEnabled("GL_EXT_texture_format_BGRA8888") ||
239 (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_texture_storage")))
Geoff Langf34d1db2015-05-20 14:10:46 -0400240 {
Geoff Langc4e93662017-05-01 10:45:59 -0400241 std::cout << "Test skipped due to missing GL_EXT_texture_format_BGRA8888 or "
242 "GL_EXT_texture_storage."
243 << std::endl;
Geoff Langf34d1db2015-05-20 14:10:46 -0400244 return;
245 }
246
Geoff Langb6a673a2014-06-05 14:19:16 -0400247 testTextureFormat(GL_BGRA8_EXT, 8, 8, 8, 8);
248}
249
Jamie Madillfa05f602015-05-07 13:47:11 -0400250TEST_P(FramebufferFormatsTest, RGBA8)
Geoff Langb6a673a2014-06-05 14:19:16 -0400251{
Geoff Langc4e93662017-05-01 10:45:59 -0400252 if (getClientMajorVersion() < 3 &&
253 (!extensionEnabled("GL_OES_rgb8_rgba8") || !extensionEnabled("GL_EXT_texture_storage")))
Geoff Langf34d1db2015-05-20 14:10:46 -0400254 {
Geoff Langc4e93662017-05-01 10:45:59 -0400255 std::cout
256 << "Test skipped due to missing ES3 or GL_OES_rgb8_rgba8 and GL_EXT_texture_storage."
257 << std::endl;
Geoff Langf34d1db2015-05-20 14:10:46 -0400258 return;
259 }
260
Geoff Langb6a673a2014-06-05 14:19:16 -0400261 testTextureFormat(GL_RGBA8_OES, 8, 8, 8, 8);
262}
263
Jamie Madillfa05f602015-05-07 13:47:11 -0400264TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH16)
Corentin Walleze0902642014-11-04 12:32:15 -0800265{
266 testRenderbufferMultisampleFormat(2, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16);
267}
268
Jamie Madillfa05f602015-05-07 13:47:11 -0400269TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24)
Corentin Walleze0902642014-11-04 12:32:15 -0800270{
271 testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24);
272}
273
Jamie Madillfa05f602015-05-07 13:47:11 -0400274TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F)
Corentin Walleze0902642014-11-04 12:32:15 -0800275{
Martin Radev1be913c2016-07-11 17:59:16 +0300276 if (getClientMajorVersion() < 3)
Geoff Langf34d1db2015-05-20 14:10:46 -0400277 {
278 std::cout << "Test skipped due to missing ES3." << std::endl;
279 return;
280 }
281
Corentin Walleze0902642014-11-04 12:32:15 -0800282 testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT32F);
283}
284
Jamie Madillfa05f602015-05-07 13:47:11 -0400285TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24_STENCIL8)
Corentin Walleze0902642014-11-04 12:32:15 -0800286{
287 testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH24_STENCIL8);
288}
289
Jamie Madillfa05f602015-05-07 13:47:11 -0400290TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F_STENCIL8)
Corentin Walleze0902642014-11-04 12:32:15 -0800291{
Martin Radev1be913c2016-07-11 17:59:16 +0300292 if (getClientMajorVersion() < 3)
Geoff Langf34d1db2015-05-20 14:10:46 -0400293 {
294 std::cout << "Test skipped due to missing ES3." << std::endl;
295 return;
296 }
297
Corentin Walleze0902642014-11-04 12:32:15 -0800298 testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH32F_STENCIL8);
299}
300
Jamie Madillfa05f602015-05-07 13:47:11 -0400301TEST_P(FramebufferFormatsTest, RenderbufferMultisample_STENCIL_INDEX8)
Corentin Walleze0902642014-11-04 12:32:15 -0800302{
Geoff Langf34d1db2015-05-20 14:10:46 -0400303 // TODO(geofflang): Figure out how to support GLSTENCIL_INDEX8 on desktop GL
Geoff Langdd323e92015-06-09 15:16:31 -0400304 if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Langf34d1db2015-05-20 14:10:46 -0400305 {
306 std::cout << "Test skipped on Desktop OpenGL." << std::endl;
307 return;
308 }
309
Corentin Walleze0902642014-11-04 12:32:15 -0800310 testRenderbufferMultisampleFormat(2, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8);
311}
Jamie Madillfa05f602015-05-07 13:47:11 -0400312
Jamie Madill3215b202015-12-15 16:41:39 -0500313// Test that binding an incomplete cube map is rejected by ANGLE.
314TEST_P(FramebufferFormatsTest, IncompleteCubeMap)
315{
316 // First make a complete CubeMap.
317 glGenTextures(1, &mTexture);
318 glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
319 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
320 nullptr);
321 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
322 nullptr);
323 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
324 nullptr);
325 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
326 nullptr);
327 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
328 nullptr);
329 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
330 nullptr);
331 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
332 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
333
334 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
335 mTexture, 0);
336
337 // Verify the framebuffer is complete.
338 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
339
340 // Make the CubeMap cube-incomplete.
341 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
342 nullptr);
343
344 // Verify the framebuffer is incomplete.
345 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
346 glCheckFramebufferStatus(GL_FRAMEBUFFER));
347
348 // Verify drawing with the incomplete framebuffer produces a GL error
349 const std::string &vs = "attribute vec4 position; void main() { gl_Position = position; }";
350 const std::string &ps = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
351 mProgram = CompileProgram(vs, ps);
352 ASSERT_NE(0u, mProgram);
353 drawQuad(mProgram, "position", 0.5f);
354 ASSERT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
355}
356
Olli Etuahobc21e182016-02-23 16:04:57 +0200357// Test that a renderbuffer with zero height but nonzero width is handled without crashes/asserts.
358TEST_P(FramebufferFormatsTest, ZeroHeightRenderbuffer)
359{
Martin Radev1be913c2016-07-11 17:59:16 +0300360 if (getClientMajorVersion() < 3)
Olli Etuahobc21e182016-02-23 16:04:57 +0200361 {
362 std::cout << "Test skipped due to missing ES3" << std::endl;
363 return;
364 }
365
366 testZeroHeightRenderbuffer();
367}
368
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500369// Use this to select which configurations (e.g. which renderer, which GLES major version) these
370// tests should be run against.
Geoff Lange0cc2a42016-01-20 10:58:17 -0500371ANGLE_INSTANTIATE_TEST(FramebufferFormatsTest,
372 ES2_D3D9(),
373 ES2_D3D11(),
374 ES3_D3D11(),
375 ES2_OPENGL(),
376 ES3_OPENGL(),
377 ES2_OPENGLES(),
378 ES3_OPENGLES());
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500379
Corentin Wallez57e6d502016-12-09 14:46:39 -0500380class FramebufferTest_ES3 : public ANGLETest
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500381{
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500382};
383
384// Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error.
Corentin Wallez57e6d502016-12-09 14:46:39 -0500385TEST_P(FramebufferTest_ES3, InvalidateIncomplete)
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500386{
Geoff Lang857c09d2017-05-16 15:55:04 -0400387 GLFramebuffer framebuffer;
388 GLRenderbuffer renderbuffer;
389
390 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
391 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
392 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500393 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
394 glCheckFramebufferStatus(GL_FRAMEBUFFER));
395
396 std::vector<GLenum> attachments;
397 attachments.push_back(GL_COLOR_ATTACHMENT0);
398
399 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
400 EXPECT_GL_NO_ERROR();
401}
402
Corentin Wallez57e6d502016-12-09 14:46:39 -0500403// Test that the framebuffer state tracking robustly handles a depth-only attachment being set
404// as a depth-stencil attachment. It is equivalent to detaching the depth-stencil attachment.
405TEST_P(FramebufferTest_ES3, DepthOnlyAsDepthStencil)
406{
Geoff Lang857c09d2017-05-16 15:55:04 -0400407 GLFramebuffer framebuffer;
408 GLRenderbuffer renderbuffer;
409
410 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
411 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
Corentin Wallez57e6d502016-12-09 14:46:39 -0500412 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 4, 4);
413
414 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
Geoff Lang857c09d2017-05-16 15:55:04 -0400415 renderbuffer);
Corentin Wallez57e6d502016-12-09 14:46:39 -0500416 EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
417}
418
Geoff Lang857c09d2017-05-16 15:55:04 -0400419// Test that the framebuffer correctly returns that it is not complete if invalid texture mip levels
420// are bound
421TEST_P(FramebufferTest_ES3, TextureAttachmentMipLevels)
422{
423 GLFramebuffer framebuffer;
424 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
425
426 GLTexture texture;
427 glBindTexture(GL_TEXTURE_2D, texture);
428
429 // Create a complete mip chain in mips 1 to 3
430 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
431 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
432 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
433
434 // Create another complete mip chain in mips 4 to 5
435 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
436 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
437
438 // Create a non-complete mip chain in mip 6
439 glTexImage2D(GL_TEXTURE_2D, 6, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
440
441 // Incomplete, mipLevel != baseLevel and texture is not mip complete
442 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
443 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
444 glCheckFramebufferStatus(GL_FRAMEBUFFER));
445
446 // Complete, mipLevel == baseLevel
447 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
448 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
449
450 // Complete, mipLevel != baseLevel but texture is now mip complete
451 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 2);
452 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
453 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 3);
454 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
455
456 // Incomplete, attached level below the base level
457 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
458 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
459 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
460 glCheckFramebufferStatus(GL_FRAMEBUFFER));
461
462 // Incomplete, attached level is beyond effective max level
463 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 4);
464 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
465 glCheckFramebufferStatus(GL_FRAMEBUFFER));
466
467 // Complete, mipLevel == baseLevel
468 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 4);
469 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
470
471 // Complete, mipLevel != baseLevel but texture is now mip complete
472 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 5);
473 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
474
475 // Complete, mipLevel == baseLevel
476 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 6);
477 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 6);
478 ExpectFramebufferCompleteOrUnsupported(GL_FRAMEBUFFER);
479}
480
Martin Radevd178aa42017-07-13 14:03:22 +0300481// Test that passing an attachment COLOR_ATTACHMENTm where m is equal to MAX_COLOR_ATTACHMENTS
482// generates an INVALID_OPERATION.
483// OpenGL ES Version 3.0.5 (November 3, 2016), 4.4.2.4 Attaching Texture Images to a Framebuffer, p.
484// 208
485TEST_P(FramebufferTest_ES3, ColorAttachmentIndexOutOfBounds)
486{
487 GLFramebuffer framebuffer;
488 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
489
490 GLint maxColorAttachments = 0;
491 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
492 GLenum attachment = static_cast<GLenum>(maxColorAttachments + GL_COLOR_ATTACHMENT0);
493
494 GLTexture texture;
495 glBindTexture(GL_TEXTURE_2D, texture.get());
496 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
497 glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture.get(), 0);
498 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
499}
500
Jamie Madilla0016b72017-07-14 14:30:46 -0400501// Check that depth-only attachments report the correct number of samples.
502TEST_P(FramebufferTest_ES3, MultisampleDepthOnly)
503{
504 GLRenderbuffer renderbuffer;
505 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
506 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_DEPTH_COMPONENT24, 32, 32);
507
508 GLFramebuffer framebuffer;
509 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
510 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
511 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
512 EXPECT_GL_NO_ERROR();
513
514 GLint samples = 0;
515 glGetIntegerv(GL_SAMPLES, &samples);
516 EXPECT_GL_NO_ERROR();
517 EXPECT_GE(samples, 2);
518}
519
Corentin Wallez57e6d502016-12-09 14:46:39 -0500520ANGLE_INSTANTIATE_TEST(FramebufferTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
JiangYizhou461d9a32017-01-04 16:37:26 +0800521
522class FramebufferTest_ES31 : public ANGLETest
523{
JiangYizhou511937d2017-08-03 15:41:29 +0800524 protected:
525 void validateSamplePass(GLuint &query, GLuint &passedCount, GLint width, GLint height)
526 {
527 glUniform2i(0, width - 1, height - 1);
528 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
529 glDrawArrays(GL_TRIANGLES, 0, 6);
530 glEndQuery(GL_ANY_SAMPLES_PASSED);
531 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
532 EXPECT_GT(static_cast<GLint>(passedCount), 0);
533
534 glUniform2i(0, width - 1, height);
535 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
536 glDrawArrays(GL_TRIANGLES, 0, 6);
537 glEndQuery(GL_ANY_SAMPLES_PASSED);
538 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
539 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
540
541 glUniform2i(0, width, height - 1);
542 glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
543 glDrawArrays(GL_TRIANGLES, 0, 6);
544 glEndQuery(GL_ANY_SAMPLES_PASSED);
545 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &passedCount);
546 EXPECT_EQ(static_cast<GLint>(passedCount), 0);
547 }
JiangYizhou461d9a32017-01-04 16:37:26 +0800548};
549
550// Test that without attachment, if either the value of FRAMEBUFFER_DEFAULT_WIDTH or
551// FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is incomplete.
552TEST_P(FramebufferTest_ES31, IncompleteMissingAttachmentDefaultParam)
553{
554 GLFramebuffer mFramebuffer;
555 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
556
557 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
558 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
559 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
560
561 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
562 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
563 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
564 glCheckFramebufferStatus(GL_FRAMEBUFFER));
565
566 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1);
567 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0);
568 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
569 glCheckFramebufferStatus(GL_FRAMEBUFFER));
570
571 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0);
572 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1);
573 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
574 glCheckFramebufferStatus(GL_FRAMEBUFFER));
575
576 ASSERT_GL_NO_ERROR();
577}
578
579// Test that the sample count of a mix of texture and renderbuffer should be same.
580TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix)
581{
582 GLFramebuffer mFramebuffer;
583 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
584
585 GLTexture mTexture;
586 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
587 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, true);
588
589 GLRenderbuffer mRenderbuffer;
590 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
591 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_RGBA8, 1, 1);
592 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
593 mTexture.get(), 0);
594 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
595 mRenderbuffer.get());
596 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
597 glCheckFramebufferStatus(GL_FRAMEBUFFER));
598
599 ASSERT_GL_NO_ERROR();
600}
601
602// Test that the sample count of texture attachments should be same.
603TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex)
604{
605 GLFramebuffer mFramebuffer;
606 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
607
608 GLTexture mTextures[2];
609 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
610 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, true);
611 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
612 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, 1, 1, true);
613 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
614 mTextures[0].get(), 0);
615 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
616 mTextures[1].get(), 0);
617 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
618 glCheckFramebufferStatus(GL_FRAMEBUFFER));
619
620 ASSERT_GL_NO_ERROR();
621}
622
623// Test that if the attached images are a mix of renderbuffers and textures, the value of
624// TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
625TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsMix)
626{
627 GLFramebuffer mFramebuffer;
628 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
629
630 GLTexture mTexture;
631 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get());
632 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
633
634 GLRenderbuffer mRenderbuffer;
635 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get());
636 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
637 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
638 mTexture.get(), 0);
639 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER,
640 mRenderbuffer.get());
641 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
642 glCheckFramebufferStatus(GL_FRAMEBUFFER));
643
644 ASSERT_GL_NO_ERROR();
645}
646
647// Test that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures.
648TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsTex)
649{
650 GLFramebuffer mFramebuffer;
651 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get());
652
653 GLTexture mTextures[2];
654 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get());
655 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false);
656 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
657 mTextures[0].get(), 0);
658 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get());
659 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGB8, 1, 1, true);
660 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE,
661 mTextures[1].get(), 0);
662 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
663 glCheckFramebufferStatus(GL_FRAMEBUFFER));
664
665 ASSERT_GL_NO_ERROR();
666}
667
JiangYizhou511937d2017-08-03 15:41:29 +0800668// If there are no attachments, rendering will be limited to a rectangle having a lower left of
669// (0, 0) and an upper right of(width, height), where width and height are the framebuffer
670// object's default width and height.
671TEST_P(FramebufferTest_ES31, RenderingLimitToDefaultFBOSizeWithNoAttchments)
672{
673 const std::string &vertexShader =
674 "#version 310 es\n"
675 "in layout(location = 0) highp vec2 a_position;\n\n"
676 "void main()\n"
677 "{\n"
678 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
679 "}\n";
680 const std::string &fragShader =
681 "#version 310 es\n"
682 "uniform layout(location = 0) highp ivec2 u_expectedSize;\n"
683 "out layout(location = 0) mediump vec4 f_color;\n\n"
684 "void main()\n"
685 "{\n"
686 " if (ivec2(gl_FragCoord.xy) != u_expectedSize) discard;\n"
687 " f_color = vec4(1.0, 0.5, 0.25, 1.0);\n"
688 "}\n";
689
690 GLuint program = CompileProgram(vertexShader, fragShader);
691 ASSERT_NE(program, 0u);
692
693 glUseProgram(program);
694
695 GLFramebuffer mFramebuffer;
696 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
697 GLuint defaultWidth = 1;
698 GLuint defaultHeight = 1;
699
700 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, defaultWidth);
701 glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, defaultHeight);
702 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
703
704 const float data[] = {
705 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f,
706 };
707
708 GLuint vertexArray = 0;
709 GLuint vertexBuffer = 0;
710 GLuint query = 0;
711 GLuint passedCount = 0;
712
713 glGenQueries(1, &query);
714 glGenVertexArrays(1, &vertexArray);
715 glBindVertexArray(vertexArray);
716
717 glGenBuffers(1, &vertexBuffer);
718 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
719 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
720
721 glEnableVertexAttribArray(0);
722 glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
723
724 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
725
726 // If fbo has attachments, the rendering size should be the same as its attachment.
727 GLTexture mTexture;
728 GLuint width = 2;
729 GLuint height = 2;
730 glBindTexture(GL_TEXTURE_2D, mTexture.get());
731 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
732 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture.get(),
733 0);
734 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
735
736 validateSamplePass(query, passedCount, width, height);
737
738 // If fbo's attachment has been removed, the rendering size should be the same as framebuffer
739 // default size.
740 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0);
741 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
742
743 validateSamplePass(query, passedCount, defaultWidth, defaultHeight);
744
745 glDisableVertexAttribArray(0);
746 glBindBuffer(GL_ARRAY_BUFFER, 0);
747 glBindVertexArray(0);
748 glDeleteBuffers(1, &vertexBuffer);
749 glDeleteVertexArrays(1, &vertexArray);
750
751 ASSERT_GL_NO_ERROR();
752}
753
754ANGLE_INSTANTIATE_TEST(FramebufferTest_ES31, ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES());