summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html
parentInitial commit. (diff)
downloadfirefox-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.html223
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>