diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html')
-rw-r--r-- | testing/web-platform/tests/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html b/testing/web-platform/tests/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html new file mode 100644 index 0000000000..17f991f180 --- /dev/null +++ b/testing/web-platform/tests/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html @@ -0,0 +1,223 @@ +<!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" + + " works with stencil for immersive"; +let nonImmersiveTestName = "Ensure that the framebuffer given by the WebGL layer" + + " works with stencil for non-immersive"; + +let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; + +function createShader(gl, type, source) { + var shader = gl.createShader(type); + gl.shaderSource(shader, source); + gl.compileShader(shader); + var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS); + if (success) { + return shader; + } + + gl.deleteShader(shader); +} + +function createProgram(gl, vertexShader, fragmentShader) { + var program = gl.createProgram(); + gl.attachShader(program, vertexShader); + gl.attachShader(program, fragmentShader); + gl.linkProgram(program); + var success = gl.getProgramParameter(program, gl.LINK_STATUS); + if (success) { + return program; + } + + gl.deleteProgram(program); +} + +let testFunction = + (session, fakeDeviceController, t, sessionObjects) => new Promise((resolve, reject) => { + const gl = sessionObjects.gl; + const webglLayer = sessionObjects.glLayer; + const xrFramebuffer = webglLayer.framebuffer; + const webglCanvas = sessionObjects.gl.canvas; + + session.requestAnimationFrame((time, xrFrame) => { + t.step(() => { + // Make sure we're starting with a clean error slate. + gl.getError(); + assert_equals(gl.getError(), gl.NO_ERROR, "Should not initially have any errors"); + + 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, 'inline, fbo = null'); + // We need to set canvas size here for inline session testing, since + // xrFramebuffer is null. + webglCanvas.width = webglCanvas.height = 300; + gl.bindFramebuffer(gl.FRAMEBUFFER, xrFramebuffer); + assert_equals(gl.getError(), gl.NO_ERROR, "Binding default framebuffer for inline session"); + } else { + assert_not_equals(xrFramebuffer, null, 'immersive, fbo != null'); + gl.bindFramebuffer(gl.FRAMEBUFFER, xrFramebuffer); + assert_equals(gl.getError(), gl.NO_ERROR, "Binding WebGLLayer framebuffer"); + } + + // Framebuffer status must be complete inside of a XR frame callback. + assert_equals(gl.checkFramebufferStatus(gl.FRAMEBUFFER), gl.FRAMEBUFFER_COMPLETE, "FBO complete"); + }); + gl.clearColor(1, 1, 1, 1); + + const vs = ` + attribute vec4 position; + uniform mat4 matrix; + void main() { + gl_Position = matrix * position; + } + `; + + const fs = ` + precision mediump float; + uniform vec4 color; + void main() { + gl_FragColor = color; + } + `; + const vertexShader = createShader(gl, gl.VERTEX_SHADER, vs); + const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fs); + const program = createProgram(gl, vertexShader, fragmentShader); + + const posLoc = gl.getAttribLocation(program, 'position'); + const matLoc = gl.getUniformLocation(program, 'matrix'); + const colorLoc = gl.getUniformLocation(program, 'color'); + + const buf = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, buf); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ + 0, -1, + 1, 1, + -1, 1, + ]), gl.STATIC_DRAW); + + gl.enableVertexAttribArray(posLoc); + gl.vertexAttribPointer( + posLoc, // attribute location + 2, // 2 value per vertex + gl.FLOAT, // 32bit floating point values + false, // don't normalize + 0, // stride (0 = base on type and size) + 0, // offset into buffer + ); + + let xrViewport; + if (session.mode == 'inline') { + xrViewport = { x: 0, y: 0, width: webglCanvas.width, height: webglCanvas.height }; + } else { + xrViewport = { x: 0, y: 0, width: webglLayer.framebufferWidth, height: webglLayer.framebufferHeight }; + } + + gl.viewport(xrViewport.x, xrViewport.y, xrViewport.width, xrViewport.height); + gl.scissor(xrViewport.x, xrViewport.y, xrViewport.width, xrViewport.height); + + // clear the stencil to 0 (the default) + gl.stencilMask(0xFF); + gl.clearStencil(0x0); + gl.disable( gl.SCISSOR_TEST ); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); + + gl.useProgram(program); + let m4 = [1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]; + + // turn on the stencil + gl.enable(gl.STENCIL_TEST); + + // Drawing into a stencil, always passes, ref val 1, mask 0xFF + gl.stencilFunc( + gl.ALWAYS, + 1, + 0xFF, + ); + // Set it to replace with the ref val (which is 1) + gl.stencilOp( + gl.KEEP, // stencil test fails + gl.KEEP, // depth test fails + gl.REPLACE, // both tests pass + ); + + m4[0] = 0.2; m4[5] = 0.2; // scale x and y + // draw a white triangle + gl.uniform4fv(colorLoc, [1, 1, 1, 1]); // white + gl.uniformMatrix4fv(matLoc, false, m4); + gl.colorMask(false, false, false, false); + gl.drawArrays(gl.TRIANGLES, 0, 3); + + gl.colorMask(true, true, true, true); + + // Stencil must be 0 + gl.stencilFunc( + gl.EQUAL, + 0, + 0xFF, + ); + // keep stencil unmodified during the draw pass + gl.stencilOp( + gl.KEEP, // stencil test fails + gl.KEEP, // depth test fails + gl.KEEP, // both tests pass + ); + + m4[0] = 0.9; m4[5] = -0.9; // scale x and y + // draw a large green triangle + gl.uniform4fv(colorLoc, [0, 1, 0, 1]); // green + gl.uniformMatrix4fv(matLoc, false, m4); + gl.drawArrays(gl.TRIANGLES, 0, 3); + + gl.flush(); + gl.finish(); + let pixels = new Uint8Array(4); + + // check that the main color is used correctly (green) + pixels[0] = pixels[1] = pixels[2] = pixels[3] = 30; + gl.readPixels(xrViewport.x + xrViewport.width / 2, xrViewport.y + xrViewport.height/4, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + if (pixels[0] == 0x0 && pixels[1] == 0xFF && pixels[2] == 0x0) { // green? + // PASSED. + } else if (pixels[0] == 0xFF && pixels[1] == 0xFF && pixels[2] == 0xFF) { // white? + reject("Failed, white detected, must be green"); + } else { + reject("Failed, readPixels (1) didn't work, gl error = " + gl.getError() + ", pixel = " +pixels[0] + " " +pixels[1] + " " +pixels[2]); + } + + // check if stencil worked, i.e. white pixels in the center + pixels[0] = pixels[1] = pixels[2] = pixels[3] = 20; + gl.readPixels(xrViewport.x + xrViewport.width / 2, xrViewport.y + xrViewport.height/2, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + if (pixels[0] == 0xFF && pixels[1] == 0xFF && pixels[2] == 0xFF) { // white? + // PASSED. + } else if (pixels[0] == 0x0 && pixels[1] == 0xFF && pixels[2] == 0x0) { // green? + reject("Failed, green detected, must be white"); + } else { + reject("Failed, readPixels (2) didn't work, gl error = " + gl.getError() + ", pixel = " +pixels[0] + " " +pixels[1] + " " +pixels[2]); + } + + // Finished. + resolve(); + }); +}); + +const gl_props = { antialias: false, alpha: false, stencil: true, depth: true }; + +// mac has issues with readPixels from the default fbo. +// skipping this test for Mac. +if (navigator.platform.indexOf("Mac") == -1) { + xr_session_promise_test( + nonImmersiveTestName, testFunction, fakeDeviceInitParams, 'inline', {}, {}, gl_props, gl_props); +} + +xr_session_promise_test( + immersiveTestName, testFunction, fakeDeviceInitParams, 'immersive-vr', {}, {}, gl_props, gl_props); + +</script> |