diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers')
8 files changed, 1545 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/00_test_list.txt new file mode 100644 index 000000000..6445c9d48 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/00_test_list.txt @@ -0,0 +1,7 @@ +framebuffer-object-attachment.html +framebuffer-test.html +framebuffer-texture-layer.html +invalidate-framebuffer.html +multisampled-renderbuffer-initialization.html +--min-version 2.0.1 multisample-with-full-sample-counts.html +readbuffer.html diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-object-attachment.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-object-attachment.html new file mode 100644 index 000000000..d4963e606 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-object-attachment.html @@ -0,0 +1,427 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> + +<script> +"use strict"; +var wtu = WebGLTestUtils; +var gl; + +function checkFramebuffer(expected) { + var actual = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (expected.indexOf(actual) < 0) { + var msg = "checkFramebufferStatus expects ["; + for (var index = 0; index < expected.length; ++index) { + msg += wtu.glEnumToString(gl, expected[index]); + if (index + 1 < expected.length) + msg += ", "; + } + msg += "], was " + wtu.glEnumToString(gl, actual); + testFailed(msg); + } else { + var msg = "checkFramebufferStatus got " + wtu.glEnumToString(gl, actual) + + " as expected"; + testPassed(msg); + } +} + +function checkBufferBits(attachment0, attachment1) { + if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) + return; + var haveDepthBuffer = attachment0 == gl.DEPTH_ATTACHMENT || + attachment0 == gl.DEPTH_STENCIL_ATTACHMENT || + attachment1 == gl.DEPTH_ATTACHMENT || + attachment1 == gl.DEPTH_STENCIL_ATTACHMENT; + var haveStencilBuffer = attachment0 == gl.STENCIL_ATTACHMENT || + attachment0 == gl.DEPTH_STENCIL_ATTACHMENT || + attachment1 == gl.STENCIL_ATTACHMENT || + attachment1 == gl.DEPTH_STENCIL_ATTACHMENT; + shouldBeTrue("gl.getParameter(gl.RED_BITS) + gl.getParameter(gl.GREEN_BITS) + " + + "gl.getParameter(gl.BLUE_BITS) + gl.getParameter(gl.ALPHA_BITS) >= 16"); + if (haveDepthBuffer) + shouldBeTrue("gl.getParameter(gl.DEPTH_BITS) >= 16"); + else + shouldBeTrue("gl.getParameter(gl.DEPTH_BITS) == 0"); + if (haveStencilBuffer) + shouldBeTrue("gl.getParameter(gl.STENCIL_BITS) >= 8"); + else + shouldBeTrue("gl.getParameter(gl.STENCIL_BITS) == 0"); +} + + +function testFramebufferWebGL1RequiredCombinations() { + debug("Checking combinations of framebuffer attachments required to be valid by WebGL 1"); + + // Per discussion with the OpenGL ES working group, the following framebuffer attachment + // combinations are required to work in all WebGL 1 implementations: + // 1. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + // 2. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16 renderbuffer + // 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL renderbuffer + + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + + var width = 64; + var height = 64; + + // 1. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + checkBufferBits(); + + // 2. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16 renderbuffer + var renderbuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + checkBufferBits(gl.DEPTH_ATTACHMENT); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null); + + // 3. COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL renderbuffer + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + checkBufferBits(gl.DEPTH_STENCIL_ATTACHMENT); + + // Clean up + gl.deleteRenderbuffer(renderbuffer); + gl.deleteTexture(texture); + gl.deleteFramebuffer(fbo); +} + +function testDepthStencilAttachmentBehaviors() { + debug(""); + debug("Checking ES3 DEPTH_STENCIL_ATTACHMENT behaviors are implemented for WebGL 2"); + // DEPTH_STENCIL_ATTACHMENT is treated as an independent attachment point in WebGL 1; + // however, in WebGL 2, it is treated as an alias for DEPTH_ATTACHMENT + STENCIL_ATTACHMENT. + var size = 16; + + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + var colorBuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, size, size); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + + var depthBuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, size, size); + + var stencilBuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, stencilBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, size, size); + + var depthStencilBuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, size, size); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + debug("color + depth"); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + checkBufferBits(gl.DEPTH_ATTACHMENT); + + debug("color + depth + stencil: depth != stencil"); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencilBuffer); + checkFramebuffer([gl.FRAMEBUFFER_UNSUPPORTED]); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, null); + + debug("color + depth: DEPTH_STENCIL for DEPTH_ATTACHMENT"); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + checkBufferBits(gl.DEPTH_ATTACHMENT); + + debug("color + depth + stencil: DEPTH_STENCIL for DEPTH_ATTACHMENT and STENCIL_ATTACHMENT"); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + checkBufferBits(gl.DEPTH_STENCIL_ATTACHMENT); + + debug("color + depth_stencil"); + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH24_STENCIL8, size, size, 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, null); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, texture, 0); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, null, 0); + + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + checkBufferBits(gl.DEPTH_STENCIL_ATTACHMENT); + + debug("DEPTH_STENCIL_ATTACHMENT overwrites DEPTH_ATTACHMENT/STENCIL_ATTACHMENT") + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, null); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + checkBufferBits(); + + debug("STENCIL_ATTACHMENT overwrites stencil set by DEPTH_STENCIL_ATTACHMENT") + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, null); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + checkBufferBits(gl.DEPTH_ATTACHMENT); +} + +function testFramebufferIncompleteAttachment() { + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + var colorBuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + + debug(""); + debug("Wrong storage type for type of attachment should be FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 16, 16); + checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]); + + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + + debug(""); + debug("0 size attachment should be FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0); + checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]); + + gl.deleteRenderbuffer(colorBuffer); + gl.deleteFramebuffer(fbo); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); +} + +function testFramebufferIncompleteMissingAttachment() { + debug(""); + debug("No attachments should be INCOMPLETE_FRAMEBUFFER_MISSING_ATTACHMENT"); + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT]); + + var colorBuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null); + checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT]); + + gl.deleteRenderbuffer(colorBuffer); + gl.deleteFramebuffer(fbo); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); +} + +function testFramebufferWithImagesOfDifferentSizes() { + debug(""); + debug("Attachments of different sizes should NOT be allowed"); + + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + var colorBuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16); + + var depthBuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 16, 16); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 32, 16); + checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS]); + gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 32); + checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) { + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS]); + } + + gl.deleteTexture(tex); + gl.deleteRenderbuffer(depthBuffer); + gl.deleteRenderbuffer(colorBuffer); + gl.deleteFramebuffer(fbo); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); +} + +function testUsingIncompleteFramebuffer() { + debug(""); + debug("Test drawing or reading from an incomplete framebuffer"); + var program = wtu.setupTexturedQuad(gl); + var tex = gl.createTexture(); + wtu.fillTexture(gl, tex, 1, 1, [0,255,0,255]); + + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT]); + debug(""); + debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION"); + testRenderingAndReading(); + + var colorBuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0); + checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]); + debug(""); + debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION"); + testRenderingAndReading(); + + function testRenderingAndReading() { + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + wtu.clearAndDrawUnitQuad(gl); + wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "drawArrays with incomplete framebuffer"); + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4)); + wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "readPixels from incomplete framebuffer"); + // copyTexImage and copyTexSubImage can be either INVALID_FRAMEBUFFER_OPERATION because + // the framebuffer is invalid OR INVALID_OPERATION because in the case of no attachments + // the framebuffer is not of a compatible type. + gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1); + wtu.glErrorShouldBe(gl, [gl.INVALID_FRAMEBUFFER_OPERATION, gl.INVALID_OPERATION], + "copyTexImage2D from incomplete framebuffer"); + gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 1, 1, 0); + wtu.glErrorShouldBe(gl, [gl.INVALID_FRAMEBUFFER_OPERATION, gl.INVALID_OPERATION], + "copyTexSubImage2D from incomplete framebuffer"); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "clear with incomplete framebuffer"); + } + + gl.deleteRenderbuffer(colorBuffer); + gl.deleteFramebuffer(fbo); + gl.deleteTexture(tex); + gl.deleteProgram(program); +} + +function testReadingFromMissingAttachment() { + debug(""); + debug("Test drawing or reading from a framebuffer with no color image"); + + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + + var size = 16; + + // The only scenario we can verify is an attempt to read or copy + // from a missing color attachment while the framebuffer is still + // complete. + var depthBuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, size, size); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "After depth renderbuffer setup"); + if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) { + // The FBO has no color attachment. ReadPixels, CopyTexImage2D, + // and CopyTexSubImage2D should all generate INVALID_OPERATION. + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Before ReadPixels from missing attachment"); + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4)); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "After ReadPixels from missing attachment"); + + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Before CopyTexImage2D from missing attachment"); + gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, size, size, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "After CopyTexImage2D from missing attachment"); + + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Before CopyTexSubImage2D from missing attachment"); + gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, size, size); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "After CopyTexSubImage2D from missing attachment"); + + gl.deleteTexture(tex); + } + + gl.deleteRenderbuffer(depthBuffer); + gl.deleteFramebuffer(fbo); +} + +description("Test framebuffer object attachment behaviors"); + +shouldBeNonNull("gl = wtu.create3DContext(undefined, undefined, 2)"); + +testFramebufferWebGL1RequiredCombinations(); +testDepthStencilAttachmentBehaviors(); +testFramebufferIncompleteAttachment(); +testFramebufferIncompleteMissingAttachment(); +testFramebufferWithImagesOfDifferentSizes(); +testUsingIncompleteFramebuffer(); +testReadingFromMissingAttachment(); + +debug("") +var successfullyParsed = true; +</script> + +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-test.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-test.html new file mode 100644 index 000000000..135531d22 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-test.html @@ -0,0 +1,309 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL Framebuffer Test Against WebGL 2</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="2" height="2"> </canvas> +<script> +"use strict"; +var wtu = WebGLTestUtils; +var gl; + +function testFramebufferRenderbuffer() { + debug(""); + debug("Checking framebuffer/renderbuffer stuff."); + + gl.getFramebufferAttachmentParameter( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, + "getFramebufferAttachmentParameter(COLOR_ATTACHMENT0) on the default framebuffer."); + gl.getFramebufferAttachmentParameter( + gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "getFramebufferAttachmentParameter(BACK) on the default framebuffer."); + gl.checkFramebufferStatus(gl.FRAMEBUFFER); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "checkFramebufferStatus on the default framebuffer."); + + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texImage2D( + gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "attach a texture to default framebuffer."); + + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "detach default renderbuffer from default framebuffer."); + + var rb = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, rb); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, canvas.width, canvas.height); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "allocate renderbuffer storage of a newly created renderbuffer."); + + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "attach a renderbuffer to the default framebuffer."); + + var fbtex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, fbtex); + gl.texImage2D( + gl.TEXTURE_2D, 0, gl.RGBA, canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + var fb = gl.createFramebuffer(); + + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bind a newly created framebuffer."); + + var target = gl.READ_FRAMEBUFFER; + gl.getFramebufferAttachmentParameter( + target, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getFramebufferAttachmentParameter(READ_FRAMEBUFFER)."); + assertMsg(gl.checkFramebufferStatus(target) != 0, + "checkFramebufferStatus(READ_FRAMEBUFFER) should succeed."); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "checkFramebufferStatus(READ_FRAMEBUFFER)."); + var readFB = gl.createFramebuffer(); + gl.bindFramebuffer(target, readFB); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bindFramebuffer(READ_FRAMEBUFFER)."); + assertMsg(readFB == gl.getParameter(gl.READ_FRAMEBUFFER_BINDING), + "bindFramebuffer(READ_FRAMEBUFFER) should change READ_FRAMEBUFFER_BINDING."); + assertMsg(fb == gl.getParameter(gl.DRAW_FRAMEBUFFER_BINDING), + "bindFramebuffer(READ_FRAMEBUFFER) should not change DRAW_FRAMEBUFFER_BINDING."); + gl.getFramebufferAttachmentParameter( + target, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) with no attachment."); + gl.framebufferTexture2D(target, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "framebufferTexImage2D(READ_FRAMEBUFFER)."); + gl.framebufferRenderbuffer(target, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "framebufferRenderbuffer(READ_FRAMEBUFFER)."); + + var colorAttachmentsNum = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS); + if (colorAttachmentsNum >= 2) { + var attachment = gl.COLOR_ATTACHMENT1; + gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, fbtex, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "framebufferTexImage2D(COLOR_ATTACHMENT1)."); + gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, null, 0); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, rb); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "framebufferRenderbuffer(COLOR_ATTACHMENT1)."); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, null); + } + + gl.getFramebufferAttachmentParameter( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "getFramebufferAttachmentParameter(GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " + + "with no attachment."); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "attach a texture to a framebuffer."); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "detach a texture from a framebuffer."); + + function numLevelsFromSize(size) { + var levels = 0; + while ((size >> levels) > 0) { + ++levels; + } + return levels; + } + + var maxTexSize = gl.getParameter(gl.MAX_TEXTURE_SIZE); + var maxLevels = numLevelsFromSize(maxTexSize); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, maxLevels - 1); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "framebufferTexture2D with an appropriate mipmap level."); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, maxLevels); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "framebufferTexture2D with a mipmap level out of range."); + + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "attach a renderbuffer to a framebuffer."); + + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "detach a renderbuffer from a framebuffer."); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bind default (null) framebuffer."); + + // attach/detach a 2d texture to one framebuffer binding point, + // while no attachment to the other binding point. + function attachAndDetachTexture(targetA, targetB) { + gl.framebufferTexture2D(targetA, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "attach a texture to read/draw framebuffer binding point."); + gl.getFramebufferAttachmentParameter( + targetA, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " + + "on read/draw framebuffer."); + gl.getFramebufferAttachmentParameter( + targetB, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " + + "on read/draw framebuffer with no attachment."); + gl.framebufferTexture2D(targetA, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "detach a texture from read/draw framebuffer."); + } + + var readFBWithTexture = gl.createFramebuffer(); + var drawFBWithTexture = gl.createFramebuffer(); + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFBWithTexture); + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, drawFBWithTexture); + attachAndDetachTexture(gl.READ_FRAMEBUFFER, gl.DRAW_FRAMEBUFFER); + attachAndDetachTexture(gl.DRAW_FRAMEBUFFER, gl.READ_FRAMEBUFFER); + + // attach different textures as color attachment to read and draw framebuffer respectively, + // then detach these attachments. + var fbtex1 = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, fbtex1); + gl.texImage2D( + gl.TEXTURE_2D, 0, gl.RG8, canvas.width, canvas.height, 0, gl.RG, gl.UNSIGNED_BYTE, null); + gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex1, 0); + gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.READ_FRAMEBUFFER, ' + + 'gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE)'); + shouldBe('gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ' + + 'gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE)', '0'); + + gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0); + gl.getFramebufferAttachmentParameter( + gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " + + "on read framebuffer with no attachment."); + gl.getFramebufferAttachmentParameter( + gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " + + "on draw framebuffer."); + gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0); + gl.getFramebufferAttachmentParameter( + gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " + + "on draw framebuffer with no attachment."); + + // attach/detach a renderbuffer to one framebuffer binding point, + // while no attachment to the other binding point. + function attachAndDetachRenderbuffer(targetA, targetB) { + gl.framebufferRenderbuffer(targetA, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "attaching a renderbuffer to a read/draw framebuffer."); + gl.getFramebufferAttachmentParameter( + targetA, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " + + "on read/draw framebuffer."); + gl.getFramebufferAttachmentParameter( + targetB, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING) " + + "on read/draw framebuffer with no attachment."); + gl.framebufferRenderbuffer(targetA, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "detach a renderbuffer from a read/draw framebuffer."); + } + + var readFBWithRenderbuffer = gl.createFramebuffer(); + var drawFBWithRenderbuffer = gl.createFramebuffer(); + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFBWithRenderbuffer); + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, drawFBWithRenderbuffer); + attachAndDetachRenderbuffer(gl.READ_FRAMEBUFFER, gl.DRAW_FRAMEBUFFER); + attachAndDetachRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.READ_FRAMEBUFFER); + + // attach different renderbuffers to read and draw framebuffer respectively, + // then detach these attachments. + var depthRB = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, depthRB); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, canvas.width, canvas.height); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "allocating renderbuffer storage of a newly created renderbuffer."); + gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRB); + gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.READ_FRAMEBUFFER, ' + + 'gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_RED_SIZE)'); + gl.getFramebufferAttachmentParameter( + gl.READ_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_DEPTH_SIZE); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE) " + + "on read framebuffer without depth attachment."); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, ' + + 'gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE)'); + gl.getFramebufferAttachmentParameter( + gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_RED_SIZE); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_RED_SIZE) " + + "on draw framebuffer without color attachment."); + + gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null); + gl.getFramebufferAttachmentParameter( + gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_RED_SIZE); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_RED_SIZE) " + + "on read framebuffer with no attachment."); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, ' + + 'gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE)'); + gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null); + gl.getFramebufferAttachmentParameter( + gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_DEPTH_SIZE); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "getFramebufferAttachmentParameter(FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE) " + + "on draw framebuffer with no attachment."); + + // binding read/draw framebuffer to default framebuffer + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bind read framebuffer to default (null) framebuffer."); + + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bind draw framebuffer to default (null) framebuffer."); +} + +description("This tests framebuffer/renderbuffer-related functions"); + +var canvas = document.getElementById("canvas"); +shouldBeNonNull("gl = wtu.create3DContext(canvas, undefined, 2)"); + +testFramebufferRenderbuffer(); + +debug(""); +var successfullyParsed = true; + +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-texture-layer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-texture-layer.html new file mode 100644 index 000000000..1b5fb694a --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/framebuffer-texture-layer.html @@ -0,0 +1,165 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL FramebufferTextureLayer Test</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="2" height="2"> </canvas> + +<script> +"use strict"; +var wtu = WebGLTestUtils; +var gl; +var canvas = document.getElementById("canvas"); + +function numLevelsFromSize(size) { + var levels = 0; + while ((size >> levels) > 0) { + ++levels; + } + return levels; +} + +function checkFramebuffer(expected) { + var actual = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (expected.indexOf(actual) < 0) { + var msg = "checkFramebufferStatus expects ["; + for (var index = 0; index < expected.length; ++index) { + msg += wtu.glEnumToString(gl, expected[index]); + if (index + 1 < expected.length) + msg += ", "; + } + msg += "], was " + wtu.glEnumToString(gl, actual); + testFailed(msg); + } else { + var msg = "checkFramebufferStatus got " + wtu.glEnumToString(gl, actual) + + " as expected"; + testPassed(msg); + } +} + +function testFramebufferTextureLayer() { + debug(""); + debug("Checking FramebufferTextureLayer stuff."); + + var tex3d = gl.createTexture(); + var fb = gl.createFramebuffer(); + gl.bindTexture(gl.TEXTURE_3D, tex3d); + gl.texImage3D(gl.TEXTURE_3D, + 0, // level + gl.RGBA, // internalFormat + 1, // width + 1, // height + 1, // depth + 0, // border + gl.RGBA, // format + gl.UNSIGNED_BYTE, // type + new Uint8Array([0xff, 0x00, 0x00, 0x00])); // data + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, 0, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "attaching a texture to default framebuffer should generate INVALID_OPERATION."); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, 0, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "attaching a texture to a framebuffer should succeed."); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, null, 0, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "detaching a texture from a framebuffer should succeed."); + + var maxTexSize = gl.getParameter(gl.MAX_3D_TEXTURE_SIZE); + var maxLevels = numLevelsFromSize(maxTexSize); + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, maxLevels - 1, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling framebufferTextureLayer with an appropriate mipmap level should succeed."); + checkFramebuffer([gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT]); + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, maxLevels, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, + "calling framebufferTextureLayer with a mipmap level out of range should generate INVALID_VALUE."); + + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, 0, -1); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, + "calling framebufferTextureLayer with a negative texture layer should generate INVALID_VALUE."); + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3d, 0, maxTexSize); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, + "calling framebufferTextureLayer with a texture layer out of range should generate INVALID_VALUE."); + + var tex2d = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex2d); + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex2d, 0, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "attaching a 2d texture to a framebuffer should generate INVALID_OPERATION."); + + var texDepthStencil = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D_ARRAY, texDepthStencil); + var fbDepthStencil = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbDepthStencil); + gl.texImage3D(gl.TEXTURE_2D_ARRAY, + 0, // level + gl.DEPTH24_STENCIL8, // internalFormat + 1, // width + 1, // height + 1, // depth + 0, // border + gl.DEPTH_STENCIL, // format + gl.UNSIGNED_INT_24_8, // type + new Uint32Array([0])); // data + gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, texDepthStencil, 0, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "attaching a depth_stencil texture to a framebuffer should succeed."); + checkFramebuffer([gl.FRAMEBUFFER_COMPLETE]); + + // Clean up + gl.deleteTexture(tex3d); + gl.deleteTexture(texDepthStencil); + gl.deleteTexture(tex2d); + gl.deleteFramebuffer(fb); + gl.deleteFramebuffer(fbDepthStencil); +} + +description("This tests framebufferTextureLayer."); + +shouldBeNonNull("gl = wtu.create3DContext(undefined, undefined, 2)"); + +testFramebufferTextureLayer(); + +debug(""); +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/invalidate-framebuffer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/invalidate-framebuffer.html new file mode 100644 index 000000000..b4811ab3a --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/invalidate-framebuffer.html @@ -0,0 +1,173 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Invalidate Framebuffer Against WebGL 2</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="20" height="20"> </canvas> +<script> +"use strict"; +description("This tests invalidateFramebuffer and invalidateSubFramebuffer"); + +debug(""); +debug("Canvas.getContext"); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, { depth : true, stencil : false }, 2); +if (!gl) { + testFailed("context does not exist"); +} else { + testPassed("context exists"); + + debug(""); + debug("invalidate framebuffer."); + + gl.clearColor(0, 0, 0, 0); + + // setup framebuffer with depth attachment and multi-sampled color attachment + var fb_m = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb_m); + + var rb_m = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, rb_m); + var samples = gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb_m); + // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the attached renderbuffer + invalidateIncompleteAttachment(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0); + gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[0], gl.RGBA8, canvas.width, canvas.height); + gl.clear(gl.COLOR_BUFFER_BIT); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "should be no errors after attaching a multi-sampled renderbuffer to fbo."); + + var rb = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, rb); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb); + // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the attached renderbuffer + invalidateIncompleteAttachment(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT); + gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[0], gl.DEPTH_COMPONENT16, canvas.width, canvas.height); + gl.clear(gl.DEPTH_BUFFER_BIT); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "should be no errors after attaching a renderbuffer to fbo."); + + // in real world case, after some drawing, we can invalidate the depth attachment of the bound fbo + invalidation(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.STENCIL_ATTACHMENT); + + // set up framebuffer to blit to and read back from + var fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + var buffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, buffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, canvas.width, canvas.height); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, buffer); + gl.clear(gl.COLOR_BUFFER_BIT); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "should be no errors after attaching a renderbuffer to fbo."); + + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb_m); + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb); + gl.blitFramebuffer(0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height, gl.COLOR_BUFFER_BIT, gl.NEAREST); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "should be no errors after bliting framebuffer."); + + // invalidate the multi-sampled color attachment of the bound read framebuffer after blitFramebuffer. + invalidation(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.DEPTH_ATTACHMENT); + + var maxColorAttachments = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS); + gl.invalidateSubFramebuffer(gl.READ_FRAMEBUFFER, [gl.COLOR_ATTACHMENT0 + maxColorAttachments], 5, 5, 10, 10); + wtu.glErrorShouldBe(gl, [gl.INVALID_OPERATION, gl.INVALID_ENUM], + "calling invalidateSubFramebuffer to invalidate a COLOR_ATTACHMENT that exceeds MAX_COLOR_ATTACHMENT should generate INVALID_ENUM or INVALID_OPERATION."); + gl.invalidateFramebuffer(gl.READ_FRAMEBUFFER, [gl.COLOR_ATTACHMENT0 + maxColorAttachments]); + wtu.glErrorShouldBe(gl, [gl.INVALID_OPERATION, gl.INVALID_ENUM], + "calling invalidateFramebuffer to invalidate a COLOR_ATTACHMENT that exceeds MAX_COLOR_ATTACHMENT should generate INVALID_ENUM or INVALID_OPERATION."); + + // invalidate the default framebuffer + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + invalidation(gl.FRAMEBUFFER, gl.DEPTH, gl.STENCIL); + + gl.deleteFramebuffer(fb_m); + gl.deleteRenderbuffer(rb_m); + gl.deleteRenderbuffer(rb); + gl.deleteFramebuffer(fb); + gl.deleteRenderbuffer(buffer); +} + +function invalidation(target, valid_attachment, invalid_attachment) { + gl.invalidateSubFramebuffer(target, [invalid_attachment], 5, 5, 10, 10); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling invalidateSubFramebuffer to invalidate a specified attachment that does not exist will be ignored. There should be no errors."); + gl.invalidateSubFramebuffer(target, [valid_attachment], 5, 5, 10, 10); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling invalidateSubFramebuffer should succeed."); + + gl.invalidateSubFramebuffer(target, [valid_attachment], 5, 5, -5, -5); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, + "calling invalidateSubFramebuffer should generate INVALID_VALUE if width < 0 or height < 0."); + + gl.invalidateSubFramebuffer(target, [valid_attachment], -5, -5, 10, 10); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling invalidateSubFramebuffer should succeed, even the invalidated pixels may be outside of the framebuffer allocated to current context. These pixels are ignored."); + gl.invalidateSubFramebuffer(target, [valid_attachment], 5, 5, 20, 20); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling invalidateSubFramebuffer should succeed, even the invalidated pixels may be outside of the framebuffer allocated to current context. These pixels are ignored."); + + gl.invalidateFramebuffer(target, [invalid_attachment]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling invalidateFramebuffer to invalidate a specified attachment that does not exist will be ignored. There should be no errors."); + gl.invalidateFramebuffer(target, [valid_attachment]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling invalidateFramebuffer should succeed."); +} + +function invalidateIncompleteAttachment(target, incomplete_attachment) { + shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", + "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); + gl.invalidateSubFramebuffer(target, [incomplete_attachment], 5, 5, 10, 10); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling invalidateSubFramebuffer to invalidate an incomplete attachment will be ignored. There should be no errors"); + gl.invalidateFramebuffer(target, [incomplete_attachment]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling invalidateFramebuffer to invalidate an incomplete attachment will be ignored. There should be no errors."); +} + +debug(""); +var successfullyParsed = true; + +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisample-with-full-sample-counts.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisample-with-full-sample-counts.html new file mode 100644 index 000000000..0a3f3ef4b --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisample-with-full-sample-counts.html @@ -0,0 +1,119 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<canvas id="canvas" width="32" height="32" style="width: 32px; height: 32px;"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +var wtu = WebGLTestUtils; +description(' Test multisample with sample number from 1 to max sample number which also includes the samples that may not be in the supported sample list'); + +var gl = wtu.create3DContext("canvas", null, 2); +var size = 32; +var program; + +if (!gl) { + testFailed('canvas.getContext() failed'); +} else { + program = wtu.setupColorQuad(gl); + gl.viewport(0, 0, size, size); + var supportedSampleCountArray = gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES); + var iterationCount = supportedSampleCountArray[0] + 1; + for (var i = 1; i < iterationCount; i++) + { + runTest(gl, i, false); + runTest(gl, i, true); + } +} + +function runTest(gl, sampleCount, isInverted) { + // Setup multi-sample RBO + var msColorRbo = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, msColorRbo); + gl.renderbufferStorageMultisample(gl.RENDERBUFFER, sampleCount, gl.RGBA8, size, size); + + // Setup multi-sample FBO. + var msFbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, msFbo); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, msColorRbo); + + // Setup resolve color RBO. + var resolveColorRbo = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, resolveColorRbo); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, size, size); + // Setup resolve FBO + var resolveFbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, resolveFbo); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, resolveColorRbo); + + gl.bindFramebuffer(gl.FRAMEBUFFER, msFbo); + if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { + testFailed("Framebuffer incomplete."); + return; + } + gl.clearColor(0.0, 0.0, 0.0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT); + + gl.enable(gl.SAMPLE_COVERAGE); + var coverageValue = isInverted ? 0.0 : 1.0; + gl.sampleCoverage(coverageValue, isInverted); + + var quadColor = [1.0, 0.0, 0.0, 1.0]; + gl.useProgram(program); + wtu.drawFloatColorQuad(gl, quadColor); + + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, resolveFbo); + gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST); + + gl.bindFramebuffer(gl.FRAMEBUFFER, resolveFbo); + wtu.checkCanvasRect(gl, 0, 0, size, size, [255, 0, 0, 255], + "User buffer has been rendered to red with sample = " + + sampleCount + ", coverageValue = " + coverageValue + + " and isInverted = " + isInverted, 3); + + gl.disable(gl.SAMPLE_COVERAGE); + gl.deleteRenderbuffer(msColorRbo); + gl.deleteRenderbuffer(resolveColorRbo); + gl.deleteFramebuffer(msFbo); + gl.deleteFramebuffer(resolveFbo); +} + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-renderbuffer-initialization.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-renderbuffer-initialization.html new file mode 100644 index 000000000..58f2286ae --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/multisampled-renderbuffer-initialization.html @@ -0,0 +1,150 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<canvas id="testbed" width="40" height="40" style="width: 40px; height: 40px;"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +var wtu = WebGLTestUtils; +description('Verify multisampled renderbuffers are initialized to 0 before being read in WebGL'); + +var gl = wtu.create3DContext("testbed", null, 2); + +if (!gl) { + testFailed('canvas.getContext() failed'); +} else { + // Set the clear color to green. It should never show up. + gl.clearColor(0, 1, 0, 1); + + runTest(gl, gl.canvas.width, gl.canvas.height, 0); + runTest(gl, gl.canvas.width, gl.canvas.height, 1); + runTest(gl, gl.canvas.width, gl.canvas.height, 0); + runTest(gl, gl.canvas.width, gl.canvas.height, 1); + + // Testing buffer clearing won't change the clear values. + var clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE); + shouldBe("clearColor", "[0, 1, 0, 1]"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors'); +} + +function runTest(gl, width, height, order) { + wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 0, 0, 0], + "internal buffers have been initialized to 0"); + + // fill the back buffer so we know that reading below happens from + // the renderbuffer. + gl.clear(gl.COLOR_BUFFER_BIT); + + // Set up non-multisampled buffer to blit to and read back from. + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + var buffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, buffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, width, height); + attachBuffer(buffer); + shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", + "gl.FRAMEBUFFER_COMPLETE"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors'); + gl.clear(gl.COLOR_BUFFER_BIT); + wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255], + "user buffer has been cleared to green"); + + // Set up multisampled buffer to test. + var fbo_m = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo_m); + var buffer_m = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, buffer_m); + switch (order) { + case 0: + allocStorage(width, height); + attachBuffer(buffer_m); + break; + case 1: + attachBuffer(buffer_m); + allocStorage(width, height); + break; + } + + function allocStorage(width, height) { + var samples = gl.getInternalformatParameter( + gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES); + gl.renderbufferStorageMultisample( + gl.RENDERBUFFER, samples[0], gl.RGBA8, width, height); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "should be no error after renderbufferStorageMultisample(RGBA8)."); + } + + function attachBuffer(buffer) { + gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, buffer); + } + + shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", + "gl.FRAMEBUFFER_COMPLETE"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors'); + + // Blit from multisampled buffer to non-multisampled buffer. + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_m); + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo); + gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, + gl.COLOR_BUFFER_BIT, gl.NEAREST); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors'); + + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 0, 0, 0], + "user buffer has been initialized to 0"); + + gl.deleteFramebuffer(fbo_m); + gl.deleteRenderbuffer(buffer_m); + gl.deleteFramebuffer(fbo); + gl.deleteRenderbuffer(buffer); + + // this clear should not matter we are about to resize + gl.clear(gl.COLOR_BUFFER_BIT); + + gl.canvas.width += 1; + gl.canvas.height += 1; + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, 'should be no errors'); + debug(''); +} + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/readbuffer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/readbuffer.html new file mode 100644 index 000000000..5be3c522b --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/renderbuffers/readbuffer.html @@ -0,0 +1,195 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Test readBuffer Against WebGL 2</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<canvas id="canvas" width="20" height="20"> </canvas> +<script> +"use strict"; +description("This tests reading from fbo"); + +var clearDrawingbuffer = function(color) { + gl.clearColor(color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255); + gl.clear(gl.COLOR_BUFFER_BIT); +} + +var validateReadingFromFramebuffer = function(color, expected, msg) { + var pixels = new Uint8Array(1 * 1 * 4); + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + wtu.glErrorShouldBe(gl, expected, msg); + if (expected == gl.NO_ERROR) + wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, color, + "the color should be [" + color + "]"); +} + +var setupRenderbuffer = function(attachment) { + var renderbuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, renderbuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, canvas.width, canvas.height); + return renderbuffer; +} + +var testReadBufferOnDefaultFB = function() { + gl.readBuffer(gl.NONE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling readBuffer with GL_NONE on the default framebuffer should succeed."); + var pixels = new Uint8Array(1 * 1 * 4); + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "should generate INVALID_OPERATION when reading from framebuffer and read buffer is GL_NONE."); + gl.readBuffer(gl.BACK); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling readBuffer with GL_BACK on the default framebuffer should succeed."); + + gl.readBuffer(gl.COLOR_ATTACHMENT0); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "calling readBuffer with GL_COLOR_ATTACHMENT0 on the default framebuffer should generate INVALID_OPERATION."); +} + +var testReadBufferOnFBO = function() { + gl.readBuffer(gl.BACK); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "calling readBuffer with GL_BACK on fbo should generate INVALID_OPERATION."); + + gl.readBuffer(gl.NONE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling readBuffer with GL_NONE on fbo should succeed."); + var pixels = new Uint8Array(1 * 1 * 4); + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, + "should generate INVALID_OPERATION when reading from framebuffer and read buffer is GL_NONE."); + gl.readBuffer(gl.COLOR_ATTACHMENT0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling readBuffer with GL_COLOR_ATTACHMENT0 on fbo should succeed."); + + var maxColorAttachments = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS); + gl.readBuffer(gl.COLOR_ATTACHMENT0 + maxColorAttachments); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, + "calling readBuffer with GL_COLOR_ATTACHMENTi that exceeds MAX_COLOR_ATTACHMENT on fbo should generate INVALID_ENUM."); + gl.readBuffer(gl.COLOR_ATTACHMENT1); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling readBuffer with GL_COLOR_ATTACHMENT1 on the fbo should succeed."); + shouldBe('gl.getParameter(gl.READ_BUFFER)', 'gl.COLOR_ATTACHMENT1'); +} + +debug(""); +debug("Canvas.getContext"); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, undefined, 2); +if (!gl) { + testFailed("context does not exist"); +} else { + testPassed("context exists"); + + debug(""); + debug("Checking reading from framebuffer."); + + // Test on the default framebuffer. Read buffer is GL_BACK by default. + var backColor = [0, 0, 0, 255]; + clearDrawingbuffer(backColor); + validateReadingFromFramebuffer(backColor, gl.NO_ERROR, + "should be no errors when reading from GL_BACK on the default framebuffer."); + + shouldBe('gl.getParameter(gl.READ_BUFFER)', 'gl.BACK'); + testReadBufferOnDefaultFB(); + + // Test on fbo. Read buffer is GL_COLOR_ATTACHMENT0 by default + var fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + var colorbuffer = setupRenderbuffer(gl.COLOR_ATTACHMENT0); + var red = [255, 0, 0, 255]; + clearDrawingbuffer(red); + validateReadingFromFramebuffer(red, gl.NO_ERROR, + "should be no errors when reading from GL_COLOR_ATTACHMENT0 on fbo."); + + shouldBe('gl.getParameter(gl.READ_BUFFER)', 'gl.COLOR_ATTACHMENT0'); + testReadBufferOnFBO(); + + // Test on user defined read buffer (GL_COLOR_ATTACHMENT1) with or without corresponding image on fbo. + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + var colorbuffer1 = setupRenderbuffer(gl.COLOR_ATTACHMENT1); + var green = [0, 255, 0, 255]; + gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]); + clearDrawingbuffer(green); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no error after setup and clear render buffer"); + gl.readBuffer(gl.COLOR_ATTACHMENT1); + validateReadingFromFramebuffer(green, gl.NO_ERROR, + "should be no errors when reading from GL_COLOR_ATTACHMENT1 on fbo."); + shouldBe('gl.getParameter(gl.READ_BUFFER)', 'gl.COLOR_ATTACHMENT1'); + // Need to reset draw buffers, otherwise it triggers a mac driver bug. + // We add a separate test for that bug: conformance2/rendering/framebuffer-completeness-unaffected.html + gl.drawBuffers([gl.COLOR_ATTACHMENT0]); + + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.RENDERBUFFER, null) + gl.readBuffer(gl.COLOR_ATTACHMENT1); + validateReadingFromFramebuffer(null, gl.INVALID_OPERATION, + "should generate INVALID_OPERATION when reading from GL_COLOR_ATTACHMENT1 but this attachment has no image currently."); + + // switch to another fbo, read buffer is GL_COLOR_ATTACHMENT0, not GL_COLOR_ATTACHMENT1 + var fb1 = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb1); + var buffer = setupRenderbuffer(gl.COLOR_ATTACHMENT0); + shouldBe('gl.getParameter(gl.READ_BUFFER)', 'gl.COLOR_ATTACHMENT0'); + var blue = [0, 0, 255, 255]; + clearDrawingbuffer(blue); + validateReadingFromFramebuffer(blue, gl.NO_ERROR, + "should be no errors when reading from GL_COLOR_ATTACHMENT0 on another fbo."); + + // switch from fbo to default fb, read buffer will switch to GL_BACK from GL_COLOR_ATTACHMENT0 + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + shouldBe('gl.getParameter(gl.READ_BUFFER)', 'gl.BACK'); + validateReadingFromFramebuffer(backColor, gl.NO_ERROR, + "should be no errors when reading from GL_BACK on the default framebuffer."); + + gl.deleteFramebuffer(fb); + gl.deleteRenderbuffer(colorbuffer); + gl.deleteRenderbuffer(colorbuffer1); + gl.deleteFramebuffer(fb1); + gl.deleteRenderbuffer(buffer); +} + +debug(""); +var successfullyParsed = true; + +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> |