| Index: conformance/ogles/ogles-utils.js
|
| ===================================================================
|
| --- conformance/ogles/ogles-utils.js (revision 0)
|
| +++ conformance/ogles/ogles-utils.js (working copy)
|
| @@ -0,0 +1,780 @@
|
| +/*
|
| +** Copyright (c) 2012 The Khronos Group Inc.
|
| +**
|
| +** Permission is hereby granted, free of charge, to any person obtaining a
|
| +** copy of this software and/or associated documentation files (the
|
| +** "Materials"), to deal in the Materials without restriction, including
|
| +** without limitation the rights to use, copy, modify, merge, publish,
|
| +** distribute, sublicense, and/or sell copies of the Materials, and to
|
| +** permit persons to whom the Materials are furnished to do so, subject to
|
| +** the following conditions:
|
| +**
|
| +** The above copyright notice and this permission notice shall be included
|
| +** in all copies or substantial portions of the Materials.
|
| +**
|
| +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
| +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
| +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
| +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
| +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
| +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
| +*/
|
| +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);
|
| + }
|
| + }
|
| +
|
| + // Check for unset uniforms
|
| + for (var name in uniforms) {
|
| + var uniform = uniforms[name];
|
| + if (!uniform.used) {
|
| + 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.makeImage(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("");
|
| + var console = document.getElementById("console");
|
| + wtu.addShaderSource(
|
| + console, label + " vertex shader", source[0], programInfo.vertexShader);
|
| + wtu.addShaderSource(
|
| + console, label + " fragment shader", 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.makeImage(canvas);
|
| + }
|
| +
|
| + 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");
|
| + }
|
| +
|
| + 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]);
|
| + 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) {
|
| + 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,
|
| +};
|
| +}());
|
| +
|
|
|
| Property changes on: conformance/ogles/ogles-utils.js
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| ## -0,0 +1 ##
|
| +LF
|
| \ No newline at end of property
|
|
|