blob: 3df70e10ccab7b822d956d71501742f5a13df7ea [file] [log] [blame]
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001//
2// Copyright 2017 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//
6
7// WebGLFramebufferTest.cpp : Framebuffer tests for GL_ANGLE_webgl_compatibility.
8// Based on WebGL 1 test renderbuffers/framebuffer-object-attachment.
9
10#include "test_utils/ANGLETest.h"
11
12#include "test_utils/gl_raii.h"
13
14namespace angle
15{
16
17class WebGLFramebufferTest : public ANGLETest
18{
19 protected:
20 WebGLFramebufferTest()
21 {
22 setWindowWidth(128);
23 setWindowHeight(128);
24 setConfigRedBits(8);
25 setConfigGreenBits(8);
26 setConfigBlueBits(8);
27 setConfigAlphaBits(8);
28 setWebGLCompatibilityEnabled(true);
29 }
30
Geoff Lange466c552017-03-17 15:24:12 -040031 void SetUp() override
32 {
33 ANGLETest::SetUp();
34 glRequestExtensionANGLE = reinterpret_cast<PFNGLREQUESTEXTENSIONANGLEPROC>(
35 eglGetProcAddress("glRequestExtensionANGLE"));
36 }
37
Jamie Madilla02315b2017-02-23 14:14:47 -050038 void drawUByteColorQuad(GLuint program, GLint uniformLoc, const GLColor &color);
39 void testDepthStencilDepthStencil(GLint width, GLint height);
40 void testDepthStencilRenderbuffer(GLint width,
41 GLint height,
42 GLRenderbuffer *colorBuffer,
43 GLbitfield allowedStatuses);
44 void testRenderingAndReading(GLuint program);
45 void testUsingIncompleteFramebuffer(GLenum depthFormat, GLenum depthAttachment);
Frank Henigman60f6eb22017-05-08 15:34:46 -040046 void testDrawingMissingAttachment();
Geoff Lange466c552017-03-17 15:24:12 -040047
48 PFNGLREQUESTEXTENSIONANGLEPROC glRequestExtensionANGLE = nullptr;
Jamie Madill4e0e6f82017-02-17 11:06:03 -050049};
50
51constexpr GLint ALLOW_COMPLETE = 0x1;
52constexpr GLint ALLOW_UNSUPPORTED = 0x2;
53constexpr GLint ALLOW_INCOMPLETE_ATTACHMENT = 0x4;
54
55void checkFramebufferForAllowedStatuses(GLbitfield allowedStatuses)
56{
57 // If the framebuffer is in an error state for multiple reasons,
58 // we can't guarantee which one will be reported.
59 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
60 bool statusAllowed =
61 ((allowedStatuses & ALLOW_COMPLETE) && (status == GL_FRAMEBUFFER_COMPLETE)) ||
62 ((allowedStatuses & ALLOW_UNSUPPORTED) && (status == GL_FRAMEBUFFER_UNSUPPORTED)) ||
63 ((allowedStatuses & ALLOW_INCOMPLETE_ATTACHMENT) &&
64 (status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT));
65 EXPECT_TRUE(statusAllowed);
66}
67
Jamie Madilla02315b2017-02-23 14:14:47 -050068void checkBufferBits(GLenum attachment0, GLenum attachment1)
Jamie Madill4e0e6f82017-02-17 11:06:03 -050069{
70 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
71 return;
72
73 bool haveDepthBuffer =
Jamie Madilla02315b2017-02-23 14:14:47 -050074 attachment0 == GL_DEPTH_ATTACHMENT || attachment0 == GL_DEPTH_STENCIL_ATTACHMENT ||
75 attachment1 == GL_DEPTH_ATTACHMENT || attachment1 == GL_DEPTH_STENCIL_ATTACHMENT;
Jamie Madill4e0e6f82017-02-17 11:06:03 -050076 bool haveStencilBuffer =
Jamie Madilla02315b2017-02-23 14:14:47 -050077 attachment0 == GL_STENCIL_ATTACHMENT || attachment0 == GL_DEPTH_STENCIL_ATTACHMENT ||
78 attachment1 == GL_STENCIL_ATTACHMENT || attachment1 == GL_DEPTH_STENCIL_ATTACHMENT;
Jamie Madill4e0e6f82017-02-17 11:06:03 -050079
80 GLint redBits = 0;
81 GLint greenBits = 0;
82 GLint blueBits = 0;
83 GLint alphaBits = 0;
84 GLint depthBits = 0;
85 GLint stencilBits = 0;
86 glGetIntegerv(GL_RED_BITS, &redBits);
87 glGetIntegerv(GL_GREEN_BITS, &greenBits);
88 glGetIntegerv(GL_BLUE_BITS, &blueBits);
89 glGetIntegerv(GL_ALPHA_BITS, &alphaBits);
90 glGetIntegerv(GL_DEPTH_BITS, &depthBits);
91 glGetIntegerv(GL_STENCIL_BITS, &stencilBits);
92
93 EXPECT_GE(redBits + greenBits + blueBits + alphaBits, 16);
94
95 if (haveDepthBuffer)
96 EXPECT_GE(depthBits, 16);
97 else
98 EXPECT_EQ(0, depthBits);
99
100 if (haveStencilBuffer)
101 EXPECT_GE(stencilBits, 8);
102 else
103 EXPECT_EQ(0, stencilBits);
104}
105
106// Tests that certain required combinations work in WebGL compatiblity.
107TEST_P(WebGLFramebufferTest, TestFramebufferRequiredCombinations)
108{
109 // Per discussion with the OpenGL ES working group, the following framebuffer attachment
110 // combinations are required to work in all WebGL implementations:
111 // 1. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture
112 // 2. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16
113 // renderbuffer
114 // 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL
115 // renderbuffer
116
117 GLFramebuffer fbo;
118 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
119
120 constexpr int width = 64;
121 constexpr int height = 64;
122
123 // 1. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture
124 GLTexture texture;
125 glBindTexture(GL_TEXTURE_2D, texture);
126 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
127 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
128 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
129 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
130 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
131 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
132 EXPECT_GL_NO_ERROR();
133 checkFramebufferForAllowedStatuses(ALLOW_COMPLETE);
Jamie Madilla02315b2017-02-23 14:14:47 -0500134 checkBufferBits(GL_NONE, GL_NONE);
Jamie Madill4e0e6f82017-02-17 11:06:03 -0500135
136 // 2. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16
137 // renderbuffer
138 GLRenderbuffer renderbuffer;
139 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
140 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
141 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
142 EXPECT_GL_NO_ERROR();
143 checkFramebufferForAllowedStatuses(ALLOW_COMPLETE);
Jamie Madilla02315b2017-02-23 14:14:47 -0500144 checkBufferBits(GL_DEPTH_ATTACHMENT, GL_NONE);
Jamie Madill4e0e6f82017-02-17 11:06:03 -0500145 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
146
147 // 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL
148 // renderbuffer
149 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
150 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
151 renderbuffer);
152 EXPECT_GL_NO_ERROR();
153 checkFramebufferForAllowedStatuses(ALLOW_COMPLETE);
Jamie Madilla02315b2017-02-23 14:14:47 -0500154 checkBufferBits(GL_DEPTH_STENCIL_ATTACHMENT, GL_NONE);
155}
156
157void testAttachment(GLint width,
158 GLint height,
159 GLRenderbuffer *colorBuffer,
160 GLenum attachment,
161 GLRenderbuffer *buffer,
162 GLbitfield allowedStatuses)
163{
164 GLFramebuffer fbo;
165 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
166 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorBuffer);
167 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, *buffer);
168 EXPECT_GL_NO_ERROR();
169 checkFramebufferForAllowedStatuses(allowedStatuses);
170 if ((allowedStatuses & ALLOW_COMPLETE) == 0)
171 {
172 std::vector<uint8_t> tempBuffer(width * height * 4);
173
174 glClear(GL_COLOR_BUFFER_BIT);
175 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
176 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, tempBuffer.data());
177 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
178 }
179 checkBufferBits(attachment, GL_NONE);
180}
181
182void testAttachments(GLRenderbuffer &colorBuffer,
183 GLenum attachment0,
184 GLRenderbuffer &buffer0,
185 GLenum attachment1,
186 GLRenderbuffer &buffer1,
187 GLbitfield allowedStatuses)
188{
189 GLFramebuffer fbo;
190 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
191 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
192 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment0, GL_RENDERBUFFER, buffer0);
193 EXPECT_GL_NO_ERROR();
194 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment1, GL_RENDERBUFFER, buffer1);
195 EXPECT_GL_NO_ERROR();
196 checkFramebufferForAllowedStatuses(allowedStatuses);
197 checkBufferBits(attachment0, attachment1);
198}
199
200void testColorRenderbuffer(GLint width,
201 GLint height,
202 GLenum internalformat,
203 GLbitfield allowedStatuses)
204{
205 GLRenderbuffer colorBuffer;
206 glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
207 glRenderbufferStorage(GL_RENDERBUFFER, internalformat, width, height);
208 EXPECT_GL_NO_ERROR();
209 testAttachment(width, height, &colorBuffer, GL_COLOR_ATTACHMENT0, &colorBuffer,
210 allowedStatuses);
211}
212
213GLint getRenderbufferParameter(GLenum paramName)
214{
215 GLint paramValue = 0;
216 glGetRenderbufferParameteriv(GL_RENDERBUFFER, paramName, &paramValue);
217 return paramValue;
218}
219
220void WebGLFramebufferTest::drawUByteColorQuad(GLuint program,
221 GLint uniformLoc,
222 const GLColor &color)
223{
224 Vector4 vecColor = color.toNormalizedVector();
225 glUseProgram(program);
226 glUniform4fv(uniformLoc, 1, vecColor.data());
227 drawQuad(program, "position", 0.5f, 1.0f, true);
228}
229
230void WebGLFramebufferTest::testDepthStencilDepthStencil(GLint width, GLint height)
231{
232 const std::string &vertexShader =
233 "attribute vec4 position;\n"
234 "void main() {\n"
235 " gl_Position = position;\n"
236 "}";
237 const std::string &fragmentShader =
238 "precision mediump float;\n"
239 "uniform vec4 color;\n"
240 "void main() {\n"
241 " gl_FragColor = color;\n"
242 "}";
243
244 if (width == 0 || height == 0)
245 {
246 return;
247 }
248
249 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
250 GLint uniformLoc = glGetUniformLocation(program.get(), "color");
251 ASSERT_NE(-1, uniformLoc);
252
253 struct TestInfo
254 {
255 GLenum firstFormat;
256 GLenum firstAttach;
257 GLenum secondFormat;
258 GLenum secondAttach;
259 };
260
261 TestInfo tests[2] = {
262 {GL_DEPTH_COMPONENT16, GL_DEPTH_ATTACHMENT, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL_ATTACHMENT},
263 {GL_DEPTH_STENCIL, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH_COMPONENT16, GL_DEPTH_ATTACHMENT}};
264
265 for (const TestInfo &test : tests)
266 {
267 for (GLint opIndex = 0; opIndex < 2; ++opIndex)
268 {
269 GLFramebuffer fbo;
270 GLTexture tex;
271 GLRenderbuffer firstRb;
272
273 // test: firstFormat vs secondFormat with unbind or delete.
274
275 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
276 // attach texture as color
277 glBindTexture(GL_TEXTURE_2D, tex);
278 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
279 nullptr);
280 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
281
282 // attach first
283 glBindRenderbuffer(GL_RENDERBUFFER, firstRb);
284 glRenderbufferStorage(GL_RENDERBUFFER, test.firstFormat, width, height);
285 glFramebufferRenderbuffer(GL_FRAMEBUFFER, test.firstAttach, GL_RENDERBUFFER, firstRb);
286
287 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
288
289 // TODO(jmadill): Remove clear - this should be implicit in WebGL_
290 glClear(GL_DEPTH_BUFFER_BIT);
291
292 glEnable(GL_DEPTH_TEST);
293 // Test it works
294 drawUByteColorQuad(program.get(), uniformLoc, GLColor::green);
295 // should not draw since DEPTH_FUNC == LESS
296 drawUByteColorQuad(program.get(), uniformLoc, GLColor::red);
297 // should be green
298 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
299
300 GLuint secondRb = 0;
301 glGenRenderbuffers(1, &secondRb);
302
303 // attach second
304 glBindRenderbuffer(GL_RENDERBUFFER, secondRb);
305 glRenderbufferStorage(GL_RENDERBUFFER, test.secondFormat, width, height);
306 glFramebufferRenderbuffer(GL_FRAMEBUFFER, test.secondAttach, GL_RENDERBUFFER, secondRb);
307
308 if (opIndex == 0)
309 {
310 // now delete it
311 glDeleteRenderbuffers(1, &secondRb);
312 secondRb = 0;
313 }
314 else
315 {
316 // unbind it
317 glFramebufferRenderbuffer(GL_FRAMEBUFFER, test.secondAttach, GL_RENDERBUFFER, 0);
318 }
319
320 // If the first attachment is not restored this may fail
321 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
322 EXPECT_GL_NO_ERROR();
323
324 // If the first attachment is not restored this may fail.
325 glClear(GL_DEPTH_BUFFER_BIT);
326 drawUByteColorQuad(program.get(), uniformLoc, GLColor::green);
327 // should not draw since DEPTH_FUNC == LESS
328 drawUByteColorQuad(program.get(), uniformLoc, GLColor::red);
329 // should be green
330 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
331 glDisable(GL_DEPTH_TEST);
332
333 if (opIndex == 1)
334 {
335 glDeleteRenderbuffers(1, &secondRb);
336 secondRb = 0;
337 }
338 }
339 }
340 EXPECT_GL_NO_ERROR();
341}
342
343void WebGLFramebufferTest::testDepthStencilRenderbuffer(GLint width,
344 GLint height,
345 GLRenderbuffer *colorBuffer,
346 GLbitfield allowedStatuses)
347{
348 GLRenderbuffer depthStencilBuffer;
349 glBindRenderbuffer(GL_RENDERBUFFER, depthStencilBuffer);
350 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
351 EXPECT_GL_NO_ERROR();
352
353 // OpenGL itself doesn't seem to guarantee that e.g. a 2 x 0
354 // renderbuffer will report 2 for its width when queried.
355 if (!(height == 0 && width > 0))
Frank Henigman0e74e052017-12-17 22:17:17 -0500356 {
Jamie Madilla02315b2017-02-23 14:14:47 -0500357 EXPECT_EQ(width, getRenderbufferParameter(GL_RENDERBUFFER_WIDTH));
Frank Henigman0e74e052017-12-17 22:17:17 -0500358 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500359 if (!(width == 0 && height > 0))
Frank Henigman0e74e052017-12-17 22:17:17 -0500360 {
Jamie Madilla02315b2017-02-23 14:14:47 -0500361 EXPECT_EQ(height, getRenderbufferParameter(GL_RENDERBUFFER_HEIGHT));
Frank Henigman0e74e052017-12-17 22:17:17 -0500362 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500363 EXPECT_EQ(GL_DEPTH_STENCIL, getRenderbufferParameter(GL_RENDERBUFFER_INTERNAL_FORMAT));
364 EXPECT_EQ(0, getRenderbufferParameter(GL_RENDERBUFFER_RED_SIZE));
365 EXPECT_EQ(0, getRenderbufferParameter(GL_RENDERBUFFER_GREEN_SIZE));
366 EXPECT_EQ(0, getRenderbufferParameter(GL_RENDERBUFFER_BLUE_SIZE));
367 EXPECT_EQ(0, getRenderbufferParameter(GL_RENDERBUFFER_ALPHA_SIZE));
368
369 // Avoid verifying these for zero-sized renderbuffers for the time
370 // being since it appears that even OpenGL doesn't guarantee them.
371 if (width > 0 && height > 0)
372 {
373 EXPECT_GT(getRenderbufferParameter(GL_RENDERBUFFER_DEPTH_SIZE), 0);
374 EXPECT_GT(getRenderbufferParameter(GL_RENDERBUFFER_STENCIL_SIZE), 0);
375 }
376 EXPECT_GL_NO_ERROR();
377 testAttachment(width, height, colorBuffer, GL_DEPTH_STENCIL_ATTACHMENT, &depthStencilBuffer,
378 allowedStatuses);
379 testDepthStencilDepthStencil(width, height);
380}
381
382// Test various attachment combinations with WebGL framebuffers.
383TEST_P(WebGLFramebufferTest, TestAttachments)
384{
385 for (GLint width = 2; width <= 2; width += 2)
386 {
387 for (GLint height = 2; height <= 2; height += 2)
388 {
389 // Dimensions width x height.
390 GLRenderbuffer colorBuffer;
391 glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
392 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, width, height);
393 EXPECT_GL_NO_ERROR();
394
395 GLRenderbuffer depthBuffer;
396 glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
397 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
398 EXPECT_GL_NO_ERROR();
399
400 GLRenderbuffer stencilBuffer;
401 glBindRenderbuffer(GL_RENDERBUFFER, stencilBuffer);
402 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
403 EXPECT_GL_NO_ERROR();
404
405 GLRenderbuffer depthStencilBuffer;
406 glBindRenderbuffer(GL_RENDERBUFFER, depthStencilBuffer);
407 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
408 EXPECT_GL_NO_ERROR();
409
410 GLbitfield allowedStatusForGoodCase =
411 (width == 0 || height == 0) ? ALLOW_INCOMPLETE_ATTACHMENT : ALLOW_COMPLETE;
412
413 // some cases involving stencil seem to be implementation-dependent
414 GLbitfield allowedStatusForImplDependentCase =
415 allowedStatusForGoodCase | ALLOW_UNSUPPORTED;
416
417 // Attach depth using DEPTH_ATTACHMENT.
418 testAttachment(width, height, &colorBuffer, GL_DEPTH_ATTACHMENT, &depthBuffer,
419 allowedStatusForGoodCase);
420
421 // Attach depth using STENCIL_ATTACHMENT.
422 testAttachment(width, height, &colorBuffer, GL_STENCIL_ATTACHMENT, &depthBuffer,
423 ALLOW_INCOMPLETE_ATTACHMENT);
424
425 // Attach depth using DEPTH_STENCIL_ATTACHMENT.
426 testAttachment(width, height, &colorBuffer, GL_DEPTH_STENCIL_ATTACHMENT, &depthBuffer,
427 ALLOW_INCOMPLETE_ATTACHMENT);
428
429 // Attach stencil using STENCIL_ATTACHMENT.
430 testAttachment(width, height, &colorBuffer, GL_STENCIL_ATTACHMENT, &stencilBuffer,
431 allowedStatusForImplDependentCase);
432
433 // Attach stencil using DEPTH_ATTACHMENT.
434 testAttachment(width, height, &colorBuffer, GL_DEPTH_ATTACHMENT, &stencilBuffer,
435 ALLOW_INCOMPLETE_ATTACHMENT);
436
437 // Attach stencil using DEPTH_STENCIL_ATTACHMENT.
438 testAttachment(width, height, &colorBuffer, GL_DEPTH_STENCIL_ATTACHMENT, &stencilBuffer,
439 ALLOW_INCOMPLETE_ATTACHMENT);
440
441 // Attach depthStencil using DEPTH_STENCIL_ATTACHMENT.
442 testAttachment(width, height, &colorBuffer, GL_DEPTH_STENCIL_ATTACHMENT,
443 &depthStencilBuffer, allowedStatusForGoodCase);
444
445 // Attach depthStencil using DEPTH_ATTACHMENT.
446 testAttachment(width, height, &colorBuffer, GL_DEPTH_ATTACHMENT, &depthStencilBuffer,
447 ALLOW_INCOMPLETE_ATTACHMENT);
448
449 // Attach depthStencil using STENCIL_ATTACHMENT.
450 testAttachment(width, height, &colorBuffer, GL_STENCIL_ATTACHMENT, &depthStencilBuffer,
451 ALLOW_INCOMPLETE_ATTACHMENT);
452
453 GLbitfield allowedStatusForConflictedAttachment =
454 (width == 0 || height == 0) ? ALLOW_UNSUPPORTED | ALLOW_INCOMPLETE_ATTACHMENT
455 : ALLOW_UNSUPPORTED;
456
457 // Attach depth, then stencil, causing conflict.
458 testAttachments(colorBuffer, GL_DEPTH_ATTACHMENT, depthBuffer, GL_STENCIL_ATTACHMENT,
459 stencilBuffer, allowedStatusForConflictedAttachment);
460
461 // Attach stencil, then depth, causing conflict.
462 testAttachments(colorBuffer, GL_STENCIL_ATTACHMENT, stencilBuffer, GL_DEPTH_ATTACHMENT,
463 depthBuffer, allowedStatusForConflictedAttachment);
464
465 // Attach depth, then depthStencil, causing conflict.
466 testAttachments(colorBuffer, GL_DEPTH_ATTACHMENT, depthBuffer,
467 GL_DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer,
468 allowedStatusForConflictedAttachment);
469
470 // Attach depthStencil, then depth, causing conflict.
471 testAttachments(colorBuffer, GL_DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer,
472 GL_DEPTH_ATTACHMENT, depthBuffer, allowedStatusForConflictedAttachment);
473
474 // Attach stencil, then depthStencil, causing conflict.
475 testAttachments(colorBuffer, GL_DEPTH_ATTACHMENT, depthBuffer,
476 GL_DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer,
477 allowedStatusForConflictedAttachment);
478
479 // Attach depthStencil, then stencil, causing conflict.
480 testAttachments(colorBuffer, GL_DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer,
481 GL_STENCIL_ATTACHMENT, stencilBuffer,
482 allowedStatusForConflictedAttachment);
483
484 // Attach color renderbuffer with internalformat == RGBA4.
485 testColorRenderbuffer(width, height, GL_RGBA4, allowedStatusForGoodCase);
486
487 // Attach color renderbuffer with internalformat == RGB5_A1.
488 // This particular format seems to be bugged on NVIDIA Retina. http://crbug.com/635081
489 // TODO(jmadill): Figure out if we can add a format workaround.
490 if (!(IsNVIDIA() && IsOSX() && IsOpenGL()))
491 {
492 testColorRenderbuffer(width, height, GL_RGB5_A1, allowedStatusForGoodCase);
493 }
494
495 // Attach color renderbuffer with internalformat == RGB565.
496 testColorRenderbuffer(width, height, GL_RGB565, allowedStatusForGoodCase);
497
498 // Create and attach depthStencil renderbuffer.
499 testDepthStencilRenderbuffer(width, height, &colorBuffer, allowedStatusForGoodCase);
500 }
501 }
502}
503
504bool tryDepth(GLRenderbuffer *depthBuffer,
505 GLenum *depthFormat,
506 GLenum *depthAttachment,
507 GLenum try_format,
508 GLenum try_attachment)
509{
510 if (*depthAttachment != GL_NONE)
511 {
512 // If we've tried once unattach the old one.
513 glFramebufferRenderbuffer(GL_FRAMEBUFFER, *depthAttachment, GL_RENDERBUFFER, 0);
514 }
515 *depthFormat = try_format;
516 *depthAttachment = try_attachment;
517 glFramebufferRenderbuffer(GL_FRAMEBUFFER, *depthAttachment, GL_RENDERBUFFER, *depthBuffer);
518 glRenderbufferStorage(GL_RENDERBUFFER, *depthFormat, 16, 16);
519 EXPECT_GL_NO_ERROR();
520 return glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
521}
522
523bool checkValidColorDepthCombination(GLenum *depthFormat, GLenum *depthAttachment)
524{
525 GLFramebuffer fbo;
526 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
527 GLRenderbuffer colorBuffer;
528 glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
529 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
530 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
531
532 GLRenderbuffer depthBuffer;
533 glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
534
535 return tryDepth(&depthBuffer, depthFormat, depthAttachment, GL_DEPTH_COMPONENT16,
536 GL_DEPTH_ATTACHMENT) ||
537 tryDepth(&depthBuffer, depthFormat, depthAttachment, GL_DEPTH_STENCIL,
538 GL_DEPTH_STENCIL_ATTACHMENT);
539}
540
541// glCheckFramebufferStatus(GL_FRAMEBUFFER) should be either complete or (unsupported/expected).
542void checkFramebuffer(GLenum expected)
543{
544 GLenum actual = glCheckFramebufferStatus(GL_FRAMEBUFFER);
545 EXPECT_TRUE(actual == expected ||
546 (expected != GL_FRAMEBUFFER_COMPLETE && actual == GL_FRAMEBUFFER_UNSUPPORTED));
547}
548
549void WebGLFramebufferTest::testRenderingAndReading(GLuint program)
550{
551 EXPECT_GL_NO_ERROR();
552
553 // drawArrays with incomplete framebuffer
554 drawQuad(program, "position", 0.5f, 1.0f, true);
555 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
556
557 // readPixels from incomplete framebuffer
558 std::vector<uint8_t> dummyBuffer(4);
559 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, dummyBuffer.data());
560 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
561
562 // copyTexImage and copyTexSubImage can be either INVALID_FRAMEBUFFER_OPERATION because
563 // the framebuffer is invalid OR INVALID_OPERATION because in the case of no attachments
564 // the framebuffer is not of a compatible type.
565
566 // copyTexSubImage2D from incomplete framebuffer
567 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
568 GLenum error = glGetError();
569 EXPECT_TRUE(error == GL_INVALID_FRAMEBUFFER_OPERATION || error == GL_INVALID_OPERATION);
570
571 // copyTexImage2D from incomplete framebuffer
572 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0);
573 error = glGetError();
574 EXPECT_TRUE(error == GL_INVALID_FRAMEBUFFER_OPERATION || error == GL_INVALID_OPERATION);
575
576 // clear with incomplete framebuffer
577 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
578 EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
579}
580
581// Test drawing or reading from an incomplete framebuffer
582void WebGLFramebufferTest::testUsingIncompleteFramebuffer(GLenum depthFormat,
583 GLenum depthAttachment)
584{
585 // Simple draw program.
586 const std::string &vertexShader =
587 "attribute vec4 position; void main() { gl_Position = position; }";
588 const std::string &fragmentShader = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
589
590 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
591
592 GLFramebuffer fbo;
593 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
594 GLRenderbuffer colorBuffer;
595 glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
596 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
597 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
598
599 GLRenderbuffer depthBuffer;
600 glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
601 glFramebufferRenderbuffer(GL_FRAMEBUFFER, depthAttachment, GL_RENDERBUFFER, depthBuffer);
602 glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, 16, 16);
603 EXPECT_GL_NO_ERROR();
604 checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
605
606 // We pick this combination because it works on desktop OpenGL but should not work on OpenGL ES
607 // 2.0
608 glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, 32, 16);
609 checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
610
611 // Drawing or reading from an incomplete framebuffer should generate
612 // INVALID_FRAMEBUFFER_OPERATION.
613 testRenderingAndReading(program.get());
614
615 GLFramebuffer fbo2;
616 glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
617 checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
618
619 // Drawing or reading from an incomplete framebuffer should generate
620 // INVALID_FRAMEBUFFER_OPERATION.
621 testRenderingAndReading(program.get());
622
623 GLRenderbuffer colorBuffer2;
624 glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer2);
625 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer2);
626 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 0, 0);
627
628 // Drawing or reading from an incomplete framebuffer should generate
629 // INVALID_FRAMEBUFFER_OPERATION.
630 testRenderingAndReading(program.get());
631}
632
633void testFramebufferIncompleteAttachment(GLenum depthFormat)
634{
635 GLFramebuffer fbo;
636 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
637 GLRenderbuffer colorBuffer;
638 glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
639 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
640 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
641 checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
642
643 // Wrong storage type for type of attachment be FRAMEBUFFER_INCOMPLETE_ATTACHMENT (OpenGL ES 2.0
644 // 4.4.5).
645 glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, 16, 16);
646 checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
647
648 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
649 checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
650
651 // 0 size attachment should be FRAMEBUFFER_INCOMPLETE_ATTACHMENT (OpenGL ES 2.0 4.4.5).
652 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 0, 0);
653 checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
654
655 EXPECT_GL_NO_ERROR();
656}
657
658// No attachments should be INCOMPLETE_FRAMEBUFFER_MISSING_ATTACHMENT (OpenGL ES 2.0 4.4.5).
659void testFramebufferIncompleteMissingAttachment()
660{
661 GLFramebuffer fbo;
662 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
663 checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
664
665 GLRenderbuffer colorBuffer;
666 glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
667 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
668 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
669 checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
670
671 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
672 checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
673
674 EXPECT_GL_NO_ERROR();
675}
676
677// Attachments of different sizes should be FRAMEBUFFER_INCOMPLETE_DIMENSIONS (OpenGL ES 2.0 4.4.5).
678void testFramebufferIncompleteDimensions(GLenum depthFormat, GLenum depthAttachment)
679{
680 GLFramebuffer fbo;
681 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
682 GLRenderbuffer colorBuffer;
683 glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
684 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
685 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
686
687 GLRenderbuffer depthBuffer;
688 glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
689 glFramebufferRenderbuffer(GL_FRAMEBUFFER, depthAttachment, GL_RENDERBUFFER, depthBuffer);
690 glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, 16, 16);
691 EXPECT_GL_NO_ERROR();
692 checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
693
694 glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, 32, 16);
695 checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
696 glRenderbufferStorage(GL_RENDERBUFFER, depthFormat, 16, 16);
697 checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
698 glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
699 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 32);
700 checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
701 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 16, 16);
702 checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
703 EXPECT_GL_NO_ERROR();
704
705 GLTexture tex;
706 glBindTexture(GL_TEXTURE_2D, tex);
707 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
708 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
709 EXPECT_GL_NO_ERROR();
710 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
711 {
712 return;
713 }
714
715 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
716 checkFramebuffer(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
717 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
718 checkFramebuffer(GL_FRAMEBUFFER_COMPLETE);
719
720 EXPECT_GL_NO_ERROR();
721}
722
Frank Henigman60f6eb22017-05-08 15:34:46 -0400723class NoColorFB final : angle::NonCopyable
Jamie Madilla02315b2017-02-23 14:14:47 -0500724{
Frank Henigman60f6eb22017-05-08 15:34:46 -0400725 public:
726 NoColorFB(int size)
Jamie Madilla02315b2017-02-23 14:14:47 -0500727 {
Frank Henigman60f6eb22017-05-08 15:34:46 -0400728 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
729
730 // The only scenario we can verify is an attempt to read or copy
731 // from a missing color attachment while the framebuffer is still
732 // complete.
733 glBindRenderbuffer(GL_RENDERBUFFER, mDepthBuffer);
734 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
735 mDepthBuffer);
736 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size, size);
737
738 // After depth renderbuffer setup
Jamie Madilla02315b2017-02-23 14:14:47 -0500739 EXPECT_GL_NO_ERROR();
Frank Henigman60f6eb22017-05-08 15:34:46 -0400740
Jamie Madilla02315b2017-02-23 14:14:47 -0500741 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
742 {
Frank Henigman60f6eb22017-05-08 15:34:46 -0400743 // Unable to allocate a framebuffer with just a depth attachment; this is legal.
744 // Try just a depth/stencil renderbuffer.
745 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
746
747 glBindRenderbuffer(GL_RENDERBUFFER, mDepthStencilBuffer);
748 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
749 mDepthStencilBuffer);
750 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, size, size);
751
752 // After depth+stencil renderbuffer setup
753 EXPECT_GL_NO_ERROR();
Jamie Madilla02315b2017-02-23 14:14:47 -0500754 }
755 }
756
Frank Henigman60f6eb22017-05-08 15:34:46 -0400757 private:
758 GLRenderbuffer mDepthBuffer;
759 GLRenderbuffer mDepthStencilBuffer;
760 GLFramebuffer mFBO;
761};
762
763// Test reading from a missing framebuffer attachment.
764void TestReadingMissingAttachment(int size)
765{
Jamie Madilla02315b2017-02-23 14:14:47 -0500766 // The FBO has no color attachment. ReadPixels, CopyTexImage2D,
767 // and CopyTexSubImage2D should all generate INVALID_OPERATION.
768
769 // Before ReadPixels from missing attachment
770 std::vector<uint8_t> dummyBuffer(4);
771 EXPECT_GL_NO_ERROR();
772 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, dummyBuffer.data());
773 // After ReadPixels from missing attachment
774 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
775
776 GLTexture tex;
777 glBindTexture(GL_TEXTURE_2D, tex);
778 // Before CopyTexImage2D from missing attachment
779 EXPECT_GL_NO_ERROR();
780 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, size, size, 0);
781 // After CopyTexImage2D from missing attachment
782 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
783
784 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
785 // Before CopyTexSubImage2D from missing attachment
786 EXPECT_GL_NO_ERROR();
787 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size, size);
788 // After CopyTexSubImage2D from missing attachment
789 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
790}
791
Frank Henigman60f6eb22017-05-08 15:34:46 -0400792// Test drawing to a missing framebuffer attachment.
793void WebGLFramebufferTest::testDrawingMissingAttachment()
794{
795 // Simple draw program.
796 const std::string &vertexShader = "attribute vec4 pos; void main() { gl_Position = pos; }";
797 const std::string &fragmentShader = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
798 ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
799
800 glClear(GL_COLOR_BUFFER_BIT);
801 EXPECT_GL_NO_ERROR();
802
803 // try glDrawArrays
804 drawQuad(program, "pos", 0.5f, 1.0f, true);
805 EXPECT_GL_NO_ERROR();
806
807 // try glDrawElements
808 drawIndexedQuad(program, "pos", 0.5f, 1.0f, true);
809 EXPECT_GL_NO_ERROR();
810}
811
Jamie Madilla02315b2017-02-23 14:14:47 -0500812// Determine if we can attach both color and depth or color and depth_stencil
813TEST_P(WebGLFramebufferTest, CheckValidColorDepthCombination)
814{
Jamie Madilla836b462017-08-16 14:58:35 -0400815 // In FL9_3, we don't have a good way to handle non-color framebuffer rendering.
816 if (IsD3D11_FL93())
817 {
818 ignoreD3D11SDKLayersWarnings();
819 }
820
Jamie Madilla02315b2017-02-23 14:14:47 -0500821 GLenum depthFormat = GL_NONE;
822 GLenum depthAttachment = GL_NONE;
823
824 if (checkValidColorDepthCombination(&depthFormat, &depthAttachment))
825 {
826 testFramebufferIncompleteDimensions(depthFormat, depthAttachment);
827 testFramebufferIncompleteAttachment(depthFormat);
828 testFramebufferIncompleteMissingAttachment();
829 testUsingIncompleteFramebuffer(depthFormat, depthAttachment);
Frank Henigman60f6eb22017-05-08 15:34:46 -0400830
831 constexpr int size = 16;
832 NoColorFB fb(size);
833 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
834 {
835 // The FBO has no color attachment. ReadPixels, CopyTexImage2D,
836 // and CopyTexSubImage2D should all generate INVALID_OPERATION.
837 TestReadingMissingAttachment(size);
838
839 // The FBO has no color attachment. Clear, DrawArrays,
840 // and DrawElements should not generate an error.
841 testDrawingMissingAttachment();
842 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500843 }
Jamie Madill4e0e6f82017-02-17 11:06:03 -0500844}
845
Geoff Lange466c552017-03-17 15:24:12 -0400846// Test to cover a bug in preserving the texture image index for WebGL framebuffer attachments
847TEST_P(WebGLFramebufferTest, TextureAttachmentCommitBug)
848{
849 if (extensionRequestable("GL_ANGLE_depth_texture"))
850 {
851 glRequestExtensionANGLE("GL_ANGLE_depth_texture");
852 }
853
854 if (!extensionEnabled("GL_ANGLE_depth_texture"))
855 {
856 std::cout << "Test skipped because depth textures are not available.\n";
857 return;
858 }
859
860 GLTexture depthTexture;
861 glBindTexture(GL_TEXTURE_2D, depthTexture.get());
862 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,
863 nullptr);
864
865 GLFramebuffer framebuffer;
866 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
867 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture.get(),
868 0);
869
870 glCheckFramebufferStatus(GL_FRAMEBUFFER);
871
872 EXPECT_GL_NO_ERROR();
873}
874
Jamie Madill4e0e6f82017-02-17 11:06:03 -0500875// Only run against WebGL 1 validation, since much was changed in 2.
876ANGLE_INSTANTIATE_TEST(WebGLFramebufferTest,
877 ES2_D3D9(),
878 ES2_D3D11(),
879 ES2_D3D11_FL9_3(),
880 ES2_OPENGL(),
881 ES2_OPENGLES());
882
883} // namespace