blob: 5edd99817f0332691b93d7b397e33c097da828d3 [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 Madill7208f692016-02-29 10:47:35 -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
Geoff Langdd323e92015-06-09 15:16:31 -040086 int clientVersion = getClientVersion();
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
Jamie Madill3215b202015-12-15 16:41:39 -0500127 void SetUp() override
Geoff Langb6a673a2014-06-05 14:19:16 -0400128 {
129 ANGLETest::SetUp();
Jamie Madill3215b202015-12-15 16:41:39 -0500130
131 glGenFramebuffers(1, &mFramebuffer);
132 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
Geoff Langb6a673a2014-06-05 14:19:16 -0400133 }
134
Jamie Madill3215b202015-12-15 16:41:39 -0500135 void TearDown() override
Geoff Langb6a673a2014-06-05 14:19:16 -0400136 {
137 ANGLETest::TearDown();
Jamie Madill3215b202015-12-15 16:41:39 -0500138
139 if (mTexture != 0)
140 {
141 glDeleteTextures(1, &mTexture);
142 mTexture = 0;
143 }
144
145 if (mRenderbuffer != 0)
146 {
147 glDeleteRenderbuffers(1, &mRenderbuffer);
148 mRenderbuffer = 0;
149 }
150
151 if (mFramebuffer != 0)
152 {
153 glDeleteFramebuffers(1, &mFramebuffer);
154 mFramebuffer = 0;
155 }
156
157 if (mProgram != 0)
158 {
159 glDeleteProgram(mProgram);
160 mProgram = 0;
161 }
Geoff Langb6a673a2014-06-05 14:19:16 -0400162 }
Jamie Madill3215b202015-12-15 16:41:39 -0500163
164 GLuint mFramebuffer;
165 GLuint mTexture;
166 GLuint mRenderbuffer;
167 GLuint mProgram;
Geoff Langb6a673a2014-06-05 14:19:16 -0400168};
169
Jamie Madillfa05f602015-05-07 13:47:11 -0400170TEST_P(FramebufferFormatsTest, RGBA4)
Geoff Langb6a673a2014-06-05 14:19:16 -0400171{
172 testTextureFormat(GL_RGBA4, 4, 4, 4, 4);
173}
174
Jamie Madillfa05f602015-05-07 13:47:11 -0400175TEST_P(FramebufferFormatsTest, RGB565)
Geoff Langb6a673a2014-06-05 14:19:16 -0400176{
177 testTextureFormat(GL_RGB565, 5, 6, 5, 0);
178}
179
Jamie Madillfa05f602015-05-07 13:47:11 -0400180TEST_P(FramebufferFormatsTest, RGB8)
Geoff Langb6a673a2014-06-05 14:19:16 -0400181{
Geoff Langf34d1db2015-05-20 14:10:46 -0400182 if (getClientVersion() < 3 && !extensionEnabled("GL_OES_rgb8_rgba8"))
183 {
184 std::cout << "Test skipped due to missing ES3 or GL_OES_rgb8_rgba8." << std::endl;
185 return;
186 }
187
Geoff Langb6a673a2014-06-05 14:19:16 -0400188 testTextureFormat(GL_RGB8_OES, 8, 8, 8, 0);
189}
190
Jamie Madillfa05f602015-05-07 13:47:11 -0400191TEST_P(FramebufferFormatsTest, BGRA8)
Geoff Langb6a673a2014-06-05 14:19:16 -0400192{
Geoff Langf34d1db2015-05-20 14:10:46 -0400193 if (!extensionEnabled("GL_EXT_texture_format_BGRA8888"))
194 {
195 std::cout << "Test skipped due to missing GL_EXT_texture_format_BGRA8888." << std::endl;
196 return;
197 }
198
Geoff Langb6a673a2014-06-05 14:19:16 -0400199 testTextureFormat(GL_BGRA8_EXT, 8, 8, 8, 8);
200}
201
Jamie Madillfa05f602015-05-07 13:47:11 -0400202TEST_P(FramebufferFormatsTest, RGBA8)
Geoff Langb6a673a2014-06-05 14:19:16 -0400203{
Geoff Langf34d1db2015-05-20 14:10:46 -0400204 if (getClientVersion() < 3 && !extensionEnabled("GL_OES_rgb8_rgba8"))
205 {
206 std::cout << "Test skipped due to missing ES3 or GL_OES_rgb8_rgba8." << std::endl;
207 return;
208 }
209
Geoff Langb6a673a2014-06-05 14:19:16 -0400210 testTextureFormat(GL_RGBA8_OES, 8, 8, 8, 8);
211}
212
Jamie Madillfa05f602015-05-07 13:47:11 -0400213TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH16)
Corentin Walleze0902642014-11-04 12:32:15 -0800214{
215 testRenderbufferMultisampleFormat(2, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16);
216}
217
Jamie Madillfa05f602015-05-07 13:47:11 -0400218TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24)
Corentin Walleze0902642014-11-04 12:32:15 -0800219{
220 testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24);
221}
222
Jamie Madillfa05f602015-05-07 13:47:11 -0400223TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F)
Corentin Walleze0902642014-11-04 12:32:15 -0800224{
Geoff Langf34d1db2015-05-20 14:10:46 -0400225 if (getClientVersion() < 3)
226 {
227 std::cout << "Test skipped due to missing ES3." << std::endl;
228 return;
229 }
230
Corentin Walleze0902642014-11-04 12:32:15 -0800231 testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT32F);
232}
233
Jamie Madillfa05f602015-05-07 13:47:11 -0400234TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24_STENCIL8)
Corentin Walleze0902642014-11-04 12:32:15 -0800235{
236 testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH24_STENCIL8);
237}
238
Jamie Madillfa05f602015-05-07 13:47:11 -0400239TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F_STENCIL8)
Corentin Walleze0902642014-11-04 12:32:15 -0800240{
Geoff Langf34d1db2015-05-20 14:10:46 -0400241 if (getClientVersion() < 3)
242 {
243 std::cout << "Test skipped due to missing ES3." << std::endl;
244 return;
245 }
246
Corentin Walleze0902642014-11-04 12:32:15 -0800247 testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH32F_STENCIL8);
248}
249
Jamie Madillfa05f602015-05-07 13:47:11 -0400250TEST_P(FramebufferFormatsTest, RenderbufferMultisample_STENCIL_INDEX8)
Corentin Walleze0902642014-11-04 12:32:15 -0800251{
Geoff Langf34d1db2015-05-20 14:10:46 -0400252 // TODO(geofflang): Figure out how to support GLSTENCIL_INDEX8 on desktop GL
Geoff Langdd323e92015-06-09 15:16:31 -0400253 if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Langf34d1db2015-05-20 14:10:46 -0400254 {
255 std::cout << "Test skipped on Desktop OpenGL." << std::endl;
256 return;
257 }
258
Corentin Walleze0902642014-11-04 12:32:15 -0800259 testRenderbufferMultisampleFormat(2, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8);
260}
Jamie Madillfa05f602015-05-07 13:47:11 -0400261
Jamie Madill3215b202015-12-15 16:41:39 -0500262// Test that binding an incomplete cube map is rejected by ANGLE.
263TEST_P(FramebufferFormatsTest, IncompleteCubeMap)
264{
265 // First make a complete CubeMap.
266 glGenTextures(1, &mTexture);
267 glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
268 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
269 nullptr);
270 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
271 nullptr);
272 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
273 nullptr);
274 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
275 nullptr);
276 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
277 nullptr);
278 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
279 nullptr);
280 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
281 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
282
283 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
284 mTexture, 0);
285
286 // Verify the framebuffer is complete.
287 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
288
289 // Make the CubeMap cube-incomplete.
290 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
291 nullptr);
292
293 // Verify the framebuffer is incomplete.
294 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
295 glCheckFramebufferStatus(GL_FRAMEBUFFER));
296
297 // Verify drawing with the incomplete framebuffer produces a GL error
298 const std::string &vs = "attribute vec4 position; void main() { gl_Position = position; }";
299 const std::string &ps = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
300 mProgram = CompileProgram(vs, ps);
301 ASSERT_NE(0u, mProgram);
302 drawQuad(mProgram, "position", 0.5f);
303 ASSERT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
304}
305
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500306// Use this to select which configurations (e.g. which renderer, which GLES major version) these
307// tests should be run against.
Geoff Lange0cc2a42016-01-20 10:58:17 -0500308ANGLE_INSTANTIATE_TEST(FramebufferFormatsTest,
309 ES2_D3D9(),
310 ES2_D3D11(),
311 ES3_D3D11(),
312 ES2_OPENGL(),
313 ES3_OPENGL(),
314 ES2_OPENGLES(),
315 ES3_OPENGLES());
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500316
317class FramebufferInvalidateTest : public ANGLETest
318{
319 protected:
320 FramebufferInvalidateTest() : mFramebuffer(0), mRenderbuffer(0) {}
321
322 void SetUp() override
323 {
324 ANGLETest::SetUp();
325
326 glGenFramebuffers(1, &mFramebuffer);
327 glGenRenderbuffers(1, &mRenderbuffer);
328 }
329
330 void TearDown() override
331 {
332 glDeleteFramebuffers(1, &mFramebuffer);
333 glDeleteRenderbuffers(1, &mRenderbuffer);
334 ANGLETest::TearDown();
335 }
336
337 GLuint mFramebuffer;
338 GLuint mRenderbuffer;
339};
340
341// Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error.
342TEST_P(FramebufferInvalidateTest, Incomplete)
343{
344 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
345 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
346 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
347 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
348 glCheckFramebufferStatus(GL_FRAMEBUFFER));
349
350 std::vector<GLenum> attachments;
351 attachments.push_back(GL_COLOR_ATTACHMENT0);
352
353 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data());
354 EXPECT_GL_NO_ERROR();
355}
356
357ANGLE_INSTANTIATE_TEST(FramebufferInvalidateTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());