| <!DOCTYPE html> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script src="resources/webxr_util.js"></script> | |
| <script src="resources/webxr_test_constants.js"></script> | |
| <script> | |
| let immersiveTestName = "Ensure that the framebuffer given by the WebGL layer" + | |
| " is opaque for immersive"; | |
| let nonImmersiveTestName = "Ensure that the framebuffer given by the WebGL layer" + | |
| " is opaque for non-immersive"; | |
| let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; | |
| let testFunction = | |
| (session, fakeDeviceController, t, sessionObjects) => new Promise((resolve, reject) => { | |
| let gl = sessionObjects.gl; | |
| let webglLayer = sessionObjects.glLayer; | |
| let xrFramebuffer = webglLayer.framebuffer; | |
| // Make sure we're starting with a clean error slate. | |
| assert_equals(gl.getError(), gl.NO_ERROR); | |
| if (session.mode == 'inline') { | |
| // Creating a layer with an inline session should return a framebuffer of | |
| // null, and as such most of these tests won't apply. | |
| assert_equals(xrFramebuffer, null); | |
| resolve(); | |
| return; | |
| } | |
| assert_not_equals(xrFramebuffer, null); | |
| // The XR framebuffer is not bound to the GL context by default. | |
| assert_not_equals(xrFramebuffer, gl.getParameter(gl.FRAMEBUFFER_BINDING)); | |
| assert_greater_than(webglLayer.framebufferWidth, 0); | |
| assert_greater_than(webglLayer.framebufferHeight, 0); | |
| gl.bindFramebuffer(gl.FRAMEBUFFER, xrFramebuffer); | |
| assert_equals(gl.getError(), gl.NO_ERROR); | |
| gl.deleteFramebuffer(xrFramebuffer); | |
| assert_equals(gl.getError(), gl.INVALID_OPERATION); | |
| // Make sure the framebuffer is still bound after failed attempt to delete. | |
| let boundFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING); | |
| assert_equals(xrFramebuffer, boundFramebuffer); | |
| assert_equals(gl.getError(), gl.NO_ERROR); | |
| // WebGL 2 does not throw an error and instead returns 0 when there are no | |
| // attachments | |
| if (gl.getParameter(gl.VERSION).includes("WebGL 1.0")) { | |
| // Ensure the framebuffer attachment properties cannot be inspected. | |
| let attachments = [ | |
| gl.COLOR_ATTACHMENT0, | |
| gl.DEPTH_ATTACHMENT, | |
| gl.STENCIL_ATTACHMENT, | |
| ]; | |
| let parameters = [ | |
| gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, | |
| gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, | |
| gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, | |
| gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, | |
| ]; | |
| for (let attachment of attachments) { | |
| for (let parameter of parameters) { | |
| let value = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, attachment, parameter); | |
| assert_equals(value, null); | |
| assert_equals(gl.getError(), gl.INVALID_OPERATION); | |
| } | |
| } | |
| } | |
| let width = 64; | |
| let height = 64; | |
| // Ensure the framebuffer texture 2D attachmentments cannot be changed. | |
| 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); | |
| assert_equals(gl.getError(), gl.INVALID_OPERATION); | |
| // Ensure the framebuffer renderbuffer attachmentments cannot be changed. | |
| let 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); | |
| assert_equals(gl.getError(), gl.INVALID_OPERATION); | |
| gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); | |
| gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer); | |
| assert_equals(gl.getError(), gl.INVALID_OPERATION); | |
| // Framebuffer status must be unsupported outside of a XR frame callback. | |
| assert_equals(gl.checkFramebufferStatus(gl.FRAMEBUFFER), gl.FRAMEBUFFER_UNSUPPORTED); | |
| session.requestAnimationFrame((time, xrFrame) => { | |
| // Framebuffer status must be complete inside of a XR frame callback. | |
| assert_equals(gl.checkFramebufferStatus(gl.FRAMEBUFFER), gl.FRAMEBUFFER_COMPLETE); | |
| // Finished. | |
| resolve(); | |
| }); | |
| }); | |
| xr_session_promise_test( | |
| immersiveTestName, testFunction, fakeDeviceInitParams, 'immersive-vr'); | |
| xr_session_promise_test( | |
| nonImmersiveTestName, testFunction, fakeDeviceInitParams, 'inline'); | |
| </script> |