Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / conformance2 / renderbuffers / framebuffer-object-attachment.html
blobbc4d623446513364f5f5a66f1b54ca3c27c1ed0b
1 <!--
2 Copyright (c) 2019 The Khronos Group Inc.
3 Use of this source code is governed by an MIT-style license that can be
4 found in the LICENSE.txt file.
5 -->
7 <!DOCTYPE html>
8 <html>
9 <head>
10 <meta charset="utf-8">
11 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
12 <script src="../../js/js-test-pre.js"></script>
13 <script src="../../js/webgl-test-utils.js"></script>
14 </head>
15 <body>
16 <div id="description"></div>
17 <div id="console"></div>
19 <script>
20 "use strict";
21 var wtu = WebGLTestUtils;
22 var gl;
24 function checkFramebuffer(expected) {
25 var actual = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
26 if (expected.indexOf(actual) < 0) {
27 var msg = "checkFramebufferStatus expects [";
28 for (var index = 0; index < expected.length; ++index) {
29 msg += wtu.glEnumToString(gl, expected[index]);
30 if (index + 1 < expected.length)
31 msg += ", ";
33 msg += "], was " + wtu.glEnumToString(gl, actual);
34 testFailed(msg);
35 } else {
36 var msg = "checkFramebufferStatus got " + wtu.glEnumToString(gl, actual) +
37 " as expected";
38 testPassed(msg);
42 function checkBufferBits(attachment0, attachment1) {
43 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)
44 return;
45 var haveDepthBuffer = attachment0 == gl.DEPTH_ATTACHMENT ||
46 attachment0 == gl.DEPTH_STENCIL_ATTACHMENT ||
47 attachment1 == gl.DEPTH_ATTACHMENT ||
48 attachment1 == gl.DEPTH_STENCIL_ATTACHMENT;
49 var haveStencilBuffer = attachment0 == gl.STENCIL_ATTACHMENT ||
50 attachment0 == gl.DEPTH_STENCIL_ATTACHMENT ||
51 attachment1 == gl.STENCIL_ATTACHMENT ||
52 attachment1 == gl.DEPTH_STENCIL_ATTACHMENT;
53 shouldBeTrue("gl.getParameter(gl.RED_BITS) + gl.getParameter(gl.GREEN_BITS) + " +
54 "gl.getParameter(gl.BLUE_BITS) + gl.getParameter(gl.ALPHA_BITS) >= 16");
55 if (haveDepthBuffer)
56 shouldBeTrue("gl.getParameter(gl.DEPTH_BITS) >= 16");
57 else
58 shouldBeTrue("gl.getParameter(gl.DEPTH_BITS) == 0");
59 if (haveStencilBuffer)
60 shouldBeTrue("gl.getParameter(gl.STENCIL_BITS) >= 8");
61 else
62 shouldBeTrue("gl.getParameter(gl.STENCIL_BITS) == 0");
66 function testFramebufferWebGL1RequiredCombinations() {
67 debug("Checking combinations of framebuffer attachments required to be valid by WebGL 1");
69 // Per discussion with the OpenGL ES working group, the following framebuffer attachment
70 // combinations are required to work in all WebGL 1 implementations:
71 // 1. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture
72 // 2. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16 renderbuffer
73 // 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL renderbuffer
75 var fbo = gl.createFramebuffer();
76 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
78 var width = 64;
79 var height = 64;
81 // 1. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture
82 var texture = gl.createTexture();
83 gl.bindTexture(gl.TEXTURE_2D, texture);
84 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
85 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
86 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
87 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
88 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
89 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
90 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
91 checkBufferBits();
93 // 2. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16 renderbuffer
94 var renderbuffer = gl.createRenderbuffer();
95 gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
96 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);
97 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);
98 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
99 checkBufferBits(gl.DEPTH_ATTACHMENT);
100 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null);
102 // 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL renderbuffer
103 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
104 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);
105 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
106 checkBufferBits(gl.DEPTH_STENCIL_ATTACHMENT);
108 // Clean up
109 gl.deleteRenderbuffer(renderbuffer);
110 gl.deleteTexture(texture);
111 gl.deleteFramebuffer(fbo);
114 function testDepthStencilAttachmentBehaviors(testOrphanedRenderbuffers) {
115 let suffix = testOrphanedRenderbuffers ? " with deleted renderbuffer" : "";
116 debug("");
117 debug("Checking ES3 DEPTH_STENCIL_ATTACHMENT behaviors are implemented for WebGL 2" + suffix);
118 // DEPTH_STENCIL_ATTACHMENT is treated as an independent attachment point in WebGL 1;
119 // however, in WebGL 2, it is treated as an alias for DEPTH_ATTACHMENT + STENCIL_ATTACHMENT.
120 var size = 16;
122 var fbo = gl.createFramebuffer();
123 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
124 var colorBuffer = gl.createRenderbuffer();
125 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
126 gl.framebufferRenderbuffer(
127 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
128 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, size, size);
129 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
131 function createDepthBuffer() {
132 let buffer = gl.createRenderbuffer();
133 gl.bindRenderbuffer(gl.RENDERBUFFER, buffer);
134 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, size, size);
135 gl.bindRenderbuffer(gl.RENDERBUFFER, null);
136 return buffer;
139 function createStencilBuffer() {
140 let buffer = gl.createRenderbuffer();
141 gl.bindRenderbuffer(gl.RENDERBUFFER, buffer);
142 gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, size, size);
143 gl.bindRenderbuffer(gl.RENDERBUFFER, null);
144 return buffer;
147 function createDepthStencilBuffer() {
148 let buffer = gl.createRenderbuffer();
149 gl.bindRenderbuffer(gl.RENDERBUFFER, buffer);
150 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, size, size);
151 gl.bindRenderbuffer(gl.RENDERBUFFER, null);
152 return buffer;
155 function orphan(renderbuffer) {
156 gl.bindFramebuffer(gl.FRAMEBUFFER, null);
157 gl.deleteRenderbuffer(renderbuffer);
158 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
161 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
163 debug("");
164 debug("color + depth" + suffix);
165 var depthBuffer = createDepthBuffer();
166 gl.framebufferRenderbuffer(
167 gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
168 if (testOrphanedRenderbuffers)
169 orphan(depthBuffer);
170 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthBuffer);
171 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
172 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
173 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
174 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
175 checkBufferBits(gl.DEPTH_ATTACHMENT);
177 debug("");
178 debug("color + depth + stencil: depth != stencil" + suffix);
179 var stencilBuffer = createStencilBuffer();
180 gl.framebufferRenderbuffer(
181 gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencilBuffer);
182 if (testOrphanedRenderbuffers)
183 orphan(stencilBuffer);
184 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthBuffer);
185 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", stencilBuffer);
186 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
187 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
188 checkFramebuffer([gl.FRAMEBUFFER_UNSUPPORTED]);
190 gl.framebufferRenderbuffer(
191 gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, null);
192 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthBuffer);
193 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
194 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
195 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
197 debug("");
198 debug("color + depth: DEPTH_STENCIL for DEPTH_ATTACHMENT" + suffix);
199 var depthStencilBuffer = createDepthStencilBuffer();
200 gl.framebufferRenderbuffer(
201 gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
202 if (testOrphanedRenderbuffers)
203 orphan(depthStencilBuffer);
204 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
205 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
206 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
207 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
208 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
209 checkBufferBits(gl.DEPTH_ATTACHMENT);
211 debug("");
212 debug("color + depth + stencil: DEPTH_STENCIL for DEPTH_ATTACHMENT and STENCIL_ATTACHMENT" + suffix);
213 if (testOrphanedRenderbuffers) {
214 depthStencilBuffer = createDepthStencilBuffer();
215 gl.framebufferRenderbuffer(
216 gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
218 gl.framebufferRenderbuffer(
219 gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
220 if (testOrphanedRenderbuffers)
221 orphan(depthStencilBuffer);
222 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
223 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
224 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
225 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
226 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
227 checkBufferBits(gl.DEPTH_STENCIL_ATTACHMENT);
229 debug("");
230 debug("color + depth_stencil" + suffix);
231 var texture = gl.createTexture();
232 gl.bindTexture(gl.TEXTURE_2D, texture);
233 gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH24_STENCIL8, size, size, 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, null);
234 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, texture, 0);
235 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", texture);
236 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", texture);
237 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", texture);
238 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
239 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
241 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, null, 0);
242 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
243 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
244 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
245 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
247 if (testOrphanedRenderbuffers)
248 depthStencilBuffer = createDepthStencilBuffer();
249 gl.framebufferRenderbuffer(
250 gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
251 if (testOrphanedRenderbuffers)
252 orphan(depthStencilBuffer);
253 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
254 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
255 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
256 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
257 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
258 checkBufferBits(gl.DEPTH_STENCIL_ATTACHMENT);
260 debug("");
261 debug("DEPTH_STENCIL_ATTACHMENT overwrites DEPTH_ATTACHMENT/STENCIL_ATTACHMENT" + suffix);
262 if (testOrphanedRenderbuffers)
263 depthBuffer = createDepthBuffer();
264 gl.framebufferRenderbuffer(
265 gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
266 if (testOrphanedRenderbuffers)
267 orphan(depthBuffer);
268 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthBuffer);
269 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
270 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
271 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
273 if (testOrphanedRenderbuffers)
274 depthStencilBuffer = createDepthStencilBuffer();
275 gl.framebufferRenderbuffer(
276 gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
277 if (testOrphanedRenderbuffers)
278 orphan(depthStencilBuffer);
279 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
280 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
281 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
282 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
284 gl.framebufferRenderbuffer(
285 gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, null);
286 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
287 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
288 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
289 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
290 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
291 checkBufferBits();
293 debug("");
294 debug("STENCIL_ATTACHMENT overwrites stencil set by DEPTH_STENCIL_ATTACHMENT" + suffix);
295 if (testOrphanedRenderbuffers)
296 depthStencilBuffer = createDepthStencilBuffer();
297 gl.framebufferRenderbuffer(
298 gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
299 if (testOrphanedRenderbuffers)
300 orphan(depthStencilBuffer);
301 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
302 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
303 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
304 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
306 gl.framebufferRenderbuffer(
307 gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, null);
308 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
309 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
310 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
311 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
312 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
313 checkBufferBits(gl.DEPTH_ATTACHMENT);
315 debug("");
316 debug("DEPTH_ATTACHMENT overwrites depth set by DEPTH_STENCIL_ATTACHMENT" + suffix);
317 if (testOrphanedRenderbuffers)
318 depthStencilBuffer = createDepthStencilBuffer();
319 gl.framebufferRenderbuffer(
320 gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
321 if (testOrphanedRenderbuffers)
322 orphan(depthStencilBuffer);
323 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
324 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
325 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
326 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
328 gl.framebufferRenderbuffer(
329 gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null);
330 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
331 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", depthStencilBuffer);
332 shouldEvaluateTo("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", null);
333 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
334 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
335 checkBufferBits(gl.STENCIL_ATTACHMENT);
338 function testFramebufferIncompleteAttachment() {
339 var fbo = gl.createFramebuffer();
340 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
341 var colorBuffer = gl.createRenderbuffer();
342 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
343 gl.framebufferRenderbuffer(
344 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
345 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
346 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
348 debug("");
349 debug("Wrong storage type for type of attachment should be FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
350 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 16, 16);
351 checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]);
353 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
354 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
356 debug("");
357 debug("0 size attachment should be FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
358 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0);
359 checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]);
361 gl.deleteRenderbuffer(colorBuffer);
362 gl.deleteFramebuffer(fbo);
363 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
366 function testFramebufferIncompleteMissingAttachment() {
367 debug("");
368 debug("No attachments should be INCOMPLETE_FRAMEBUFFER_MISSING_ATTACHMENT");
369 var fbo = gl.createFramebuffer();
370 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
371 checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT]);
373 var colorBuffer = gl.createRenderbuffer();
374 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
375 gl.framebufferRenderbuffer(
376 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
377 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
378 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
380 gl.framebufferRenderbuffer(
381 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null);
382 checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT]);
384 gl.deleteRenderbuffer(colorBuffer);
385 gl.deleteFramebuffer(fbo);
386 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
389 function testFramebufferWithImagesOfDifferentSizes() {
390 debug("");
391 debug("Attachments of different sizes should NOT be allowed");
393 var fbo = gl.createFramebuffer();
394 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
395 var colorBuffer = gl.createRenderbuffer();
396 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
397 gl.framebufferRenderbuffer(
398 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
399 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16);
401 var depthBuffer = gl.createRenderbuffer();
402 gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
403 gl.framebufferRenderbuffer(
404 gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
405 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 16, 16);
406 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
407 checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]);
409 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 32, 16);
410 checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS]);
411 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
412 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 32);
413 checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS]);
414 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
416 var tex = gl.createTexture();
417 gl.bindTexture(gl.TEXTURE_2D, tex);
418 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
419 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
420 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
421 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
422 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
423 checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS]);
426 gl.deleteTexture(tex);
427 gl.deleteRenderbuffer(depthBuffer);
428 gl.deleteRenderbuffer(colorBuffer);
429 gl.deleteFramebuffer(fbo);
430 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
433 function testUsingIncompleteFramebuffer() {
434 debug("");
435 debug("Test drawing or reading from an incomplete framebuffer");
436 var program = wtu.setupTexturedQuad(gl);
437 var tex = gl.createTexture();
438 wtu.fillTexture(gl, tex, 1, 1, [0,255,0,255]);
440 var fbo = gl.createFramebuffer();
441 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
442 checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT]);
443 debug("");
444 debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION");
445 testRenderingAndReading();
447 var colorBuffer = gl.createRenderbuffer();
448 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
449 gl.framebufferRenderbuffer(
450 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
451 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0);
452 checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]);
453 debug("");
454 debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION");
455 testRenderingAndReading();
457 function testRenderingAndReading() {
458 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
459 wtu.clearAndDrawUnitQuad(gl);
460 wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "drawArrays with incomplete framebuffer");
461 gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
462 wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "readPixels from incomplete framebuffer");
463 // copyTexImage and copyTexSubImage can be either INVALID_FRAMEBUFFER_OPERATION because
464 // the framebuffer is invalid OR INVALID_OPERATION because in the case of no attachments
465 // the framebuffer is not of a compatible type.
466 gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
467 wtu.glErrorShouldBe(gl, [gl.INVALID_FRAMEBUFFER_OPERATION, gl.INVALID_OPERATION],
468 "copyTexImage2D from incomplete framebuffer");
469 gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 1, 1, 0);
470 wtu.glErrorShouldBe(gl, [gl.INVALID_FRAMEBUFFER_OPERATION, gl.INVALID_OPERATION],
471 "copyTexSubImage2D from incomplete framebuffer");
472 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
473 wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "clear with incomplete framebuffer");
476 gl.deleteRenderbuffer(colorBuffer);
477 gl.deleteFramebuffer(fbo);
478 gl.deleteTexture(tex);
479 gl.deleteProgram(program);
482 function testReadingFromMissingAttachment() {
483 debug("");
484 debug("Test drawing or reading from a framebuffer with no color image");
486 var fbo = gl.createFramebuffer();
487 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
488 var object_type = gl.getFramebufferAttachmentParameter(
489 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
490 if (object_type != gl.NONE)
491 testFailed("object type from empty attachment point should be NONE");
492 else
493 testPassed("object type from empty attachment point is NONE");
494 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query should not generate error");
496 var object_name = gl.getFramebufferAttachmentParameter(
497 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
498 if (object_name)
499 testFailed("object name from empty attachment point should be null");
500 else
501 testPassed("object name from empty attachment point is null");
502 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Query should not generate error");
504 var size = 16;
506 // The only scenario we can verify is an attempt to read or copy
507 // from a missing color attachment while the framebuffer is still
508 // complete.
509 var depthBuffer = gl.createRenderbuffer();
510 gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
511 gl.framebufferRenderbuffer(
512 gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
513 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, size, size);
514 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "After depth renderbuffer setup");
515 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
516 // The FBO has no color attachment. ReadPixels, CopyTexImage2D,
517 // and CopyTexSubImage2D should all generate INVALID_OPERATION.
518 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Before ReadPixels from missing attachment");
519 gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
520 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "After ReadPixels from missing attachment");
522 var tex = gl.createTexture();
523 gl.bindTexture(gl.TEXTURE_2D, tex);
524 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Before CopyTexImage2D from missing attachment");
525 gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, size, size, 0);
526 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "After CopyTexImage2D from missing attachment");
528 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
529 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Before CopyTexSubImage2D from missing attachment");
530 gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, size, size);
531 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "After CopyTexSubImage2D from missing attachment");
533 gl.deleteTexture(tex);
536 gl.deleteRenderbuffer(depthBuffer);
537 gl.deleteFramebuffer(fbo);
540 description("Test framebuffer object attachment behaviors");
542 shouldBeNonNull("gl = wtu.create3DContext(undefined, undefined, 2)");
544 testFramebufferWebGL1RequiredCombinations();
545 testDepthStencilAttachmentBehaviors(false);
546 testDepthStencilAttachmentBehaviors(true);
547 testFramebufferIncompleteAttachment();
548 testFramebufferIncompleteMissingAttachment();
549 testFramebufferWithImagesOfDifferentSizes();
550 testUsingIncompleteFramebuffer();
551 testReadingFromMissingAttachment();
553 // -
555 debug("");
556 debug("Test calling framebufferTexture2D with impossible mip levels.");
558 const fb = gl.createFramebuffer();
559 gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
561 const tex = gl.createTexture();
562 gl.bindTexture(gl.TEXTURE_2D, tex);
564 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 1000);
565 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Mip level attachment impossibly high.");
566 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 10);
567 wtu.glErrorShouldBe(gl, 0, "Mip level attachment within acceptable range.");
569 // Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1636517 :
570 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 1000);
571 wtu.glErrorShouldBe(gl, 0, "Mip level detachment can be impossibly high.");
572 shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "0");
574 // -
576 debug("")
577 var successfullyParsed = true;
578 </script>
580 <script src="../../js/js-test-post.js"></script>
581 </body>
582 </html>