blob: 430ca8400943bb795fdd85c6c88255b9535f4134 [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"
Geoff Langb6a673a2014-06-05 14:19:16 -040011
Jamie Madillfa05f602015-05-07 13:47:11 -040012using namespace angle;
Austin Kinross18b931d2014-09-29 12:58:31 -070013
Geoff Langb6a673a2014-06-05 14:19:16 -040014class FramebufferFormatsTest : public ANGLETest
15{
Jamie Madillfa05f602015-05-07 13:47:11 -040016 protected:
Jamie Madill3215b202015-12-15 16:41:39 -050017 FramebufferFormatsTest() : mFramebuffer(0), mTexture(0), mRenderbuffer(0), mProgram(0)
Geoff Langb6a673a2014-06-05 14:19:16 -040018 {
19 setWindowWidth(128);
20 setWindowHeight(128);
21 setConfigRedBits(8);
22 setConfigGreenBits(8);
23 setConfigBlueBits(8);
24 setConfigAlphaBits(8);
25 }
26
27 void checkBitCount(GLuint fbo, GLenum channel, GLint minBits)
28 {
29 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
30
31 GLint bits = 0;
32 glGetIntegerv(channel, &bits);
33
34 if (minBits == 0)
35 {
36 EXPECT_EQ(minBits, bits);
37 }
38 else
39 {
40 EXPECT_GE(bits, minBits);
41 }
42 }
43
Jamie Madill1fbc59f2016-02-24 15:25:51 -050044 void testBitCounts(GLuint fbo,
45 GLint minRedBits,
46 GLint minGreenBits,
47 GLint minBlueBits,
48 GLint minAlphaBits,
49 GLint minDepthBits,
50 GLint minStencilBits)
Geoff Langb6a673a2014-06-05 14:19:16 -040051 {
52 checkBitCount(fbo, GL_RED_BITS, minRedBits);
53 checkBitCount(fbo, GL_GREEN_BITS, minGreenBits);
54 checkBitCount(fbo, GL_BLUE_BITS, minBlueBits);
55 checkBitCount(fbo, GL_ALPHA_BITS, minAlphaBits);
56 checkBitCount(fbo, GL_DEPTH_BITS, minDepthBits);
57 checkBitCount(fbo, GL_STENCIL_BITS, minStencilBits);
58 }
59
Jamie Madill1fbc59f2016-02-24 15:25:51 -050060 void testTextureFormat(GLenum internalFormat,
61 GLint minRedBits,
62 GLint minGreenBits,
63 GLint minBlueBits,
Geoff Langb6a673a2014-06-05 14:19:16 -040064 GLint minAlphaBits)
65 {
Jamie Madill3215b202015-12-15 16:41:39 -050066 glGenTextures(1, &mTexture);
67 glBindTexture(GL_TEXTURE_2D, mTexture);
Geoff Langb6a673a2014-06-05 14:19:16 -040068 glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
69
Jamie Madill3215b202015-12-15 16:41:39 -050070 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
Geoff Langb6a673a2014-06-05 14:19:16 -040071
Jamie Madill3215b202015-12-15 16:41:39 -050072 testBitCounts(mFramebuffer, minRedBits, minGreenBits, minBlueBits, minAlphaBits, 0, 0);
Geoff Langb6a673a2014-06-05 14:19:16 -040073 }
74
Jamie Madill1fbc59f2016-02-24 15:25:51 -050075 void testRenderbufferMultisampleFormat(int minESVersion,
76 GLenum attachmentType,
77 GLenum internalFormat)
Corentin Walleze0902642014-11-04 12:32:15 -080078 {
Geoff Langc4222072015-05-25 13:19:48 -040079 // TODO(geofflang): Figure out why this is broken on Intel OpenGL
Jamie Madill518b9fa2016-03-02 11:26:02 -050080 if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Langc4222072015-05-25 13:19:48 -040081 {
82 std::cout << "Test skipped on Intel OpenGL." << std::endl;
83 return;
84 }
85
Martin Radev1be913c2016-07-11 17:59:16 +030086 int clientVersion = getClientMajorVersion();
Jamie Madillfa05f602015-05-07 13:47:11 -040087 if (clientVersion < minESVersion)
Corentin Walleze0902642014-11-04 12:32:15 -080088 {
89 return;
90 }
91
92 // Check that multisample is supported with at least two samples (minimum required is 1)
93 bool supports2Samples = false;
94
Jamie Madillfa05f602015-05-07 13:47:11 -040095 if (clientVersion == 2)
Corentin Walleze0902642014-11-04 12:32:15 -080096 {
97 if (extensionEnabled("ANGLE_framebuffer_multisample"))
98 {
99 int maxSamples;
100 glGetIntegerv(GL_MAX_SAMPLES_ANGLE, &maxSamples);
101 supports2Samples = maxSamples >= 2;
102 }
103 }
104 else
105 {
Jamie Madillfa05f602015-05-07 13:47:11 -0400106 assert(clientVersion >= 3);
Corentin Walleze0902642014-11-04 12:32:15 -0800107 int maxSamples;
108 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
109 supports2Samples = maxSamples >= 2;
110 }
111
112 if (!supports2Samples)
113 {
114 return;
115 }
116
Jamie Madill3215b202015-12-15 16:41:39 -0500117 glGenRenderbuffers(1, &mRenderbuffer);
118 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
Corentin Walleze0902642014-11-04 12:32:15 -0800119
120 EXPECT_GL_NO_ERROR();
121 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, internalFormat, 128, 128);
122 EXPECT_GL_NO_ERROR();
Jamie Madill3215b202015-12-15 16:41:39 -0500123 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentType, GL_RENDERBUFFER, mRenderbuffer);
Corentin Walleze0902642014-11-04 12:32:15 -0800124 EXPECT_GL_NO_ERROR();
Corentin Walleze0902642014-11-04 12:32:15 -0800125 }
126
Olli Etuahobc21e182016-02-23 16:04:57 +0200127 void testZeroHeightRenderbuffer()
128 {
129 glGenRenderbuffers(1, &mRenderbuffer);
130 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
131 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 0);
132 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
133 mRenderbuffer);
134 EXPECT_GL_NO_ERROR();
135 }
136
Jamie Madill3215b202015-12-15 16:41:39 -0500137 void SetUp() override
Geoff Langb6a673a2014-06-05 14:19:16 -0400138 {
139 ANGLETest::SetUp();
Jamie Madill3215b202015-12-15 16:41:39 -0500140
141 glGenFramebuffers(1, &mFramebuffer);
142 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
Geoff Langb6a673a2014-06-05 14:19:16 -0400143 }
144
Jamie Madill3215b202015-12-15 16:41:39 -0500145 void TearDown() override
Geoff Langb6a673a2014-06-05 14:19:16 -0400146 {
147 ANGLETest::TearDown();
Jamie Madill3215b202015-12-15 16:41:39 -0500148
149 if (mTexture != 0)
150 {
151 glDeleteTextures(1, &mTexture);
152 mTexture = 0;
153 }
154
155 if (mRenderbuffer != 0)
156 {
157 glDeleteRenderbuffers(1, &mRenderbuffer);
158 mRenderbuffer = 0;
159 }
160
161 if (mFramebuffer != 0)
162 {
163 glDeleteFramebuffers(1, &mFramebuffer);
164 mFramebuffer = 0;
165 }
166
167 if (mProgram != 0)
168 {
169 glDeleteProgram(mProgram);
170 mProgram = 0;
171 }
Geoff Langb6a673a2014-06-05 14:19:16 -0400172 }
Jamie Madill3215b202015-12-15 16:41:39 -0500173
174 GLuint mFramebuffer;
175 GLuint mTexture;
176 GLuint mRenderbuffer;
177 GLuint mProgram;
Geoff Langb6a673a2014-06-05 14:19:16 -0400178};
179
Jamie Madillfa05f602015-05-07 13:47:11 -0400180TEST_P(FramebufferFormatsTest, RGBA4)
Geoff Langb6a673a2014-06-05 14:19:16 -0400181{
182 testTextureFormat(GL_RGBA4, 4, 4, 4, 4);
183}
184
Jamie Madillfa05f602015-05-07 13:47:11 -0400185TEST_P(FramebufferFormatsTest, RGB565)
Geoff Langb6a673a2014-06-05 14:19:16 -0400186{
187 testTextureFormat(GL_RGB565, 5, 6, 5, 0);
188}
189
Jamie Madillfa05f602015-05-07 13:47:11 -0400190TEST_P(FramebufferFormatsTest, RGB8)
Geoff Langb6a673a2014-06-05 14:19:16 -0400191{
Martin Radev1be913c2016-07-11 17:59:16 +0300192 if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_rgb8_rgba8"))
Geoff Langf34d1db2015-05-20 14:10:46 -0400193 {
194 std::cout << "Test skipped due to missing ES3 or GL_OES_rgb8_rgba8." << std::endl;
195 return;
196 }
197
Geoff Langb6a673a2014-06-05 14:19:16 -0400198 testTextureFormat(GL_RGB8_OES, 8, 8, 8, 0);
199}
200
Jamie Madillfa05f602015-05-07 13:47:11 -0400201TEST_P(FramebufferFormatsTest, BGRA8)
Geoff Langb6a673a2014-06-05 14:19:16 -0400202{
Geoff Langf34d1db2015-05-20 14:10:46 -0400203 if (!extensionEnabled("GL_EXT_texture_format_BGRA8888"))
204 {
205 std::cout << "Test skipped due to missing GL_EXT_texture_format_BGRA8888." << std::endl;
206 return;
207 }
208
Geoff Langb6a673a2014-06-05 14:19:16 -0400209 testTextureFormat(GL_BGRA8_EXT, 8, 8, 8, 8);
210}
211
Jamie Madillfa05f602015-05-07 13:47:11 -0400212TEST_P(FramebufferFormatsTest, RGBA8)
Geoff Langb6a673a2014-06-05 14:19:16 -0400213{
Martin Radev1be913c2016-07-11 17:59:16 +0300214 if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_rgb8_rgba8"))
Geoff Langf34d1db2015-05-20 14:10:46 -0400215 {
216 std::cout << "Test skipped due to missing ES3 or GL_OES_rgb8_rgba8." << std::endl;
217 return;
218 }
219
Geoff Langb6a673a2014-06-05 14:19:16 -0400220 testTextureFormat(GL_RGBA8_OES, 8, 8, 8, 8);
221}
222
Jamie Madillfa05f602015-05-07 13:47:11 -0400223TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH16)
Corentin Walleze0902642014-11-04 12:32:15 -0800224{
225 testRenderbufferMultisampleFormat(2, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16);
226}
227
Jamie Madillfa05f602015-05-07 13:47:11 -0400228TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24)
Corentin Walleze0902642014-11-04 12:32:15 -0800229{
230 testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24);
231}
232
Jamie Madillfa05f602015-05-07 13:47:11 -0400233TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F)
Corentin Walleze0902642014-11-04 12:32:15 -0800234{
Martin Radev1be913c2016-07-11 17:59:16 +0300235 if (getClientMajorVersion() < 3)
Geoff Langf34d1db2015-05-20 14:10:46 -0400236 {
237 std::cout << "Test skipped due to missing ES3." << std::endl;
238 return;
239 }
240
Corentin Walleze0902642014-11-04 12:32:15 -0800241 testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT32F);
242}
243
Jamie Madillfa05f602015-05-07 13:47:11 -0400244TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24_STENCIL8)
Corentin Walleze0902642014-11-04 12:32:15 -0800245{
246 testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH24_STENCIL8);
247}
248
Jamie Madillfa05f602015-05-07 13:47:11 -0400249TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F_STENCIL8)
Corentin Walleze0902642014-11-04 12:32:15 -0800250{
Martin Radev1be913c2016-07-11 17:59:16 +0300251 if (getClientMajorVersion() < 3)
Geoff Langf34d1db2015-05-20 14:10:46 -0400252 {
253 std::cout << "Test skipped due to missing ES3." << std::endl;
254 return;
255 }
256
Corentin Walleze0902642014-11-04 12:32:15 -0800257 testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH32F_STENCIL8);
258}
259
Jamie Madillfa05f602015-05-07 13:47:11 -0400260TEST_P(FramebufferFormatsTest, RenderbufferMultisample_STENCIL_INDEX8)
Corentin Walleze0902642014-11-04 12:32:15 -0800261{
Geoff Langf34d1db2015-05-20 14:10:46 -0400262 // TODO(geofflang): Figure out how to support GLSTENCIL_INDEX8 on desktop GL
Geoff Langdd323e92015-06-09 15:16:31 -0400263 if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Langf34d1db2015-05-20 14:10:46 -0400264 {
265 std::cout << "Test skipped on Desktop OpenGL." << std::endl;
266 return;
267 }
268
Corentin Walleze0902642014-11-04 12:32:15 -0800269 testRenderbufferMultisampleFormat(2, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8);
270}
Jamie Madillfa05f602015-05-07 13:47:11 -0400271
Jamie Madill3215b202015-12-15 16:41:39 -0500272// Test that binding an incomplete cube map is rejected by ANGLE.
273TEST_P(FramebufferFormatsTest, IncompleteCubeMap)
274{
275 // First make a complete CubeMap.
276 glGenTextures(1, &mTexture);
277 glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
278 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
279 nullptr);
280 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
281 nullptr);
282 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
283 nullptr);
284 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
285 nullptr);
286 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
287 nullptr);
288 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
289 nullptr);
290 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
291 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
292
293 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
294 mTexture, 0);
295
296 // Verify the framebuffer is complete.
297 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
298
299 // Make the CubeMap cube-incomplete.
300 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
301 nullptr);
302
303 // Verify the framebuffer is incomplete.
304 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
305 glCheckFramebufferStatus(GL_FRAMEBUFFER));
306
307 // Verify drawing with the incomplete framebuffer produces a GL error
308 const std::string &vs = "attribute vec4 position; void main() { gl_Position = position; }";
309 const std::string &ps = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
310 mProgram = CompileProgram(vs, ps);
311 ASSERT_NE(0u, mProgram);
312 drawQuad(mProgram, "position", 0.5f);
313 ASSERT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
314}
315
Olli Etuahobc21e182016-02-23 16:04:57 +0200316// Test that a renderbuffer with zero height but nonzero width is handled without crashes/asserts.
317TEST_P(FramebufferFormatsTest, ZeroHeightRenderbuffer)
318{
Martin Radev1be913c2016-07-11 17:59:16 +0300319 if (getClientMajorVersion() < 3)
Olli Etuahobc21e182016-02-23 16:04:57 +0200320 {
321 std::cout << "Test skipped due to missing ES3" << std::endl;
322 return;
323 }
324
325 testZeroHeightRenderbuffer();
326}
327
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500328// Use this to select which configurations (e.g. which renderer, which GLES major version) these
329// tests should be run against.
Geoff Lange0cc2a42016-01-20 10:58:17 -0500330ANGLE_INSTANTIATE_TEST(FramebufferFormatsTest,
331 ES2_D3D9(),
332 ES2_D3D11(),
333 ES3_D3D11(),
334 ES2_OPENGL(),
335 ES3_OPENGL(),
336 ES2_OPENGLES(),
337 ES3_OPENGLES());
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500338
339class FramebufferInvalidateTest : public ANGLETest
340{
341 protected:
342 FramebufferInvalidateTest() : mFramebuffer(0), mRenderbuffer(0) {}
343
344 void SetUp() override
345 {
346 ANGLETest::SetUp();
347
348 glGenFramebuffers(1, &mFramebuffer);
349 glGenRenderbuffers(1, &mRenderbuffer);
350 }
351
352 void TearDown() override
353 {
354 glDeleteFramebuffers(1, &mFramebuffer);
355 glDeleteRenderbuffers(1, &mRenderbuffer);
356 ANGLETest::TearDown();
357 }
358
359 GLuint mFramebuffer;
360 GLuint mRenderbuffer;
361};
362
363// Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error.
364TEST_P(FramebufferInvalidateTest, Incomplete)
365{
366 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
367 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
368 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
369 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
370 glCheckFramebufferStatus(GL_FRAMEBUFFER));
371
372 std::vector<GLenum> attachments;
373 attachments.push_back(GL_COLOR_ATTACHMENT0);
374
375 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
376 EXPECT_GL_NO_ERROR();
377}
378
379ANGLE_INSTANTIATE_TEST(FramebufferInvalidateTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());