Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / conformance / ogles / ogles-utils.js
blobb2a150049636b7dd15fb3498ff51026aa189e300
1 /*
2 Copyright (c) 2019 The Khronos Group Inc.
3 Use of this source code is governed by an MIT-style license that can be
4 found in the LICENSE.txt file.
5 */
6 OpenGLESTestRunner = (function(){
7 var wtu = WebGLTestUtils;
8 var gl;
10 var HALF_GRID_MAX_SIZE = 32;
11 var KNOWN_ATTRIBS = [
12   "gtf_Vertex",
13   "gtf_Color"
16 var GTFPIXELTOLERANCE = 24;
17 var GTFACCEPTABLEFAILURECONT = 10;
18 var GTFAMDPIXELTOLERANCE = 12;
19 var GTFSCORETOLERANCE = 0.65;
20 var GTFNCCTOLARANCEZERO = 0.25;
21 var GTFKERNALSIZE = 5;
23 function log(msg) {
24   // debug(msg);
27 function compareImages(refData, tstData, width, height, diff) {
28   function isPixelSame(offset) {
29     // First do simple check
30     if (Math.abs(refData[offset + 0] - tstData[offset + 0]) <= GTFPIXELTOLERANCE &&
31         Math.abs(refData[offset + 1] - tstData[offset + 1]) <= GTFPIXELTOLERANCE &&
32         Math.abs(refData[offset + 2] - tstData[offset + 2]) <= GTFPIXELTOLERANCE) {
33       return true;
34     }
36     // TODO: Implement crazy check that's used in OpenGL ES 2.0 conformance tests.
37     // NOTE: on Desktop things seem to be working. Maybe the more complex check
38     // is needed for embedded systems?
39     return false;
40   }
42   var same = true;
43   for (var yy = 0; yy < height; ++yy) {
44     for (var xx = 0; xx < width; ++xx) {
45       var offset = (yy * width + xx) * 4;
46       var diffOffset = ((height - yy - 1) * width + xx) * 4;
47       diff[diffOffset + 0] = 0;
48       diff[diffOffset + 1] = 0;
49       diff[diffOffset + 2] = 0;
50       diff[diffOffset + 3] = 255;
51       if (!isPixelSame(offset)) {
52         diff[diffOffset] = 255;
53         if (same) {
54           same = false;
55           testFailed("pixel @ (" + xx + ", " + yy + " was [" +
56                      tstData[offset + 0] + "," +
57                      tstData[offset + 1] + "," +
58                      tstData[offset + 2] + "," +
59                      tstData[offset + 3] + "] expected [" +
60                      refData[offset + 0] + "," +
61                      refData[offset + 1] + "," +
62                      refData[offset + 2] + "," +
63                      refData[offset + 3] + "]")
64         }
65       }
66     }
67   }
68   return same;
71 function persp(fovy, aspect, n, f) {
72   var dz = f - n;
73   var rad = fovy / 2.0 * 3.14159265 / 180;
75   var s = Math.sin(rad);
76   if (dz == 0 || s == 0 || aspect == 0)
77     return;
79   var cot = Math.cos(rad) / s;
81   return [
82     cot / aspect,
83     0.0,
84     0.0,
85     0.0,
87     0.0,
88     cot,
89     0.0,
90     0.0,
92     0.0,
93     0.0,
94     -(f + n) / dz,
95     -1.0,
97     0.0,
98     0.0,
99     -2.0 * f * n / dz,
100     0.0
101   ];
104 function setAttribs(attribs, buffers) {
105   for (var name in attribs) {
106     var buffer = buffers[name];
107     if (!buffer) {
108       testFailed("no buffer for attrib:" + name);
109       continue;
110     }
111     var loc = attribs[name];
112     log("setup attrib: " + loc + " as " + name);
113     var buf = gl.createBuffer();
114     gl.bindBuffer(gl.ARRAY_BUFFER, buf);
115     gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(buffer.data), gl.STATIC_DRAW);
116     gl.enableVertexAttribArray(loc);
117     gl.vertexAttribPointer(loc, buffer.numComponents, gl.FLOAT, false, 0, 0);
118   }
121 function drawSquare(attribs) {
122   var buffers = {
123     "gtf_Vertex": {
124       data: [
125         1.0, -1.0, -2.0,
126         1.0, 1.0, -2.0,
127         -1.0, -1.0, -2.0,
128         -1.0, 1.0, -2.0
129       ],
130       numComponents: 3
131     },
132     "gtf_Color": {
133       data: [
134         0.5, 1.0, 0.0,
135         0.0, 1.0, 1.0,
136         1.0, 0.0, 0.0,
137         0.5, 0.0, 1.0
138       ],
139       numComponents: 3,
140     },
141     "gtf_SecondaryColor": {
142       data: [
143         0.5, 0.0, 1.0,
144         1.0, 0.0, 0.0,
145         0.0, 1.0, 1.0,
146         0.5, 1.0, 0.0
147       ],
148       numComponents: 3,
149     },
150     "gtf_Normal": {
151       data: [
152         0.5, 0.0, 1.0,
153         1.0, 0.0, 0.0,
154         0.0, 1.0, 1.0,
155         0.5, 1.0, 0.0
156       ],
157       numComponents: 3,
158     },
159     "gtf_MultiTexCoord0": {
160       data: [
161         1.0, 0.0,
162         1.0, 1.0,
163         0.0, 0.0,
164         0.0, 1.0
165       ],
166       numComponents: 2,
167     },
168     "gtf_FogCoord": {
169       data: [
170         0.0,
171         1.0,
172         0.0,
173         1.0
174       ],
175       numComponents: 1,
176     }
177   };
178   setAttribs(attribs, buffers);
179   gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
182 function drawFrontBackSquare(attribs) {
183   var front = {
184     "gtf_Vertex": {
185       data: [
186         1.0, -1.0, -2.0,
187         1.0, 0.0, -2.0,
188         -1.0, -1.0, -2.0,
189         -1.0, 0.0, -2.0
190       ],
191       numComponents: 3
192     },
193     "gtf_Color": {
194       data: [
195         0.0, 1.0, 0.0,
196         0.0, 1.0, 0.0,
197         0.0, 1.0, 0.0,
198         0.0, 1.0, 0.0
199       ],
200       numComponents: 3,
201     },
202     "gtf_MultiTexCoord0": {
203       data: [
204         1.0, 0.0,
205         1.0, 0.5,
206         0.0, 0.0,
207         0.0, 0.5
208       ],
209       numComponents: 2,
210     }
211   };
212   setAttribs(attribs, front);
213   gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
215   var back = {
216     "gtf_Vertex": {
217       data: [
218         1.0, 1.0, -2.0,
219         1.0, 0.0, -2.0,
220         -1.0, 1.0, -2.0,
221         -1.0, 0.0, -2.0
222       ],
223       numComponents: 3
224     },
225     "gtf_Color": {
226       data: [
227         1.0, 0.0, 0.0,
228         1.0, 0.0, 0.0,
229         1.0, 0.0, 0.0,
230         1.0, 0.0, 0.0
231       ],
232       numComponents: 3,
233     },
234     "gtf_MultiTexCoord0": {
235       data: [
236         1.0, 0.1,
237         1.0, 0.5,
238         0.0, 0.1,
239         0.0, 0.5
240       ],
241       numComponents: 2,
242     }
243   };
244   setAttribs(attribs, back);
245   gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
248 function drawGrid(attribs, width, height) {
249   var n = Math.min(Math.floor(Math.max(width, height) / 4), HALF_GRID_MAX_SIZE);
251   var numVertices = (n + n) * (n + n) * 6;
253   var gridVertices   = [];
254   var gridColors     = [];
255   var gridSecColors  = [];
256   var gridNormals    = [];
257   var gridFogCoords  = [];
258   var gridTexCoords0 = [];
260   var currentVertex    = 0;
261   var currentColor     = 0;
262   var currentSecColor  = 0;
263   var currentTexCoord0 = 0;
264   var currentNormal    = 0;
265   var currentFogCoord  = 0;
267   var z = -2.0;
268   for(var i = -n; i < n; ++i)
269   {
270       var x1 = i / n;
271       var x2 = (i + 1) / n;
272       for(var j = -n; j < n; ++j)
273       {
274           var y1 = j / n;
275           var y2 = (j + 1) / n;
277           // VERTEX 0
278           gridVertices[currentVertex++] = x1;
279           gridVertices[currentVertex++] = y1;
280           gridVertices[currentVertex++] = z;
281           gridColors[currentColor++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
282           gridColors[currentColor++] = (x1 + 1.0) / 2.0;
283           gridColors[currentColor++] = (y1 + 1.0) / 2.0;
284           gridSecColors[currentSecColor++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
285           gridSecColors[currentSecColor++] = (x2 + 1.0) / 2.0;
286           gridSecColors[currentSecColor++] = (y2 + 1.0) / 2.0;
287           gridTexCoords0[currentTexCoord0++] = (x1 + 1.0) / 2.0;
288           gridTexCoords0[currentTexCoord0++] = (y1 + 1.0) / 2.0;
289           gridNormals[currentNormal++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
290           gridNormals[currentNormal++] = (x2 + 1.0) / 2.0;
291           gridNormals[currentNormal++] = (y2 + 1.0) / 2.0;
292           gridFogCoords[currentFogCoord++] = (y1 + 1.0) / 2.0;
294           // VERTEX 1
295           gridVertices[currentVertex++] = x2;
296           gridVertices[currentVertex++] = y1;
297           gridVertices[currentVertex++] = z;
298           gridColors[currentColor++] = 1.0 - (x2 + y1 + 2.0) / 4.0;
299           gridColors[currentColor++] = (x2 + 1.0) / 2.0;
300           gridColors[currentColor++] = (y1 + 1.0) / 2.0;
301           gridSecColors[currentSecColor++] = 1.0 - (x1 + y2 + 2.0) / 4.0;
302           gridSecColors[currentSecColor++] = (x1 + 1.0) / 2.0;
303           gridSecColors[currentSecColor++] = (y2 + 1.0) / 2.0;
304           gridTexCoords0[currentTexCoord0++] = (x2 + 1.0) / 2.0;
305           gridTexCoords0[currentTexCoord0++] = (y1 + 1.0) / 2.0;
306           gridNormals[currentNormal++] = 1.0 - (x1 + y2 + 2.0) / 4.0;
307           gridNormals[currentNormal++] = (x1 + 1.0) / 2.0;
308           gridNormals[currentNormal++] = (y2 + 1.0) / 2.0;
309           gridFogCoords[currentFogCoord++] = (y1 + 1.0) / 2.0;
311           // VERTEX 2
312           gridVertices[currentVertex++] = x2;
313           gridVertices[currentVertex++] = y2;
314           gridVertices[currentVertex++] = z;
315           gridColors[currentColor++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
316           gridColors[currentColor++] = (x2 + 1.0) / 2.0;
317           gridColors[currentColor++] = (y2 + 1.0) / 2.0;
318           gridSecColors[currentSecColor++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
319           gridSecColors[currentSecColor++] = (x1 + 1.0) / 2.0;
320           gridSecColors[currentSecColor++] = (y1 + 1.0) / 2.0;
321           gridTexCoords0[currentTexCoord0++] = (x2 + 1.0) / 2.0;
322           gridTexCoords0[currentTexCoord0++] = (y2 + 1.0) / 2.0;
323           gridNormals[currentNormal++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
324           gridNormals[currentNormal++] = (x1 + 1.0) / 2.0;
325           gridNormals[currentNormal++] = (y1 + 1.0) / 2.0;
326           gridFogCoords[currentFogCoord++] = (y2 + 1.0) / 2.0;
328           // VERTEX 2
329           gridVertices[currentVertex++] = x2;
330           gridVertices[currentVertex++] = y2;
331           gridVertices[currentVertex++] = z;
332           gridColors[currentColor++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
333           gridColors[currentColor++] = (x2 + 1.0) / 2.0;
334           gridColors[currentColor++] = (y2 + 1.0) / 2.0;
335           gridSecColors[currentSecColor++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
336           gridSecColors[currentSecColor++] = (x1 + 1.0) / 2.0;
337           gridSecColors[currentSecColor++] = (y1 + 1.0) / 2.0;
338           gridTexCoords0[currentTexCoord0++] = (x2 + 1.0) / 2.0;
339           gridTexCoords0[currentTexCoord0++] = (y2 + 1.0) / 2.0;
340           gridNormals[currentNormal++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
341           gridNormals[currentNormal++] = (x1 + 1.0) / 2.0;
342           gridNormals[currentNormal++] = (y1 + 1.0) / 2.0;
343           gridFogCoords[currentFogCoord++] = (y2 + 1.0) / 2.0;
345           // VERTEX 3
346           gridVertices[currentVertex++] = x1;
347           gridVertices[currentVertex++] = y2;
348           gridVertices[currentVertex++] = z;
349           gridColors[currentColor++] = 1.0 - (x1 + y2 + 2.0) / 4.0;
350           gridColors[currentColor++] = (x1 + 1.0) / 2.0;
351           gridColors[currentColor++] = (y2 + 1.0) / 2.0;
352           gridSecColors[currentSecColor++] = 1.0 - (x2 + y1 + 2.0) / 4.0;
353           gridSecColors[currentSecColor++] = (x2 + 1.0) / 2.0;
354           gridSecColors[currentSecColor++] = (y1 + 1.0) / 2.0;
355           gridTexCoords0[currentTexCoord0++] = (x1 + 1.0) / 2.0;
356           gridTexCoords0[currentTexCoord0++] = (y2 + 1.0) / 2.0;
357           gridNormals[currentNormal++] = 1.0 - (x2 + y1 + 2.0) / 4.0;
358           gridNormals[currentNormal++] = (x2 + 1.0) / 2.0;
359           gridNormals[currentNormal++] = (y1 + 1.0) / 2.0;
360           gridFogCoords[currentFogCoord++] = (y2 + 1.0) / 2.0;
362           // VERTEX 0
363           gridVertices[currentVertex++] = x1;
364           gridVertices[currentVertex++] = y1;
365           gridVertices[currentVertex++] = z;
366           gridColors[currentColor++] = 1.0 - (x1 + y1 + 2.0) / 4.0;
367           gridColors[currentColor++] = (x1 + 1.0) / 2.0;
368           gridColors[currentColor++] = (y1 + 1.0) / 2.0;
369           gridSecColors[currentSecColor++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
370           gridSecColors[currentSecColor++] = (x2 + 1.0) / 2.0;
371           gridSecColors[currentSecColor++] = (y2 + 1.0) / 2.0;
372           gridTexCoords0[currentTexCoord0++] = (x1 + 1.0) / 2.0;
373           gridTexCoords0[currentTexCoord0++] = (y1 + 1.0) / 2.0;
374           gridNormals[currentNormal++] = 1.0 - (x2 + y2 + 2.0) / 4.0;
375           gridNormals[currentNormal++] = (x2 + 1.0) / 2.0;
376           gridNormals[currentNormal++] = (y2 + 1.0) / 2.0;
377           gridFogCoords[currentFogCoord++] = (y1 + 1.0) / 2.0;
378       }
379   }
381   var buffers = {
382     "gtf_Vertex":         { data: gridVertices,   numComponents: 3 },
383     "gtf_Color":          { data: gridColors,     numComponents: 3 },
384     "gtf_SecondaryColor": { data: gridSecColors,  numComponents: 3 },
385     "gtf_Normal":         { data: gridNormals,    numComponents: 3 },
386     "gtf_FogCoord":       { data: gridFogCoords,  numComponents: 1 },
387     "gtf_MultiTexCoord0": { data: gridTexCoords0, numComponents: 2 }
388   };
389   setAttribs(attribs, buffers);
390   gl.drawArrays(gl.TRIANGLES, 0, numVertices);
393 var MODEL_FUNCS = {
394   square:          drawSquare,
395   frontbacksquare: drawFrontBackSquare,
396   grid:            drawGrid
399 function drawWithProgram(program, programInfo, test) {
400   gl.useProgram(program);
401   var attribs = { };
403   var numAttribs = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
404   for (var ii = 0; ii < numAttribs; ++ii) {
405     var info = gl.getActiveAttrib(program, ii);
406     var name = info.name;
407     var location = gl.getAttribLocation(program, name);
408     attribs[name] = location;
410     if (KNOWN_ATTRIBS.indexOf(name) < 0) {
411       testFailed("unknown attrib:" + name)
412     }
413   }
415   var uniforms = { };
416   var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
417   for (var ii = 0; ii < numUniforms; ++ii) {
418     var info = gl.getActiveUniform(program, ii);
419     var name = info.name;
420     if (name.match(/\[0\]$/)) {
421       name = name.substr(0, name.length - 3);
422     }
423     var location = gl.getUniformLocation(program, name);
424     uniforms[name] = {location: location};
425   }
427   var getUniformLocation = function(name) {
428     var uniform = uniforms[name];
429     if (uniform) {
430       uniform.used = true;
431       return uniform.location;
432     }
433     return null;
434   }
436   // Set known uniforms
437   var loc = getUniformLocation("gtf_ModelViewProjectionMatrix");
438   if (loc)  {
439     gl.uniformMatrix4fv(
440       loc,
441       false,
442       persp(60, 1, 1, 30));
443   }
444   var loc = getUniformLocation("viewportwidth");
445   if (loc) {
446     gl.uniform1f(loc, gl.canvas.width);
447   }
448   var loc = getUniformLocation("viewportheight");
449   if (loc) {
450     gl.uniform1f(loc, gl.canvas.height);
451   }
453   // Set test specific uniforms
454   for (var name in programInfo.uniforms) {
455     var location = getUniformLocation(name);
456     if (!location) {
457       continue;
458     }
459     var uniform = programInfo.uniforms[name];
460     var type = uniform.type;
461     var value = uniform.value;
462     var transpose = uniform.transpose;
463     if (transpose !== undefined) {
464       log("gl." + type + '("' + name + '", ' + transpose + ", " + value + ")");
465       gl[type](location, transpose, value);
466     } else if (!type.match("v$")) {
467       var args = [location];
468       for (var ii = 0; ii < value.length; ++ii) {
469         args.push(value[ii]);
470       }
471       gl[type].apply(gl, args);
472       log("gl." + type + '("' + name + '", ' + args.slice(1) + ")");
473     } else {
474       log("gl." + type + '("' + name + '", ' + value + ")");
475       gl[type](location, value);
476     }
477     var err = gl.getError();
478     if (err != gl.NO_ERROR) {
479       testFailed(wtu.glEnumToString(gl, err) + " generated setting uniform: " + name);
480     }
481   }
483   // Filter out specified built-in uniforms
484   if (programInfo.builtin_uniforms) {
485     var num_builtins_found = 0;
486     var valid_values = programInfo.builtin_uniforms.valid_values;
487     for (var index in valid_values) {
488       var uniform = uniforms[valid_values[index]];
489       if (uniform) {
490         ++num_builtins_found;
491         uniform.builtin = true;
492       }
493     }
495     var min_required = programInfo.builtin_uniforms.min_required;
496     if (num_builtins_found < min_required) {
497       testFailed("only found " + num_builtins_found + " of " + min_required +
498                  " required built-in uniforms: " + valid_values);
499     }
500   }
502   // Check for unset uniforms
503   for (var name in uniforms) {
504     var uniform = uniforms[name];
505     if (!uniform.used && !uniform.builtin) {
506       testFailed("uniform " + name + " never set");
507     }
508   }
511   for (var state in test.state) {
512     var fields = test.state[state];
513     switch (state) {
514     case 'depthrange':
515       gl.depthRange(fields.near, fields.far);
516       break;
517     default:
518       testFailed("unknown state: " + state)
519     }
520   }
522   gl.clearColor(0, 0, 0, 0);
523   gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
525   var model = test.model || "square";
526   var fn = MODEL_FUNCS[model];
527   if (!fn) {
528     testFailed("unknown model type: " + model)
529   } else {
530     log("draw as: " + model)
531     fn(attribs, gl.canvas.width, gl.canvas.height);
532   }
534   var pixels = new Uint8Array(gl.canvas.width * gl.canvas.height * 4);
535   gl.readPixels(0, 0, gl.canvas.width, gl.canvas.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
536   return {
537     width: gl.canvas.width,
538     height: gl.canvas.height,
539     pixels: pixels,
540     img: wtu.makeImageFromCanvas(gl.canvas)
541   };
544 function runProgram(programInfo, test, label, callback) {
545   var shaders = [];
546   var source = [];
547   var count = 0;
549   function loadShader(path, type, index) {
550     wtu.loadTextFileAsync(path, function(success, text) {
551       addShader(success, text, type, path, index);
552     });
553   }
555   function addShader(success, text, type, path, index) {
556     ++count;
557     if (!success) {
558       testFailed("could not load: " + path);
559     } else {
560       var shader = wtu.loadShader(gl, text, type);
561       shaders.push(shader);
562       source[index] = text;
563     }
564     if (count == 2) {
565       var result;
566       if (shaders.length == 2) {
567         debug("");
568         if (!quietMode()) {
569         var consoleDiv = document.getElementById("console");
570           wtu.addShaderSources(
571               gl, consoleDiv, label + " vertex shader", shaders[0], source[0],
572               programInfo.vertexShader);
573           wtu.addShaderSources(
574               gl, consoleDiv, label + " fragment shader", shaders[1], source[1],
575               programInfo.fragmentShader);
576         }
577         var program = wtu.createProgram(gl, shaders[0], shaders[1]);
578         result = drawWithProgram(program, programInfo, test);
579       }
580       callback(result);
581     }
582   }
584   loadShader(programInfo.vertexShader, gl.VERTEX_SHADER, 0);
585   loadShader(programInfo.fragmentShader, gl.FRAGMENT_SHADER, 1);
588 function compareResults(expected, actual) {
589   var width = expected.width;
590   var height = expected.height;
591   var canvas = document.createElement("canvas");
592   canvas.width = width;
593   canvas.height = height;
594   var ctx = canvas.getContext("2d");
595   var imgData = ctx.getImageData(0, 0, width, height);
596   var tolerance = 0;
598   var expData = expected.pixels;
599   var actData = actual.pixels;
601   var same = compareImages(expData, actData, width, height, imgData.data);
603   var console = document.getElementById("console");
604   var diffImg = null;
605   if (!same) {
606     ctx.putImageData(imgData, 0, 0);
607     diffImg = wtu.makeImageFromCanvas(canvas);
608   }
610   if (!quietMode()) {
611     var div = document.createElement("div");
612     div.className = "testimages";
613     wtu.insertImage(div, "reference", expected.img);
614     wtu.insertImage(div, "test", actual.img);
615     if (diffImg) {
616       wtu.insertImage(div, "diff", diffImg);
617     }
618     div.appendChild(document.createElement('br'));
620     console.appendChild(div);
621   }
623   if (!same) {
624     testFailed("images are different");
625   } else {
626     testPassed("images are the same");
627   }
629   if (!quietMode())
630     console.appendChild(document.createElement('hr'));
633 function runCompareTest(test, callback) {
634   debug("");
635   debug("test: " + test.name);
636   var results = [];
637   var count = 0;
639   function storeResults(index) {
640     return function(result) {
641       results[index] = result;
642       ++count;
643       if (count == 2) {
644         compareResults(results[0], results[1]);
645         wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
646         callback();
647       }
648     }
649   }
651   runProgram(test.referenceProgram, test, "reference", storeResults(0));
652   runProgram(test.testProgram, test, "test", storeResults(1));
655 function runBuildTest(test, callback) {
656   debug("");
657   debug("test: " + test.name);
659   var shaders = [null, null];
660   var source = ["",""];
661   var success = [undefined, undefined];
662   var count = 0;
664   function loadShader(path, type, index) {
665     if (path == "empty") {
666       shaders[index] = gl.createShader();
667       success[index] = true;
668       source[index] = "/* empty */";
669       attachAndLink();
670     } else {
671       wtu.loadTextFileAsync(path, function(loadSuccess, text) {
672         if (!loadSuccess) {
673           success[index] = false;
674           source[index] = "/* could not load */";
675           testFailed("could not load:" + path);
676         } else {
677           source[index] = text;
678           shaders[index] = wtu.loadShader(gl, text, type, function(index) {
679             return function(msg) {
680               success[index] = false
681             }
682           }(index));
683           if (success[index] === undefined) {
684             success[index] = true;
685           }
686         }
687         attachAndLink();
688       });
689     }
690   }
692   function attachAndLink() {
693     ++count;
694     if (count == 2) {
695       if (!quietMode()) {
696         debug("");
697         var c = document.getElementById("console");
698         wtu.addShaderSource(
699             c, "vertex shader", source[0], test.testProgram.vertexShader);
700         debug("compile: " + (success[0] ? "success" : "fail"));
701         wtu.addShaderSource(
702             c, "fragment shader", source[1], test.testProgram.fragmentShader);
703         debug("compile: " + (success[1] ? "success" : "fail"));
704       }
705       compileSuccess = (success[0] && success[1]);
706       if (!test.compstat) {
707         if (compileSuccess) {
708           testFailed("expected compile failure but was successful");
709         } else {
710           testPassed("expected compile failure and it failed");
711         }
712       } else {
713         if (compileSuccess) {
714           testPassed("expected compile success and it was successful");
715         } else {
716           testFailed("expected compile success but it failed");
717         }
718         var linkSuccess = true;
719         var program = wtu.createProgram(gl, shaders[0], shaders[1], function() {
720           linkSuccess = false;
721         });
722         if (linkSuccess !== test.linkstat) {
723           testFailed("expected link to " + (test.linkstat ? "succeed" : "fail"));
724         } else {
725           testPassed("shaders compiled and linked as expected.");
726         }
727       }
728       callback();
729     }
730   }
732   loadShader(test.testProgram.vertexShader, gl.VERTEX_SHADER, 0);
733   loadShader(test.testProgram.fragmentShader, gl.FRAGMENT_SHADER, 1);
736 var testPatterns = {
737   compare: runCompareTest,
738   build: runBuildTest,
740   dummy: null  // just here to mark the end
743 function LogGLCall(functionName, args) {
744   console.log("gl." + functionName + "(" +
745             WebGLDebugUtils.glFunctionArgsToString(functionName, args) + ")");
748 // Runs the tests async since they will load shaders.
749 function run(obj) {
750   description();
752   var canvas = document.getElementById("example");
753   gl = wtu.create3DContext(canvas);
754   if (window.WebGLDebugUtils) {
755     gl = WebGLDebugUtils.makeDebugContext(gl, undefined, LogGLCall);
756   }
757   if (!gl) {
758     testFailed("context does not exist");
759     finishTest();
760     return;
761   }
763   if (gl.canvas.width != 500 || gl.canvas.height != 500) {
764     testFailed("canvas must be 500x500 pixels: Several shaders are hard coded to this size.");
765   }
767   var tests = obj.tests;
768   var ndx = 0;
770   function runNextTest() {
771     if (ndx < tests.length) {
772       var test = tests[ndx++];
773       var fn = testPatterns[test.pattern];
774       if (!fn) {
775         testFailed("test pattern: " + test.pattern + " not supoprted")
776         runNextTest();
777       } else {
778         fn(test, runNextTest);
779       }
780     } else {
781       finishTest();
782     }
783   }
784   runNextTest();
787 return {
788   run: run,
790 }());