summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/conformance/ogles/ogles-utils.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance/ogles/ogles-utils.js')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/ogles/ogles-utils.js791
1 files changed, 791 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/ogles/ogles-utils.js b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/ogles-utils.js
new file mode 100644
index 0000000000..b2a1500496
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/ogles/ogles-utils.js
@@ -0,0 +1,791 @@
+/*
+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.
+*/
+OpenGLESTestRunner = (function(){
+var wtu = WebGLTestUtils;
+var gl;
+
+var HALF_GRID_MAX_SIZE = 32;
+var KNOWN_ATTRIBS = [
+ "gtf_Vertex",
+ "gtf_Color"
+];
+
+var GTFPIXELTOLERANCE = 24;
+var GTFACCEPTABLEFAILURECONT = 10;
+var GTFAMDPIXELTOLERANCE = 12;
+var GTFSCORETOLERANCE = 0.65;
+var GTFNCCTOLARANCEZERO = 0.25;
+var GTFKERNALSIZE = 5;
+
+function log(msg) {
+ // debug(msg);
+}
+
+function compareImages(refData, tstData, width, height, diff) {
+ function isPixelSame(offset) {
+ // First do simple check
+ if (Math.abs(refData[offset + 0] - tstData[offset + 0]) <= GTFPIXELTOLERANCE &&
+ Math.abs(refData[offset + 1] - tstData[offset + 1]) <= GTFPIXELTOLERANCE &&
+ Math.abs(refData[offset + 2] - tstData[offset + 2]) <= GTFPIXELTOLERANCE) {
+ return true;
+ }
+
+ // TODO: Implement crazy check that's used in OpenGL ES 2.0 conformance tests.
+ // NOTE: on Desktop things seem to be working. Maybe the more complex check
+ // is needed for embedded systems?
+ return false;
+ }
+
+ var same = true;
+ for (var yy = 0; yy < height; ++yy) {
+ for (var xx = 0; xx < width; ++xx) {
+ var offset = (yy * width + xx) * 4;
+ var diffOffset = ((height - yy - 1) * width + xx) * 4;
+ diff[diffOffset + 0] = 0;
+ diff[diffOffset + 1] = 0;
+ diff[diffOffset + 2] = 0;
+ diff[diffOffset + 3] = 255;
+ if (!isPixelSame(offset)) {
+ diff[diffOffset] = 255;
+ if (same) {
+ same = false;
+ testFailed("pixel @ (" + xx + ", " + yy + " was [" +
+ tstData[offset + 0] + "," +
+ tstData[offset + 1] + "," +
+ tstData[offset + 2] + "," +
+ tstData[offset + 3] + "] expected [" +
+ refData[offset + 0] + "," +
+ refData[offset + 1] + "," +
+ refData[offset + 2] + "," +
+ refData[offset + 3] + "]")
+ }
+ }
+ }
+ }
+ return same;
+}
+
+function persp(fovy, aspect, n, f) {
+ var dz = f - n;
+ var rad = fovy / 2.0 * 3.14159265 / 180;
+
+ var s = Math.sin(rad);
+ if (dz == 0 || s == 0 || aspect == 0)
+ return;
+
+ var cot = Math.cos(rad) / s;
+
+ return [
+ cot / aspect,
+ 0.0,
+ 0.0,
+ 0.0,
+
+ 0.0,
+ cot,
+ 0.0,
+ 0.0,
+
+ 0.0,
+ 0.0,
+ -(f + n) / dz,
+ -1.0,
+
+ 0.0,
+ 0.0,
+ -2.0 * f * n / dz,
+ 0.0
+ ];
+}
+
+function setAttribs(attribs, buffers) {
+ for (var name in attribs) {
+ var buffer = buffers[name];
+ if (!buffer) {
+ testFailed("no buffer for attrib:" + name);
+ continue;
+ }
+ var loc = attribs[name];
+ log("setup attrib: " + loc + " as " + name);
+ var buf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(buffer.data), gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(loc);
+ gl.vertexAttribPointer(loc, buffer.numComponents, gl.FLOAT, false, 0, 0);
+ }
+}
+
+function drawSquare(attribs) {
+ var buffers = {
+ "gtf_Vertex": {
+ data: [
+ 1.0, -1.0, -2.0,
+ 1.0, 1.0, -2.0,
+ -1.0, -1.0, -2.0,
+ -1.0, 1.0, -2.0
+ ],
+ numComponents: 3
+ },
+ "gtf_Color": {
+ data: [
+ 0.5, 1.0, 0.0,
+ 0.0, 1.0, 1.0,
+ 1.0, 0.0, 0.0,
+ 0.5, 0.0, 1.0
+ ],
+ numComponents: 3,
+ },
+ "gtf_SecondaryColor": {
+ data: [
+ 0.5, 0.0, 1.0,
+ 1.0, 0.0, 0.0,
+ 0.0, 1.0, 1.0,
+ 0.5, 1.0, 0.0
+ ],
+ numComponents: 3,
+ },
+ "gtf_Normal": {
+ data: [
+ 0.5, 0.0, 1.0,
+ 1.0, 0.0, 0.0,
+ 0.0, 1.0, 1.0,
+ 0.5, 1.0, 0.0
+ ],
+ numComponents: 3,
+ },
+ "gtf_MultiTexCoord0": {
+ data: [
+ 1.0, 0.0,
+ 1.0, 1.0,
+ 0.0, 0.0,
+ 0.0, 1.0
+ ],
+ numComponents: 2,
+ },
+ "gtf_FogCoord": {
+ data: [
+ 0.0,
+ 1.0,
+ 0.0,
+ 1.0
+ ],
+ numComponents: 1,
+ }
+ };
+ setAttribs(attribs, buffers);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+}
+
+function drawFrontBackSquare(attribs) {
+ var front = {
+ "gtf_Vertex": {
+ data: [
+ 1.0, -1.0, -2.0,
+ 1.0, 0.0, -2.0,
+ -1.0, -1.0, -2.0,
+ -1.0, 0.0, -2.0
+ ],
+ numComponents: 3
+ },
+ "gtf_Color": {
+ data: [
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0
+ ],
+ numComponents: 3,
+ },
+ "gtf_MultiTexCoord0": {
+ data: [
+ 1.0, 0.0,
+ 1.0, 0.5,
+ 0.0, 0.0,
+ 0.0, 0.5
+ ],
+ numComponents: 2,
+ }
+ };
+ setAttribs(attribs, front);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
+ var back = {
+ "gtf_Vertex": {
+ data: [
+ 1.0, 1.0, -2.0,
+ 1.0, 0.0, -2.0,
+ -1.0, 1.0, -2.0,
+ -1.0, 0.0, -2.0
+ ],
+ numComponents: 3
+ },
+ "gtf_Color": {
+ data: [
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0,
+ 1.0, 0.0, 0.0
+ ],
+ numComponents: 3,
+ },
+ "gtf_MultiTexCoord0": {
+ data: [
+ 1.0, 0.1,
+ 1.0, 0.5,
+ 0.0, 0.1,
+ 0.0, 0.5
+ ],
+ numComponents: 2,
+ }
+ };
+ setAttribs(attribs, back);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+}
+
+function drawGrid(attribs, width, height) {
+ var n = Math.min(Math.floor(Math.max(width, height) / 4), HALF_GRID_MAX_SIZE);
+
+ var numVertices = (n + n) * (n + n) * 6;
+
+ var gridVertices = [];
+ var gridColors = [];
+ var gridSecColors = [];
+ var gridNormals = [];
+ var gridFogCoords = [];
+ var gridTexCoords0 = [];
+
+ var currentVertex = 0;
+ var currentColor = 0;
+ var currentSecColor = 0;
+ var currentTexCoord0 = 0;
+ var currentNormal = 0;
+ var currentFogCoord = 0;
+
+ var z = -2.0;
+ for(var i = -n; i < n; ++i)
+ {
+ var x1 = i / n;
+ var x2 = (i + 1) / n;
+ for(var j = -n; j < n; ++j)
+ {
+ var y1 = j / n;
+ var y2 = (j + 1) / n;
+
+ // VERTEX 0
+ gridVertices[currentVertex++] = x1;
+ gridVertices[currentVertex++] = y1;
+ gridVertices[currentVertex++] = z;
+ gridColors[currentColor++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
+ gridColors[currentColor++] = (x1 + 1.0) / 2.0;
+ gridColors[currentColor++] = (y1 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
+ gridSecColors[currentSecColor++] = (x2 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = (y2 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (x1 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (y1 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
+ gridNormals[currentNormal++] = (x2 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = (y2 + 1.0) / 2.0;
+ gridFogCoords[currentFogCoord++] = (y1 + 1.0) / 2.0;
+
+ // VERTEX 1
+ gridVertices[currentVertex++] = x2;
+ gridVertices[currentVertex++] = y1;
+ gridVertices[currentVertex++] = z;
+ gridColors[currentColor++] = 1.0 - (x2 + y1 + 2.0) / 4.0;
+ gridColors[currentColor++] = (x2 + 1.0) / 2.0;
+ gridColors[currentColor++] = (y1 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = 1.0 - (x1 + y2 + 2.0) / 4.0;
+ gridSecColors[currentSecColor++] = (x1 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = (y2 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (x2 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (y1 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = 1.0 - (x1 + y2 + 2.0) / 4.0;
+ gridNormals[currentNormal++] = (x1 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = (y2 + 1.0) / 2.0;
+ gridFogCoords[currentFogCoord++] = (y1 + 1.0) / 2.0;
+
+ // VERTEX 2
+ gridVertices[currentVertex++] = x2;
+ gridVertices[currentVertex++] = y2;
+ gridVertices[currentVertex++] = z;
+ gridColors[currentColor++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
+ gridColors[currentColor++] = (x2 + 1.0) / 2.0;
+ gridColors[currentColor++] = (y2 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
+ gridSecColors[currentSecColor++] = (x1 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = (y1 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (x2 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (y2 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
+ gridNormals[currentNormal++] = (x1 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = (y1 + 1.0) / 2.0;
+ gridFogCoords[currentFogCoord++] = (y2 + 1.0) / 2.0;
+
+ // VERTEX 2
+ gridVertices[currentVertex++] = x2;
+ gridVertices[currentVertex++] = y2;
+ gridVertices[currentVertex++] = z;
+ gridColors[currentColor++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
+ gridColors[currentColor++] = (x2 + 1.0) / 2.0;
+ gridColors[currentColor++] = (y2 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
+ gridSecColors[currentSecColor++] = (x1 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = (y1 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (x2 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (y2 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
+ gridNormals[currentNormal++] = (x1 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = (y1 + 1.0) / 2.0;
+ gridFogCoords[currentFogCoord++] = (y2 + 1.0) / 2.0;
+
+ // VERTEX 3
+ gridVertices[currentVertex++] = x1;
+ gridVertices[currentVertex++] = y2;
+ gridVertices[currentVertex++] = z;
+ gridColors[currentColor++] = 1.0 - (x1 + y2 + 2.0) / 4.0;
+ gridColors[currentColor++] = (x1 + 1.0) / 2.0;
+ gridColors[currentColor++] = (y2 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = 1.0 - (x2 + y1 + 2.0) / 4.0;
+ gridSecColors[currentSecColor++] = (x2 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = (y1 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (x1 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (y2 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = 1.0 - (x2 + y1 + 2.0) / 4.0;
+ gridNormals[currentNormal++] = (x2 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = (y1 + 1.0) / 2.0;
+ gridFogCoords[currentFogCoord++] = (y2 + 1.0) / 2.0;
+
+ // VERTEX 0
+ gridVertices[currentVertex++] = x1;
+ gridVertices[currentVertex++] = y1;
+ gridVertices[currentVertex++] = z;
+ gridColors[currentColor++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
+ gridColors[currentColor++] = (x1 + 1.0) / 2.0;
+ gridColors[currentColor++] = (y1 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
+ gridSecColors[currentSecColor++] = (x2 + 1.0) / 2.0;
+ gridSecColors[currentSecColor++] = (y2 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (x1 + 1.0) / 2.0;
+ gridTexCoords0[currentTexCoord0++] = (y1 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
+ gridNormals[currentNormal++] = (x2 + 1.0) / 2.0;
+ gridNormals[currentNormal++] = (y2 + 1.0) / 2.0;
+ gridFogCoords[currentFogCoord++] = (y1 + 1.0) / 2.0;
+ }
+ }
+
+ var buffers = {
+ "gtf_Vertex": { data: gridVertices, numComponents: 3 },
+ "gtf_Color": { data: gridColors, numComponents: 3 },
+ "gtf_SecondaryColor": { data: gridSecColors, numComponents: 3 },
+ "gtf_Normal": { data: gridNormals, numComponents: 3 },
+ "gtf_FogCoord": { data: gridFogCoords, numComponents: 1 },
+ "gtf_MultiTexCoord0": { data: gridTexCoords0, numComponents: 2 }
+ };
+ setAttribs(attribs, buffers);
+ gl.drawArrays(gl.TRIANGLES, 0, numVertices);
+}
+
+var MODEL_FUNCS = {
+ square: drawSquare,
+ frontbacksquare: drawFrontBackSquare,
+ grid: drawGrid
+};
+
+function drawWithProgram(program, programInfo, test) {
+ gl.useProgram(program);
+ var attribs = { };
+
+ var numAttribs = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
+ for (var ii = 0; ii < numAttribs; ++ii) {
+ var info = gl.getActiveAttrib(program, ii);
+ var name = info.name;
+ var location = gl.getAttribLocation(program, name);
+ attribs[name] = location;
+
+ if (KNOWN_ATTRIBS.indexOf(name) < 0) {
+ testFailed("unknown attrib:" + name)
+ }
+ }
+
+ var uniforms = { };
+ var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
+ for (var ii = 0; ii < numUniforms; ++ii) {
+ var info = gl.getActiveUniform(program, ii);
+ var name = info.name;
+ if (name.match(/\[0\]$/)) {
+ name = name.substr(0, name.length - 3);
+ }
+ var location = gl.getUniformLocation(program, name);
+ uniforms[name] = {location: location};
+ }
+
+ var getUniformLocation = function(name) {
+ var uniform = uniforms[name];
+ if (uniform) {
+ uniform.used = true;
+ return uniform.location;
+ }
+ return null;
+ }
+
+ // Set known uniforms
+ var loc = getUniformLocation("gtf_ModelViewProjectionMatrix");
+ if (loc) {
+ gl.uniformMatrix4fv(
+ loc,
+ false,
+ persp(60, 1, 1, 30));
+ }
+ var loc = getUniformLocation("viewportwidth");
+ if (loc) {
+ gl.uniform1f(loc, gl.canvas.width);
+ }
+ var loc = getUniformLocation("viewportheight");
+ if (loc) {
+ gl.uniform1f(loc, gl.canvas.height);
+ }
+
+ // Set test specific uniforms
+ for (var name in programInfo.uniforms) {
+ var location = getUniformLocation(name);
+ if (!location) {
+ continue;
+ }
+ var uniform = programInfo.uniforms[name];
+ var type = uniform.type;
+ var value = uniform.value;
+ var transpose = uniform.transpose;
+ if (transpose !== undefined) {
+ log("gl." + type + '("' + name + '", ' + transpose + ", " + value + ")");
+ gl[type](location, transpose, value);
+ } else if (!type.match("v$")) {
+ var args = [location];
+ for (var ii = 0; ii < value.length; ++ii) {
+ args.push(value[ii]);
+ }
+ gl[type].apply(gl, args);
+ log("gl." + type + '("' + name + '", ' + args.slice(1) + ")");
+ } else {
+ log("gl." + type + '("' + name + '", ' + value + ")");
+ gl[type](location, value);
+ }
+ var err = gl.getError();
+ if (err != gl.NO_ERROR) {
+ testFailed(wtu.glEnumToString(gl, err) + " generated setting uniform: " + name);
+ }
+ }
+
+ // Filter out specified built-in uniforms
+ if (programInfo.builtin_uniforms) {
+ var num_builtins_found = 0;
+ var valid_values = programInfo.builtin_uniforms.valid_values;
+ for (var index in valid_values) {
+ var uniform = uniforms[valid_values[index]];
+ if (uniform) {
+ ++num_builtins_found;
+ uniform.builtin = true;
+ }
+ }
+
+ var min_required = programInfo.builtin_uniforms.min_required;
+ if (num_builtins_found < min_required) {
+ testFailed("only found " + num_builtins_found + " of " + min_required +
+ " required built-in uniforms: " + valid_values);
+ }
+ }
+
+ // Check for unset uniforms
+ for (var name in uniforms) {
+ var uniform = uniforms[name];
+ if (!uniform.used && !uniform.builtin) {
+ testFailed("uniform " + name + " never set");
+ }
+ }
+
+
+ for (var state in test.state) {
+ var fields = test.state[state];
+ switch (state) {
+ case 'depthrange':
+ gl.depthRange(fields.near, fields.far);
+ break;
+ default:
+ testFailed("unknown state: " + state)
+ }
+ }
+
+ gl.clearColor(0, 0, 0, 0);
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+ var model = test.model || "square";
+ var fn = MODEL_FUNCS[model];
+ if (!fn) {
+ testFailed("unknown model type: " + model)
+ } else {
+ log("draw as: " + model)
+ fn(attribs, gl.canvas.width, gl.canvas.height);
+ }
+
+ var pixels = new Uint8Array(gl.canvas.width * gl.canvas.height * 4);
+ gl.readPixels(0, 0, gl.canvas.width, gl.canvas.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+ return {
+ width: gl.canvas.width,
+ height: gl.canvas.height,
+ pixels: pixels,
+ img: wtu.makeImageFromCanvas(gl.canvas)
+ };
+}
+
+function runProgram(programInfo, test, label, callback) {
+ var shaders = [];
+ var source = [];
+ var count = 0;
+
+ function loadShader(path, type, index) {
+ wtu.loadTextFileAsync(path, function(success, text) {
+ addShader(success, text, type, path, index);
+ });
+ }
+
+ function addShader(success, text, type, path, index) {
+ ++count;
+ if (!success) {
+ testFailed("could not load: " + path);
+ } else {
+ var shader = wtu.loadShader(gl, text, type);
+ shaders.push(shader);
+ source[index] = text;
+ }
+ if (count == 2) {
+ var result;
+ if (shaders.length == 2) {
+ debug("");
+ if (!quietMode()) {
+ var consoleDiv = document.getElementById("console");
+ wtu.addShaderSources(
+ gl, consoleDiv, label + " vertex shader", shaders[0], source[0],
+ programInfo.vertexShader);
+ wtu.addShaderSources(
+ gl, consoleDiv, label + " fragment shader", shaders[1], source[1],
+ programInfo.fragmentShader);
+ }
+ var program = wtu.createProgram(gl, shaders[0], shaders[1]);
+ result = drawWithProgram(program, programInfo, test);
+ }
+ callback(result);
+ }
+ }
+
+ loadShader(programInfo.vertexShader, gl.VERTEX_SHADER, 0);
+ loadShader(programInfo.fragmentShader, gl.FRAGMENT_SHADER, 1);
+}
+
+function compareResults(expected, actual) {
+ var width = expected.width;
+ var height = expected.height;
+ var canvas = document.createElement("canvas");
+ canvas.width = width;
+ canvas.height = height;
+ var ctx = canvas.getContext("2d");
+ var imgData = ctx.getImageData(0, 0, width, height);
+ var tolerance = 0;
+
+ var expData = expected.pixels;
+ var actData = actual.pixels;
+
+ var same = compareImages(expData, actData, width, height, imgData.data);
+
+ var console = document.getElementById("console");
+ var diffImg = null;
+ if (!same) {
+ ctx.putImageData(imgData, 0, 0);
+ diffImg = wtu.makeImageFromCanvas(canvas);
+ }
+
+ if (!quietMode()) {
+ var div = document.createElement("div");
+ div.className = "testimages";
+ wtu.insertImage(div, "reference", expected.img);
+ wtu.insertImage(div, "test", actual.img);
+ if (diffImg) {
+ wtu.insertImage(div, "diff", diffImg);
+ }
+ div.appendChild(document.createElement('br'));
+
+ console.appendChild(div);
+ }
+
+ if (!same) {
+ testFailed("images are different");
+ } else {
+ testPassed("images are the same");
+ }
+
+ if (!quietMode())
+ console.appendChild(document.createElement('hr'));
+}
+
+function runCompareTest(test, callback) {
+ debug("");
+ debug("test: " + test.name);
+ var results = [];
+ var count = 0;
+
+ function storeResults(index) {
+ return function(result) {
+ results[index] = result;
+ ++count;
+ if (count == 2) {
+ compareResults(results[0], results[1]);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
+ callback();
+ }
+ }
+ }
+
+ runProgram(test.referenceProgram, test, "reference", storeResults(0));
+ runProgram(test.testProgram, test, "test", storeResults(1));
+}
+
+function runBuildTest(test, callback) {
+ debug("");
+ debug("test: " + test.name);
+
+ var shaders = [null, null];
+ var source = ["",""];
+ var success = [undefined, undefined];
+ var count = 0;
+
+ function loadShader(path, type, index) {
+ if (path == "empty") {
+ shaders[index] = gl.createShader();
+ success[index] = true;
+ source[index] = "/* empty */";
+ attachAndLink();
+ } else {
+ wtu.loadTextFileAsync(path, function(loadSuccess, text) {
+ if (!loadSuccess) {
+ success[index] = false;
+ source[index] = "/* could not load */";
+ testFailed("could not load:" + path);
+ } else {
+ source[index] = text;
+ shaders[index] = wtu.loadShader(gl, text, type, function(index) {
+ return function(msg) {
+ success[index] = false
+ }
+ }(index));
+ if (success[index] === undefined) {
+ success[index] = true;
+ }
+ }
+ attachAndLink();
+ });
+ }
+ }
+
+ function attachAndLink() {
+ ++count;
+ if (count == 2) {
+ if (!quietMode()) {
+ debug("");
+ var c = document.getElementById("console");
+ wtu.addShaderSource(
+ c, "vertex shader", source[0], test.testProgram.vertexShader);
+ debug("compile: " + (success[0] ? "success" : "fail"));
+ wtu.addShaderSource(
+ c, "fragment shader", source[1], test.testProgram.fragmentShader);
+ debug("compile: " + (success[1] ? "success" : "fail"));
+ }
+ compileSuccess = (success[0] && success[1]);
+ if (!test.compstat) {
+ if (compileSuccess) {
+ testFailed("expected compile failure but was successful");
+ } else {
+ testPassed("expected compile failure and it failed");
+ }
+ } else {
+ if (compileSuccess) {
+ testPassed("expected compile success and it was successful");
+ } else {
+ testFailed("expected compile success but it failed");
+ }
+ var linkSuccess = true;
+ var program = wtu.createProgram(gl, shaders[0], shaders[1], function() {
+ linkSuccess = false;
+ });
+ if (linkSuccess !== test.linkstat) {
+ testFailed("expected link to " + (test.linkstat ? "succeed" : "fail"));
+ } else {
+ testPassed("shaders compiled and linked as expected.");
+ }
+ }
+ callback();
+ }
+ }
+
+ loadShader(test.testProgram.vertexShader, gl.VERTEX_SHADER, 0);
+ loadShader(test.testProgram.fragmentShader, gl.FRAGMENT_SHADER, 1);
+}
+
+var testPatterns = {
+ compare: runCompareTest,
+ build: runBuildTest,
+
+ dummy: null // just here to mark the end
+};
+
+function LogGLCall(functionName, args) {
+ console.log("gl." + functionName + "(" +
+ WebGLDebugUtils.glFunctionArgsToString(functionName, args) + ")");
+}
+
+// Runs the tests async since they will load shaders.
+function run(obj) {
+ description();
+
+ var canvas = document.getElementById("example");
+ gl = wtu.create3DContext(canvas);
+ if (window.WebGLDebugUtils) {
+ gl = WebGLDebugUtils.makeDebugContext(gl, undefined, LogGLCall);
+ }
+ if (!gl) {
+ testFailed("context does not exist");
+ finishTest();
+ return;
+ }
+
+ if (gl.canvas.width != 500 || gl.canvas.height != 500) {
+ testFailed("canvas must be 500x500 pixels: Several shaders are hard coded to this size.");
+ }
+
+ var tests = obj.tests;
+ var ndx = 0;
+
+ function runNextTest() {
+ if (ndx < tests.length) {
+ var test = tests[ndx++];
+ var fn = testPatterns[test.pattern];
+ if (!fn) {
+ testFailed("test pattern: " + test.pattern + " not supoprted")
+ runNextTest();
+ } else {
+ fn(test, runNextTest);
+ }
+ } else {
+ finishTest();
+ }
+ }
+ runNextTest();
+}
+
+return {
+ run: run,
+};
+}());
+