summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/js/glsl-conformance-test.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/js/glsl-conformance-test.js424
1 files changed, 424 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/js/glsl-conformance-test.js b/dom/canvas/test/webgl-conf/checkout/js/glsl-conformance-test.js
new file mode 100644
index 0000000000..12a056ce21
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/js/glsl-conformance-test.js
@@ -0,0 +1,424 @@
+/*
+Copyright (c) 2019 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.
+*/
+GLSLConformanceTester = (function(){
+
+var wtu = WebGLTestUtils;
+var defaultVertexShader = [
+ "attribute vec4 vPosition;",
+ "void main()",
+ "{",
+ " gl_Position = vPosition;",
+ "}"
+].join('\n');
+
+var defaultFragmentShader = [
+ "precision mediump float;",
+ "void main()",
+ "{",
+ " gl_FragColor = vec4(1.0,0.0,0.0,1.0);",
+ "}"
+].join('\n');
+
+var defaultESSL3VertexShader = [
+ "#version 300 es",
+ "in vec4 vPosition;",
+ "void main()",
+ "{",
+ " gl_Position = vPosition;",
+ "}"
+].join('\n');
+
+var defaultESSL3FragmentShader = [
+ "#version 300 es",
+ "precision mediump float;",
+ "out vec4 my_FragColor;",
+ "void main()",
+ "{",
+ " my_FragColor = vec4(1.0,0.0,0.0,1.0);",
+ "}"
+].join('\n');
+
+function log(msg) {
+ bufferedLogToConsole(msg);
+}
+
+var vShaderDB = {};
+var fShaderDB = {};
+
+/**
+ * The info parameter should contain the following keys. Note that you may leave
+ * the parameters for one shader out, in which case the default shader will be
+ * used.
+ * vShaderSource: the source code for vertex shader
+ * vShaderId: id of an element containing vertex shader source code. Used if
+ * vShaderSource is not specified.
+ * vShaderSuccess: true if vertex shader compilation should
+ * succeed.
+ * fShaderSource: the source code for fragment shader
+ * fShaderId: id of an element containing fragment shader source code. Used if
+ * fShaderSource is not specified.
+ * fShaderSuccess: true if fragment shader compilation should
+ * succeed.
+ * linkSuccess: true if link should succeed
+ * passMsg: msg to describe success condition.
+ * render: if true render to unit quad. Green = success
+ * uniforms: an array of objects specifying uniforms to set prior to rendering.
+ * Each object should have the following keys:
+ * name: uniform variable name in the shader source. Uniform location will
+ * be queried based on its name.
+ * functionName: name of the function used to set the uniform. For example:
+ * 'uniform1i'
+ * value: value of the uniform to set.
+ */
+function runOneTest(gl, info) {
+ var passMsg = info.passMsg
+ debug("");
+ debug("test: " + passMsg);
+
+ var consoleDiv = document.getElementById("console");
+
+ var vIsDefault = false;
+ var fIsDefault = false;
+
+ if (info.vShaderSource === undefined) {
+ if (info.vShaderId) {
+ info.vShaderSource = document.getElementById(info.vShaderId).text;
+ } else {
+ vIsDefault = true;
+ }
+ }
+ if (info.fShaderSource === undefined) {
+ if (info.fShaderId) {
+ info.fShaderSource = document.getElementById(info.fShaderId).text;
+ } else {
+ fIsDefault = true;
+ }
+ }
+
+ var vLabel = (vIsDefault ? "default" : "test") + " vertex shader";
+ var fLabel = (fIsDefault ? "default" : "test") + " fragment shader";
+ if (vIsDefault) {
+ info.vShaderSource = defaultVertexShader;
+ info.vShaderSuccess = true;
+ }
+ if (fIsDefault) {
+ info.fShaderSource = defaultFragmentShader;
+ info.fShaderSuccess = true;
+ }
+
+ if (vIsDefault != fIsDefault) {
+ // The language version of the default shader is chosen
+ // according to the language version of the other shader.
+ // We rely on "#version 300 es" being in this usual format.
+ // It must be on the first line of the shader according to the spec.
+ if (fIsDefault) {
+ // If we're using the default fragment shader, we need to make sure that
+ // it's language version matches with the vertex shader.
+ if (info.vShaderSource.split('\n')[0] == '#version 300 es') {
+ info.fShaderSource = defaultESSL3FragmentShader;
+ }
+ } else {
+ // If we're using the default vertex shader, we need to make sure that
+ // it's language version matches with the fragment shader.
+ if (info.fShaderSource.split('\n')[0] == '#version 300 es') {
+ info.vShaderSource = defaultESSL3VertexShader;
+ }
+ }
+ }
+
+ var vSource = info.vShaderPrep ? info.vShaderPrep(info.vShaderSource) :
+ info.vShaderSource;
+
+ if (!quietMode()) {
+ wtu.addShaderSource(consoleDiv, vLabel, vSource);
+ }
+
+ // Reuse identical shaders so we test shared shader.
+ var vShader = vShaderDB[vSource];
+ if (!vShader) {
+ // loadShader, with opt_skipCompileStatus: true.
+ vShader = wtu.loadShader(gl, vSource, gl.VERTEX_SHADER, null, null, null, null, true);
+ let compiledVShader = vShader;
+ if (vShader && !gl.getShaderParameter(vShader, gl.COMPILE_STATUS)) {
+ compiledVShader = null;
+ }
+ if (info.vShaderTest) {
+ if (!info.vShaderTest(compiledVShader)) {
+ testFailed("[vertex shader test] " + passMsg);
+ return;
+ }
+ }
+ // As per GLSL 1.0.17 10.27 we can only check for success on
+ // compileShader, not failure.
+ if (!info.ignoreResults && info.vShaderSuccess && !compiledVShader) {
+ testFailed("[unexpected vertex shader compile status] (expected: " +
+ info.vShaderSuccess + ") " + passMsg);
+ if (!quietMode() && vShader) {
+ const info = gl.getShaderInfoLog(vShader);
+ wtu.addShaderSource(consoleDiv, vLabel + " info log", info);
+ }
+ }
+ // Save the shaders so we test shared shader.
+ if (compiledVShader) {
+ vShaderDB[vSource] = compiledVShader;
+ } else {
+ vShader = null;
+ }
+ }
+
+ var debugShaders = gl.getExtension('WEBGL_debug_shaders');
+ if (debugShaders && vShader && !quietMode()) {
+ wtu.addShaderSource(consoleDiv, vLabel + " translated for driver",
+ debugShaders.getTranslatedShaderSource(vShader));
+ }
+
+ var fSource = info.fShaderPrep ? info.fShaderPrep(info.fShaderSource) :
+ info.fShaderSource;
+
+ if (!quietMode()) {
+ wtu.addShaderSource(consoleDiv, fLabel, fSource);
+ }
+
+ // Reuse identical shaders so we test shared shader.
+ var fShader = fShaderDB[fSource];
+ if (!fShader) {
+ // loadShader, with opt_skipCompileStatus: true.
+ fShader = wtu.loadShader(gl, fSource, gl.FRAGMENT_SHADER, null, null, null, null, true);
+ let compiledFShader = fShader;
+ if (fShader && !gl.getShaderParameter(fShader, gl.COMPILE_STATUS)) {
+ compiledFShader = null;
+ }
+ if (info.fShaderTest) {
+ if (!info.fShaderTest(compiledFShader)) {
+ testFailed("[fragment shader test] " + passMsg);
+ return;
+ }
+ }
+ //debug(fShader == null ? "fail" : "succeed");
+ // As per GLSL 1.0.17 10.27 we can only check for success on
+ // compileShader, not failure.
+ if (!info.ignoreResults && info.fShaderSuccess && !compiledFShader) {
+ testFailed("[unexpected fragment shader compile status] (expected: " +
+ info.fShaderSuccess + ") " + passMsg);
+ if (!quietMode() && fShader) {
+ const info = gl.getShaderInfoLog(fShader);
+ wtu.addShaderSource(consoleDiv, fLabel + " info log", info);
+ }
+ return;
+ }
+
+ // Safe the shaders so we test shared shader.
+ if (compiledFShader) {
+ fShaderDB[fSource] = compiledFShader;
+ } else {
+ fShader = null;
+ }
+ }
+
+ if (debugShaders && fShader && !quietMode()) {
+ wtu.addShaderSource(consoleDiv, fLabel + " translated for driver",
+ debugShaders.getTranslatedShaderSource(fShader));
+ }
+
+ if (vShader && fShader) {
+ var program = gl.createProgram();
+ gl.attachShader(program, vShader);
+ gl.attachShader(program, fShader);
+
+ if (vSource.indexOf("vPosition") >= 0) {
+ gl.bindAttribLocation(program, 0, "vPosition");
+ }
+ if (vSource.indexOf("texCoord0") >= 0) {
+ gl.bindAttribLocation(program, 1, "texCoord0");
+ }
+ gl.linkProgram(program);
+ var linked = (gl.getProgramParameter(program, gl.LINK_STATUS) != 0);
+ if (!linked) {
+ var error = gl.getProgramInfoLog(program);
+ log("*** Error linking program '"+program+"':"+error);
+ }
+ if (!info.ignoreResults && linked != info.linkSuccess) {
+ testFailed("[unexpected link status] (expected: " +
+ info.linkSuccess + ") " + passMsg);
+ return;
+ }
+ } else {
+ if (!info.ignoreResults && info.linkSuccess) {
+ testFailed("[link failed] " + passMsg);
+ return;
+ }
+ }
+
+ if (parseInt(wtu.getUrlOptions().dumpShaders)) {
+ var vInfo = {
+ shader: vShader,
+ shaderSuccess: info.vShaderSuccess,
+ label: vLabel,
+ source: vSource
+ };
+ var fInfo = {
+ shader: fShader,
+ shaderSuccess: info.fShaderSuccess,
+ label: fLabel,
+ source: fSource
+ };
+ wtu.dumpShadersInfo(gl, window.location.pathname, passMsg, vInfo, fInfo);
+ }
+
+ if (!info.render) {
+ testPassed(passMsg);
+ return;
+ }
+
+ gl.useProgram(program);
+
+ if (info.uniforms !== undefined) {
+ for (var i = 0; i < info.uniforms.length; ++i) {
+ var uniform = info.uniforms[i];
+ var uniformLocation = gl.getUniformLocation(program, uniform.name);
+ if (uniformLocation !== null) {
+ if (uniform.functionName.includes("Matrix")) {
+ gl[uniform.functionName](uniformLocation, false, uniform.value);
+ } else {
+ gl[uniform.functionName](uniformLocation, uniform.value);
+ }
+ debug(uniform.name + ' set to ' + uniform.value);
+ } else {
+ debug('uniform ' + uniform.name + ' had null location and was not set');
+ }
+ }
+ }
+
+ if (info.uniformBlocks !== undefined) {
+ for (var i = 0; i < info.uniformBlocks.length; ++i) {
+ var uniformBlockIndex = gl.getUniformBlockIndex(program, info.uniformBlocks[i].name);
+ if (uniformBlockIndex !== null) {
+ gl.uniformBlockBinding(program, uniformBlockIndex, i);
+ debug(info.uniformBlocks[i].name + ' (index ' + uniformBlockIndex + ') bound to slot ' + i);
+
+ var uboValueBuffer = gl.createBuffer();
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, i, uboValueBuffer);
+ gl.bufferData(gl.UNIFORM_BUFFER, info.uniformBlocks[i].value, info.uniformBlocks[i].usage || gl.STATIC_DRAW);
+ } else {
+ debug('uniform block' + info.uniformBlocks[i].name + ' had null block index and was not set');
+ }
+ }
+ }
+
+ wtu.setupUnitQuad(gl);
+ wtu.clearAndDrawUnitQuad(gl);
+
+ var div = document.createElement("div");
+ div.className = "testimages";
+ wtu.insertImage(div, "result", wtu.makeImageFromCanvas(gl.canvas));
+ div.appendChild(document.createElement('br'));
+ consoleDiv.appendChild(div);
+
+ var tolerance = 0;
+ if (info.renderTolerance !== undefined) {
+ tolerance = info.renderTolerance;
+ }
+ if (info.renderColor !== undefined) {
+ wtu.checkCanvas(gl, info.renderColor, "should be expected color " + info.renderColor, tolerance);
+ } else {
+ wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green", tolerance);
+ }
+}
+
+function runTests(shaderInfos, opt_contextVersion) {
+ var wtu = WebGLTestUtils;
+ var canvas = document.createElement('canvas');
+ canvas.width = 32;
+ canvas.height = 32;
+ var gl = wtu.create3DContext(canvas, undefined, opt_contextVersion);
+ if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+ return;
+ }
+
+ for (var i = 0; i < shaderInfos.length; i++) {
+ runOneTest(gl, shaderInfos[i]);
+ }
+
+ finishTest();
+};
+
+function getSource(elem) {
+ var str = elem.text;
+ return str.replace(/^\s*/, '').replace(/\s*$/, '');
+}
+
+function getPassMessage(source) {
+ var lines = source.split('\n');
+ return lines[0].substring(3);
+}
+
+function getSuccess(msg) {
+ if (msg.indexOf("fail") >= 0) {
+ return false;
+ }
+ if (msg.indexOf("succeed") >= 0) {
+ return true;
+ }
+ testFailed("bad test description. Must have 'fail' or 'succeed'");
+}
+
+function setupTest() {
+ var info = {};
+
+ var vShaderElem = document.getElementById('vertexShader');
+ if (vShaderElem) {
+ info.vShaderSource = getSource(vShaderElem);
+ info.passMsg = getPassMessage(info.vShaderSource);
+ info.vShaderSuccess = getSuccess(info.passMsg);
+ }
+
+ var fShaderElem = document.getElementById('fragmentShader');
+ if (fShaderElem) {
+ info.fShaderSource = getSource(fShaderElem);
+ info.passMsg = getPassMessage(info.fShaderSource);
+ info.fShaderSuccess = getSuccess(info.passMsg);
+ }
+
+ // linkSuccess should be true if shader success value is undefined or true for both shaders.
+ info.linkSuccess = info.vShaderSuccess !== false && info.fShaderSuccess !== false;
+
+ if (info.passMsg === undefined) {
+ testFailed("no test shader found.");
+ finishTest();
+ return;
+ }
+
+ return info;
+}
+
+function runTest() {
+ var info = setupTest();
+ description(info.passMsg);
+ runTests([info]);
+}
+
+function runRenderTests(tests, opt_contextVersion) {
+ for (var ii = 0; ii < tests.length; ++ii) {
+ tests[ii].render = true
+ }
+ runTests(tests, opt_contextVersion);
+}
+
+function runRenderTest() {
+ var info = setupTest();
+ description(info.passMsg);
+ runRenderTests([info]);
+}
+
+return {
+ runTest: runTest,
+ runTests: runTests,
+ runRenderTest: runRenderTest,
+ runRenderTests: runRenderTests
+};
+}());