summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-clip-cull-distance.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-clip-cull-distance.html')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-clip-cull-distance.html475
1 files changed, 475 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-clip-cull-distance.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-clip-cull-distance.html
new file mode 100644
index 0000000000..cb2253c326
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-clip-cull-distance.html
@@ -0,0 +1,475 @@
+<!--
+Copyright (c) 2022 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL WEBGL_clip_cull_distance Conformance Tests</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>
+<canvas width="32" height="32" id="c"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description("This test verifies the functionality of the WEBGL_clip_cull_distance extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("c", null, 2);
+var ext;
+const w = gl.drawingBufferWidth;
+const h = gl.drawingBufferHeight;
+
+function runTestNoExtension() {
+ debug("");
+ debug("Check parameters and capabilities without the extension");
+
+ shouldBeNull("gl.getParameter(0x0D32 /* MAX_CLIP_DISTANCES_WEBGL */)");
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension");
+ shouldBeNull("gl.getParameter(0x82F9 /* MAX_CULL_DISTANCES_WEBGL */)");
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension");
+ shouldBeNull("gl.getParameter(0x82FA /* MAX_COMBINED_CLIP_AND_CULL_DISTANCES_WEBGL */)");
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension");
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ const assertState = (i) => {
+ shouldBeFalse(`gl.isEnabled(${0x3000 + i} /* CLIP_DISTANCE${i}_WEBGL */)`);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension");
+
+ shouldBeNull(`gl.getParameter(${0x3000 + i} /* CLIP_DISTANCE${i}_WEBGL */)`);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension");
+ };
+
+ for (let i = 0; i < 8; i++) {
+ assertState(i);
+
+ gl.enable(0x3000 + i /* CLIP_DISTANCEi_WEBGL */);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "capability unknown without enabling the extension");
+
+ assertState(i);
+
+ gl.disable(0x3000 + i /* CLIP_DISTANCEi_WEBGL */);
+ wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "capability unknown without enabling the extension");
+
+ assertState(i);
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ debug("");
+}
+
+function checkEnums() {
+ debug("");
+ debug("Check enums");
+ shouldBe("ext.MAX_CLIP_DISTANCES_WEBGL", "0x0D32");
+ shouldBe("ext.MAX_CULL_DISTANCES_WEBGL", "0x82F9");
+ shouldBe("ext.MAX_COMBINED_CLIP_AND_CULL_DISTANCES_WEBGL", "0x82FA");
+ shouldBe("ext.CLIP_DISTANCE0_WEBGL", "0x3000");
+ shouldBe("ext.CLIP_DISTANCE1_WEBGL", "0x3001");
+ shouldBe("ext.CLIP_DISTANCE2_WEBGL", "0x3002");
+ shouldBe("ext.CLIP_DISTANCE3_WEBGL", "0x3003");
+ shouldBe("ext.CLIP_DISTANCE4_WEBGL", "0x3004");
+ shouldBe("ext.CLIP_DISTANCE5_WEBGL", "0x3005");
+ shouldBe("ext.CLIP_DISTANCE6_WEBGL", "0x3006");
+ shouldBe("ext.CLIP_DISTANCE7_WEBGL", "0x3007");
+}
+
+function checkQueries() {
+ debug("");
+ debug("Check parameters");
+ shouldBeGreaterThanOrEqual('gl.getParameter(ext.MAX_CLIP_DISTANCES_WEBGL)', '8');
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ const maxCullDistances = gl.getParameter(ext.MAX_CULL_DISTANCES_WEBGL);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ if (maxCullDistances == 0) {
+ testPassed("No cull distance support");
+ shouldBe("gl.getParameter(ext.MAX_COMBINED_CLIP_AND_CULL_DISTANCES_WEBGL)", "0");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ } else if (maxCullDistances >= 8) {
+ testPassed("Optional cull distance support");
+ shouldBeGreaterThanOrEqual("gl.getParameter(ext.MAX_COMBINED_CLIP_AND_CULL_DISTANCES_WEBGL)", "8");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ } else {
+ testFailed("Invalid number of supported cull distances");
+ }
+
+ debug("");
+ debug("Check clip distance capabilities");
+
+ const assertState = (i, s) => {
+ shouldBe(`gl.isEnabled(${0x3000 + i} /* CLIP_DISTANCE${i}_WEBGL */)`, s ? "true" : "false");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ shouldBe(`gl.getParameter(${0x3000 + i} /* CLIP_DISTANCE${i}_WEBGL */)`, s ? "true" : "false");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+ };
+
+ for (let i = 0; i < 8; i++) {
+ assertState(i, false);
+
+ gl.enable(ext.CLIP_DISTANCE0_WEBGL + i);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ assertState(i, true);
+
+ gl.disable(ext.CLIP_DISTANCE0_WEBGL + i);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ assertState(i, false);
+ }
+}
+
+function checkClipDistance() {
+ debug("");
+ debug("Check clip distance operation");
+
+ const vs = `#version 300 es
+#extension GL_ANGLE_clip_cull_distance : require
+
+uniform vec4 u_plane;
+in vec2 a_position;
+void main()
+{
+ gl_Position = vec4(a_position, 0.0, 1.0);
+ gl_ClipDistance[0] = dot(gl_Position, u_plane);
+}`;
+
+ const program = wtu.setupProgram(gl, [vs, wtu.simpleColorFragmentShaderESSL300]);
+ gl.useProgram(program);
+ gl.uniform4fv(gl.getUniformLocation(program, 'u_color'), [1.0, 0.0, 0.0, 1.0]);
+
+ gl.enable(ext.CLIP_DISTANCE0_WEBGL);
+
+ // Clear to blue
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ wtu.setupUnitQuad(gl);
+
+ // Draw full screen quad with color red
+ gl.uniform4f(gl.getUniformLocation(program, "u_plane"), 1, 0, 0, 0.5);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ // All pixels on the left of the plane x = -0.5 must be blue
+ let x = 0;
+ let y = 0;
+ let width = w / 4 - 1;
+ let height = h;
+ wtu.checkCanvasRect(gl, x, y, width, height,
+ [0, 0, 255, 255], "should be blue");
+
+ // All pixels on the right of the plane x = -0.5 must be red
+ x = w / 4 + 2;
+ y = 0;
+ width = w - x;
+ height = h;
+ wtu.checkCanvasRect(gl, x, y, width, height,
+ [255, 0, 0, 255], "should be red");
+
+ // Clear to green
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Draw full screen quad with color red
+ gl.uniform4f(gl.getUniformLocation(program, "u_plane"), -1, 0, 0, -0.5);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ // All pixels on the left of the plane x = -0.5 must be red
+ x = 0;
+ y = 0;
+ width = w / 4 - 1;
+ height = h;
+ wtu.checkCanvasRect(gl, x, y, width, height,
+ [255, 0, 0, 255], "should be red");
+
+ // All pixels on the right of the plane x = -0.5 must be green
+ x = w / 4 + 2;
+ y = 0;
+ width = w - x;
+ height = h;
+ wtu.checkCanvasRect(gl, x, y, width, height,
+ [0, 255, 0, 255], "should be green");
+
+ // Disable CLIP_DISTANCE0 and draw again
+ gl.disable(ext.CLIP_DISTANCE0_WEBGL);
+ wtu.drawUnitQuad(gl);
+
+ // All pixels must be red
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+}
+
+function checkClipDistanceInterpolation() {
+ debug("");
+ debug("Check clip distance interpolation");
+
+ const vs = `#version 300 es
+#extension GL_ANGLE_clip_cull_distance : require
+in vec2 a_position;
+void main()
+{
+ gl_Position = vec4(a_position, 0.0, 1.0);
+ gl_ClipDistance[0] = dot(gl_Position, vec4( 1, 0, 0, 0.5));
+ gl_ClipDistance[1] = dot(gl_Position, vec4(-1, 0, 0, 0.5));
+ gl_ClipDistance[2] = dot(gl_Position, vec4( 0, 1, 0, 0.5));
+ gl_ClipDistance[3] = dot(gl_Position, vec4( 0, -1, 0, 0.5));
+ gl_ClipDistance[4] = gl_ClipDistance[0];
+ gl_ClipDistance[5] = gl_ClipDistance[1];
+ gl_ClipDistance[6] = gl_ClipDistance[2];
+ gl_ClipDistance[7] = gl_ClipDistance[3];
+}`;
+
+ const fs = `#version 300 es
+#extension GL_ANGLE_clip_cull_distance : require
+precision highp float;
+out vec4 my_FragColor;
+void main()
+{
+ float r = gl_ClipDistance[0] + gl_ClipDistance[1];
+ float g = gl_ClipDistance[2] + gl_ClipDistance[3];
+ float b = gl_ClipDistance[4] + gl_ClipDistance[5];
+ float a = gl_ClipDistance[6] + gl_ClipDistance[7];
+ my_FragColor = vec4(r, g, b, a) * 0.5;
+}`;
+
+ const program = wtu.setupProgram(gl, [vs, fs]);
+ gl.useProgram(program);
+
+ gl.enable(ext.CLIP_DISTANCE0_WEBGL);
+ gl.enable(ext.CLIP_DISTANCE1_WEBGL);
+ gl.enable(ext.CLIP_DISTANCE2_WEBGL);
+ gl.enable(ext.CLIP_DISTANCE3_WEBGL);
+ gl.enable(ext.CLIP_DISTANCE4_WEBGL);
+ gl.enable(ext.CLIP_DISTANCE5_WEBGL);
+ gl.enable(ext.CLIP_DISTANCE6_WEBGL);
+ gl.enable(ext.CLIP_DISTANCE7_WEBGL);
+
+ wtu.setupUnitQuad(gl);
+
+ // Clear to blue
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Draw full screen quad with color gray
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ const data = new Uint8Array(w * h * 4);
+ gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, data);
+ let passed = true;
+ for (let x = 0; x < w; x++) {
+ for (let y = 0; y < h; y++) {
+ const currentPosition = (y * h + x) * 4;
+ const inside = (x >= w / 4 && x < w * 3 / 4 && y >= h / 4 && y < h * 3 / 4);
+ const expected = inside ? [127, 127, 127, 127] : [0, 0, 255, 255];
+ const actual = data.slice(currentPosition, currentPosition + 4);
+ if (Math.abs(actual[0] - expected[0]) > 1 ||
+ Math.abs(actual[1] - expected[1]) > 1 ||
+ Math.abs(actual[2] - expected[2]) > 1 ||
+ Math.abs(actual[3] - expected[3]) > 1) {
+ passed = false;
+ }
+ }
+ }
+ if (passed) {
+ testPassed("Correct clip distance interpolation");
+ } else {
+ testFailed("Incorrect clip distance interpolation");
+ }
+}
+
+function checkCullDistance() {
+ debug("");
+ debug("Check cull distance operation");
+
+ if (gl.getParameter(ext.MAX_CULL_DISTANCES_WEBGL) == 0) {
+ testPassed("No cull distance support");
+ return;
+ }
+
+ const vs = `#version 300 es
+#extension GL_ANGLE_clip_cull_distance : require
+
+uniform vec4 u_plane;
+in vec2 a_position;
+void main()
+{
+ gl_Position = vec4(a_position, 0.0, 1.0);
+ gl_CullDistance[0] = dot(gl_Position, u_plane);
+}`;
+
+ const program = wtu.setupProgram(gl, [vs, wtu.simpleColorFragmentShaderESSL300]);
+ gl.useProgram(program);
+ gl.uniform4fv(gl.getUniformLocation(program, 'u_color'), [1.0, 0.0, 0.0, 1.0]);
+
+ // Clear to blue
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ wtu.setupUnitQuad(gl);
+
+ // Draw full screen quad with color red
+ gl.uniform4f(gl.getUniformLocation(program, "u_plane"), 1, 0, 0, 0.5);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ // All pixels must be red
+ wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
+
+ // Clear to green
+ gl.clearColor(0, 1, 0, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ // Draw full screen quad with color red
+ gl.uniform4f(gl.getUniformLocation(program, "u_plane"), -1, 1, 0, -0.5);
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ // All pixels above the y > x line must be red
+ const data = new Uint8Array(w * h * 4);
+ gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, data);
+ let passed = true;
+ for (let x = 0; x < w; ++x) {
+ for (let y = 0; y < h; ++y) {
+ if (y <= x + 2 && y >= x - 2) continue; // skip the edge
+ const currentPosition = (y * h + x) * 4;
+ const actual = data.slice(currentPosition, currentPosition + 2);
+ const expected = (y > x) ? [255, 0] : [0, 255];
+ if (actual[0] != expected[0] || actual[1] != expected[1]) {
+ passed = false;
+ }
+ }
+ }
+ if (passed) {
+ testPassed("Correct cull distance operation");
+ } else {
+ testFailed("Incorrect cull distance operation");
+ }
+}
+
+function checkCullDistanceInterpolation() {
+ debug("");
+ debug("Check cull distance interpolation");
+
+ if (gl.getParameter(ext.MAX_CULL_DISTANCES_WEBGL) == 0) {
+ testPassed("No cull distance support");
+ return;
+ }
+
+ const vs = `#version 300 es
+#extension GL_ANGLE_clip_cull_distance : require
+in vec2 a_position;
+void main()
+{
+ gl_Position = vec4(a_position, 0.0, 1.0);
+ gl_CullDistance[0] = dot(gl_Position, vec4( 1, 0, 0, 1));
+ gl_CullDistance[1] = dot(gl_Position, vec4(-1, 0, 0, 1));
+ gl_CullDistance[2] = dot(gl_Position, vec4( 0, 1, 0, 1));
+ gl_CullDistance[3] = dot(gl_Position, vec4( 0, -1, 0, 1));
+ gl_CullDistance[4] = gl_CullDistance[0];
+ gl_CullDistance[5] = gl_CullDistance[1];
+ gl_CullDistance[6] = gl_CullDistance[2];
+ gl_CullDistance[7] = gl_CullDistance[3];
+}`;
+
+ const fs = `#version 300 es
+#extension GL_ANGLE_clip_cull_distance : require
+precision highp float;
+out vec4 my_FragColor;
+void main()
+{
+ float r = gl_CullDistance[0] + gl_CullDistance[1];
+ float g = gl_CullDistance[2] + gl_CullDistance[3];
+ float b = gl_CullDistance[4] + gl_CullDistance[5];
+ float a = gl_CullDistance[6] + gl_CullDistance[7];
+ my_FragColor = vec4(r, g, b, a) * 0.25;
+}`;
+
+ const program = wtu.setupProgram(gl, [vs, fs]);
+ gl.useProgram(program);
+
+ // Clear to blue
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ wtu.setupQuad(gl, {scale: 0.5});
+
+ // Draw a small quad with color gray
+ wtu.drawUnitQuad(gl);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
+
+ const data = new Uint8Array(w * h * 4);
+ gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, data);
+ let passed = true;
+ for (let x = 0; x < w; x++) {
+ for (let y = 0; y < h; y++) {
+ const currentPosition = (y * h + x) * 4;
+ const inside = (x >= w / 4 && x < w * 3 / 4 && y >= h / 4 && y < h * 3 / 4);
+ const expected = inside ? [127, 127, 127, 127] : [0, 0, 255, 255];
+ const actual = data.slice(currentPosition, currentPosition + 4);
+ if (Math.abs(actual[0] - expected[0]) > 1 ||
+ Math.abs(actual[1] - expected[1]) > 1 ||
+ Math.abs(actual[2] - expected[2]) > 1 ||
+ Math.abs(actual[3] - expected[3]) > 1) {
+ passed = false;
+ }
+ }
+ }
+ if (passed) {
+ testPassed("Correct cull distance interpolation");
+ } else {
+ testFailed("Incorrect cull distance interpolation");
+ }
+}
+
+function runTestExtension() {
+ checkEnums();
+ checkQueries();
+
+ checkClipDistance();
+ checkClipDistanceInterpolation();
+
+ checkCullDistance();
+ checkCullDistanceInterpolation();
+}
+
+function runTest() {
+ if (!gl) {
+ testFailed("context does not exist");
+ } else {
+ testPassed("context exists");
+
+ runTestNoExtension();
+
+ ext = gl.getExtension("WEBGL_clip_cull_distance");
+
+ wtu.runExtensionSupportedTest(gl, "WEBGL_clip_cull_distance", ext !== null);
+
+ if (ext !== null) {
+ runTestExtension();
+ } else {
+ testPassed("No WEBGL_clip_cull_distance support -- this is legal");
+ }
+ }
+}
+
+runTest();
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>