Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / webgl / src / sdk / tests / webgl-conformance-tests.html
1 <!--
2
3 /*
4 ** Copyright (c) 2013 The Khronos Group Inc.
5 **
6 ** Permission is hereby granted, free of charge, to any person obtaining a
7 ** copy of this software and/or associated documentation files (the
8 ** "Materials"), to deal in the Materials without restriction, including
9 ** without limitation the rights to use, copy, modify, merge, publish,
10 ** distribute, sublicense, and/or sell copies of the Materials, and to
11 ** permit persons to whom the Materials are furnished to do so, subject to
12 ** the following conditions:
13 **
14 ** The above copyright notice and this permission notice shall be included
15 ** in all copies or substantial portions of the Materials.
16 **
17 ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
24 */
25
26 -->
27 <!DOCTYPE html>
28 <html>
29 <head>
30 <meta charset="utf-8">
31 <!-- Prevents Chrome from offering to translate tests which generate
32      random characters for things like attribute names -->
33 <meta name="google" value="notranslate">
34 <title>WebGL Conformance Tests</title>
35 <style>
36   body {
37     border: 0;
38     margin: 0;
39     padding: 0;
40     height: 100%;
41     max-height:100%;
42     font-family: Verdana, Arial, sans-serif;
43     font-size: 0.8em;
44   }
45
46   a {
47     color: #88F;
48     text-decoration: none;
49   }
50
51   a:hover {
52     border-bottom: 1px solid #66D;
53   }
54
55   #testlist {
56     position:fixed;
57     top:310px;
58     left:0;
59     right:0;
60     bottom:0px;
61     overflow:auto;
62     padding:1em;
63   }
64
65   #header {
66     position:absolute;
67     top:0;
68     left:0;
69     width:100%;
70     height:310px;
71     overflow:auto;
72     border-bottom: 1px solid #CCC;
73   }
74
75   #info {
76     text-align: center;
77     min-width: 300px;
78   }
79
80   table {
81     width: 100%;
82     height: 100%;
83     border: 0;
84   }
85
86   #frames {
87     border-left: 1px solid #CCC;
88   }
89
90   #frames td {
91       min-height: 1px;
92       min-width: 1px;
93   }
94
95   #frames iframe {
96     border: 0;
97   }
98   
99   #testList {
100     padding:1em;
101   }
102
103   .folder {
104     margin-bottom: 1.5em;
105   }
106
107   .folderHeader {
108     white-space: nowrap;
109   }
110
111   .folderName {
112     font-weight: bold;
113   }
114
115   .pageHeader {
116     white-space: nowrap;
117   }
118
119   .testpage { 
120     border-style: solid;
121     border-color: #CCC;
122     border-width: 0px 0 1px 0;
123     background-color: #FFF;
124     padding: 4px 0 4px 0;
125
126     -webkit-transition: background-color 0.25s;
127     -moz-transition: background-color 0.25s;
128     transition: background-color 0.25s;
129   }
130
131   .testpage:first-child { 
132     border-width: 1px 0 1px 0;
133   }
134
135   .timeout { }
136   .success { }
137   .fail { }
138   .testpagesuccess { background-color: #8F8; }
139   .testpagefail { background-color: #F88; }
140   .testpageskipped { background-color: #888; }
141   .testpagetimeout { background-color: #FC8; }
142   .nowebgl { font-weight: bold; color: red; }
143   #error-wrap {
144       float: left;
145       position: relative;
146       left: 50%;
147   }
148   #error {
149      color: red;
150      float: left;
151      position: relative;
152      left: -50%;
153      text-align: left;
154   }
155   ul {
156     list-style: none;
157     padding-left: 1em;
158   }
159 </style>
160 <script type="text/javascript" src="resources/webgl-test-harness.js"></script>
161 <script>
162 "use strict";
163 var DEFAULT_CONFORMANCE_TEST_VERSION = "1.0.3 (beta)";
164
165 var OPTIONS = {
166   version: DEFAULT_CONFORMANCE_TEST_VERSION,
167   frames: 1,
168   allowSkip: 0
169 };
170
171 var testVersions = [
172   "1.0.3 (beta)",
173   "2.0.0 (beta)"
174 ];
175
176 function start() {
177
178   function log(msg) {
179     if (window.console && window.console.log) {
180       window.console.log(msg);
181     }
182   }
183
184   function create3DContext(canvas, attrs, version) {
185     if (!canvas) {
186       canvas = document.createElement("canvas");
187     }
188     var context = null;
189     var names;
190     switch (version) {
191       case 2:
192         names = ["webgl2", "experimental-webgl2"]; break;
193       default:
194         names = ["webgl", "experimental-webgl"]; break;
195     }
196     for (var i = 0; i < names.length; ++i) {
197       try {
198         context = canvas.getContext(names[i], attrs);
199       } catch (e) {
200       }
201       if (context) {
202         break;
203       }
204     }
205     return context;
206   }
207
208   var reportType = WebGLTestHarnessModule.TestHarness.reportType;
209   var pageCount = 0;
210   var folderCount = 0;
211   var autoScrollEnabled = true; // Whether the user prefers to auto scroll
212   var autoScroll = true; // Whether auto scroll is actually performed
213
214   var Page = function(reporter, folder, testIndex, url) {
215     this.reporter = reporter;
216     this.folder = folder;
217     this.url = url;
218     this.totalTests = 0;
219     this.totalSuccessful = 0;
220     this.totalTimeouts = 0;
221     this.totalSkipped = 0;
222     this.testIndex = testIndex;
223
224     this.elementId = "page" + pageCount++;
225     var li = reporter.localDoc.createElement('li');
226     li.id = this.elementId;
227     var div = reporter.localDoc.createElement('div');
228     div.classList.add('pageHeader');
229     var check = reporter.localDoc.createElement('input');
230     check.type = 'checkbox';
231     check.checked = true;
232     div.appendChild(check);
233     var button = reporter.localDoc.createElement('input');
234     button.type = 'button';
235     button.value = 'run';
236     button.onclick = function() {
237       autoScroll = false;
238       reporter.runTest(url);
239     };
240     if (reporter.noSelectedWebGLVersion) {
241       button.disabled = true;
242     }
243     div.appendChild(button);
244     var a = reporter.localDoc.createElement('a');
245     a.href = WebGLTestHarnessModule.getURLWithVersion(url, reporter.selectedWebGLVersion);
246     a.target = "_blank";
247     var node = reporter.localDoc.createTextNode(url);
248     a.appendChild(node);
249     div.appendChild(a);
250     li.setAttribute('class', 'testpage');
251     li.appendChild(div);
252     var ul = reporter.localDoc.createElement('ul');
253     var node = reporter.localDoc.createTextNode('');
254     li.appendChild(ul);
255     div.appendChild(node);
256     this.totalsElem = node;
257     this.resultElem = ul;
258     this.elem = li;
259     this.check = check;
260   };
261
262   Page.prototype.addResult = function(msg, success, skipped) {
263     ++this.totalTests;
264     if (success === undefined) {
265       ++this.totalTimeouts;
266       var result = "timeout";
267       var css = "timeout";
268     } else if (success) {
269       if(skipped) {
270         ++this.totalSkipped;
271       } else {
272         ++this.totalSuccessful;
273       }
274       // don't report success.
275       return;
276     } else {
277       var result = "failed";
278       var css = "fail";
279     }
280
281     var node = this.reporter.localDoc.createTextNode(result + ': ' + msg);
282     var li = this.reporter.localDoc.createElement('li');
283     li.appendChild(node);
284     li.setAttribute('class', css);
285     this.resultElem.appendChild(li);
286   };
287
288   Page.prototype.startPage = function() {
289     if (autoScroll && this.elem.scrollIntoView) {
290       this.elem.scrollIntoView(false);
291     }
292     this.totalTests = 0;
293     this.totalSuccessful = 0;
294     this.totalTimeouts = 0;
295     // remove previous results.
296     while (this.resultElem.hasChildNodes()) {
297       this.resultElem.removeChild(this.resultElem.childNodes[0]);
298     }
299     this.totalsElem.textContent = '';
300
301     var shouldRun = this.check.checked && this.folder.checked();
302
303     if (shouldRun) {
304       this.elem.classList.remove('testpagetimeout');
305       this.elem.classList.remove('testpageskipped');
306       this.elem.classList.remove('testpagefail');
307       this.elem.classList.remove('testpagesuccess');
308     }
309
310     return this.check.checked && this.folder.checked();
311   };
312
313   Page.prototype.firstTestIndex = function() {
314     return this.testIndex;
315   };
316
317   Page.prototype.finishPage = function(success) {
318     if(this.totalSkipped) {
319       var msg = ' (' + this.totalSkipped + ' of ' + this.totalTests + ' skipped)';
320     } else {
321       var msg = ' (' + this.totalSuccessful + ' of ' + this.totalTests + ' passed)';
322     }
323
324     if (success === undefined) {
325       var css = 'testpagetimeout';
326       msg = '(*timeout*)';
327       ++this.totalTests;
328       ++this.totalTimeouts;
329     } else if (this.totalSkipped) {
330       var css = 'testpageskipped';
331     } else if (this.totalSuccessful != this.totalTests) {
332       var css = 'testpagefail';
333     } else {
334       var css = 'testpagesuccess';
335     }
336     this.elem.classList.add(css);
337     this.totalsElem.textContent = msg;
338   };
339
340   Page.prototype.enableTest = function(re) {
341     if (this.url.match(re)) {
342       this.check.checked = true;
343       this.folder.enableUp_();
344     }
345   };
346
347   Page.prototype.disableTest = function(re) {
348     if (this.url.match(re)) {
349       this.check.checked = false;
350     }
351   };
352
353   var Folder = function(reporter, folder, depth, opt_name) {
354     this.reporter = reporter;
355     this.depth = depth;
356     this.name = opt_name || "";
357     this.displayName = this.name;
358     if (folder && folder.displayName) {
359       this.displayName = folder.displayName + '/' + this.displayName;
360     }
361     this.subFolders = {};
362     this.pages = [];
363     this.items = [];
364     this.folder = folder;
365     var that = this;
366
367     var doc = reporter.localDoc;
368     this.elementId = "folder" + folderCount++;
369     var li = doc.createElement('li');
370     li.id = this.elementId;
371     li.classList.add("folder");
372     var div = doc.createElement('div');
373     div.classList.add('folderHeader');
374     var check = doc.createElement('input');
375     check.type = 'checkbox';
376     check.checked = true;
377     div.appendChild(check);
378     var button = doc.createElement('input');
379     button.type = 'button';
380     button.value = 'run';
381     button.onclick = function() {
382       autoScroll = autoScrollEnabled;
383       that.run();
384     };
385     if (reporter.noSelectedWebGLVersion) {
386       button.disabled = true;
387     }
388     div.appendChild(button);
389     var h = doc.createElement('span');
390     h.classList.add('folderName');
391     h.appendChild(doc.createTextNode(this.displayName));
392     div.appendChild(h);
393     var ul = doc.createElement('ul');
394     li.appendChild(div);
395     li.appendChild(ul);
396     this.childUL = ul;
397     this.elem = li;
398     this.check = check;
399     this.folderHeader = div;
400   };
401
402   Folder.prototype.checked = function() {
403     return this.check.checked &&
404         (this.folder ? this.folder.checked() : true);
405   };
406
407   Folder.prototype.firstTestIndex = function() {
408     return this.items[0].firstTestIndex();
409   };
410
411   Folder.prototype.numChildren = function() {
412     var numChildren = 0;
413     for (var name in this.subFolders) {
414       numChildren += this.subFolders[name].numChildren();
415     }
416     return numChildren + this.pages.length;
417   };
418
419   Folder.prototype.run = function() {
420     var firstTestIndex = this.firstTestIndex();
421     var count = this.numChildren();
422     log("run tests: " + firstTestIndex + " to " + (firstTestIndex + count - 1))
423     testHarness.runTests({start: firstTestIndex, count: count});
424   };
425
426   Folder.prototype.getSubFolder = function(name) {
427     var subFolder = this.subFolders[name];
428     if (subFolder === undefined) {
429       subFolder = new Folder(this.reporter, this, this.depth + 1, name);
430       this.subFolders[name] = subFolder;
431       this.items.push(subFolder);
432       this.childUL.appendChild(subFolder.elem);
433     }
434     return subFolder;
435   };
436
437   Folder.prototype.getOrCreateFolder = function(url) {
438     var parts = url.split('/');
439     var folder = this;
440     for (var pp = 0; pp < parts.length - 1; ++pp) {
441       folder = folder.getSubFolder(parts[pp]);
442     }
443     return folder;
444   };
445
446   Folder.prototype.addPage = function(page) {
447     this.pages.push(page);
448     this.items.push(page);
449     this.childUL.appendChild(page.elem);
450     this.folderHeader.classList.add('hasPages');
451   };
452
453   Folder.prototype.disableTest = function(re, opt_forceRecurse) {
454     var recurse = true;
455     if (this.name.match(re)) {
456       this.check.checked = false;
457       recurse = opt_forceRecurse;
458     }
459     if (recurse) {
460       for (var name in this.subFolders) {
461         this.subFolders[name].disableTest(re, opt_forceRecurse);
462       }
463       for (var ii = 0; ii < this.pages.length; ++ii) {
464         this.pages[ii].disableTest(re);
465       }
466     }
467   };
468
469   Folder.prototype.enableUp_ = function() {
470     this.check.checked = true;
471     var parent = this.folder;
472     if (parent) {
473       parent.enableUp_();
474     }
475   }
476
477   Folder.prototype.enableTest = function(re) {
478     if (this.name.match(re)) {
479       this.enableUp_();
480     }
481     for (var name in this.subFolders) {
482       this.subFolders[name].enableTest(re);
483     }
484     for (var ii = 0; ii < this.pages.length; ++ii) {
485       this.pages[ii].enableTest(re);
486     }
487   };
488
489   var Reporter = function(iframes) {
490     this.localDoc = document;
491     this.resultElem = document.getElementById("results");
492     this.fullResultsElem = document.getElementById("fullresults");
493     var node = this.localDoc.createTextNode('');
494     this.fullResultsElem.appendChild(node);
495     this.fullResultsNode = node;
496     this.iframes = iframes;
497     this.currentPageElem = null;
498     this.totalPages = 0;
499     this.pagesByURL = {};
500
501     // Check to see if WebGL is supported
502     var canvas = document.createElement("canvas");
503     var ctx = create3DContext(canvas, null, 1);
504
505     // Check to see if WebGL2 is supported
506     var canvas2 = document.createElement("canvas");
507     var ctx2 = create3DContext(canvas2, null, 2);
508
509     this.noSelectedWebGLVersion = false;
510     this.selectedWebGLVersion = WebGLTestHarnessModule.getMajorVersion(OPTIONS.version);
511     if (this.selectedWebGLVersion == 2 && !ctx2) {
512         this.noSelectedWebGLVersion = true;
513     } else if (this.selectedWebGLVersion == 1 && !ctx) {
514         this.noSelectedWebGLVersion = true;
515     }
516
517     // If the WebGL2 context could be created use it to get context info
518     if (ctx2) {
519       ctx = ctx2;
520     }
521
522     this.noWebGL = !ctx;
523
524     this.contextInfo = {};
525     this.root = new Folder(this, null, 0, "all");
526     this.resultElem.appendChild(this.root.elem);
527     this.callbacks = { };
528
529     if (ctx) {
530       this.contextInfo["VENDOR"] = ctx.getParameter(ctx.VENDOR);
531       this.contextInfo["VERSION"] = ctx.getParameter(ctx.VERSION);
532       this.contextInfo["RENDERER"] = ctx.getParameter(ctx.RENDERER);
533       this.contextInfo["RED_BITS"] = ctx.getParameter(ctx.RED_BITS);
534       this.contextInfo["GREEN_BITS"] = ctx.getParameter(ctx.GREEN_BITS);
535       this.contextInfo["BLUE_BITS"] = ctx.getParameter(ctx.BLUE_BITS);
536       this.contextInfo["ALPHA_BITS"] = ctx.getParameter(ctx.ALPHA_BITS);
537       this.contextInfo["DEPTH_BITS"] = ctx.getParameter(ctx.DEPTH_BITS);
538       this.contextInfo["STENCIL_BITS"] = ctx.getParameter(ctx.STENCIL_BITS);
539
540       var ext = ctx.getExtension("WEBGL_debug_renderer_info");
541       if (ext) {
542         this.contextInfo["UNMASKED_VENDOR"] = ctx.getParameter(ext.UNMASKED_VENDOR_WEBGL);
543         this.contextInfo["UNMASKED_RENDERER"] = ctx.getParameter(ext.UNMASKED_RENDERER_WEBGL);
544       }
545     }
546   };
547
548   Reporter.prototype.enableTest = function(name) {
549     this.root.enableTest(name);
550   };
551
552   Reporter.prototype.disableTest = function(name) {
553     this.root.disableTest(name);
554   };
555
556   Reporter.prototype.disableAllTests = function() {
557     this.root.disableTest(".*", true);
558   };
559
560   Reporter.prototype.addEventListener = function(type, func) {
561     if (!this.callbacks[type]) {
562       this.callbacks[type] = [];
563     }
564     this.callbacks[type].push(func);
565   };
566
567   Reporter.prototype.executeListenerEvents_ = function(type) {
568     var callbacks = this.callbacks[type].slice(0);
569     for (var ii = 0; ii < callbacks.length; ++ii) {
570       setTimeout(callbacks[ii], 0);
571     }
572   };
573
574   Reporter.prototype.runTest = function(url) {
575     var page = this.pagesByURL[url];
576     testHarness.runTests({start: page.firstTestIndex(), count: 1});
577   };
578
579   Reporter.prototype.getFolder = function(url) {
580     return this.root.getOrCreateFolder(url);
581   };
582
583   Reporter.prototype.addPage = function(url) {
584     var folder = this.getFolder(url);
585     var page = new Page(this, folder, this.totalPages, url);
586     folder.addPage(page);
587     ++this.totalPages;
588     this.pagesByURL[url] = page;
589   };
590
591   Reporter.prototype.startPage = function(url) {
592     var page = this.pagesByURL[url];
593     return page.startPage();
594   };
595
596   Reporter.prototype.addResult = function(url, msg, success, skipped) {
597     var page = this.pagesByURL[url];
598     page.addResult(msg, success, skipped);
599   };
600
601   Reporter.prototype.finishPage = function(url, success) {
602     var page = this.pagesByURL[url];
603     page.finishPage(success);
604   };
605
606   Reporter.prototype.displayFinalResults = function(msg, success) {
607     if (success) {
608       var totalTests = 0;
609       var totalSuccessful = 0;
610       var totalTimeouts = 0;
611       var totalSkipped = 0;
612       for (var url in this.pagesByURL) {
613         var page = this.pagesByURL[url];
614         totalTests += page.totalTests;
615         totalSuccessful += page.totalSuccessful;
616         totalTimeouts += page.totalTimeouts;
617         totalSkipped += page.totalSkipped;
618       }
619       var timeout = '';
620       if (totalTimeouts > 0) {
621         timeout = ', ' + totalTimeouts + ' timed out';
622       }
623       var msg = ' (' + totalSuccessful + ' of ' +
624                 totalTests + ' passed' + timeout + ')';
625       this.fullResultsNode.textContent = msg;
626
627       // generate a text summary
628       var tx = "";
629       tx += "WebGL Conformance Test Results\n";
630       tx += "Version " + OPTIONS.version + "\n";
631       tx += "\n";
632       tx += "-------------------\n\n";
633       tx += "User Agent: " + (navigator.userAgent ? navigator.userAgent : "(navigator.userAgent is null)") + "\n";
634       tx += "WebGL VENDOR: " + this.contextInfo["VENDOR"] + "\n";
635       tx += "WebGL VERSION: " + this.contextInfo["VERSION"] + "\n";
636       tx += "WebGL RENDERER: " + this.contextInfo["RENDERER"] + "\n";
637       tx += "Unmasked VENDOR: " + this.contextInfo["UNMASKED_VENDOR"] + "\n";
638       tx += "Unmasked RENDERER: " + this.contextInfo["UNMASKED_RENDERER"] + "\n";
639       tx += "WebGL R/G/B/A/Depth/Stencil bits (default config): " + this.contextInfo["RED_BITS"] + "/" + this.contextInfo["GREEN_BITS"] + "/" + this.contextInfo["BLUE_BITS"] + "/" + this.contextInfo["ALPHA_BITS"] + "/" + this.contextInfo["DEPTH_BITS"] + "/" + this.contextInfo["STENCIL_BITS"] + "\n";
640       tx += "\n";
641       tx += "-------------------\n\n";
642       tx += "Test Summary (" + totalTests + " total tests):\n";
643       tx += "Tests PASSED: " + totalSuccessful + "\n";
644       tx += "Tests FAILED: " + (totalTests - totalSuccessful - totalSkipped) + "\n";
645       tx += "Tests TIMED OUT: " + totalTimeouts + "\n";
646       tx += "Tests SKIPPED: " + totalSkipped + "\n";
647       tx += "\n";
648       tx += "-------------------\n\n";
649       if (totalSuccessful < totalTests) {
650         tx += "Failures:\n\n";
651         for (var url in this.pagesByURL) {
652             var page = this.pagesByURL[url];
653             var pageTotalFail = page.totalTests - page.totalSuccessful - page.totalSkipped;
654             if (!(page.totalTests == 0 && page.totalTimeouts == 0) &&
655                 pageTotalFail > 0)
656             {
657             tx += url + ": " + pageTotalFail + " tests failed";
658             if (page.totalTimeouts)
659                 tx += " (" + page.totalTimeouts + " timed out)";
660             tx += "\n";
661             }
662         }
663       } else {
664         tx += "All tests PASSED\n\n";
665       }
666       tx += "\n";
667       tx += "-------------------\n\n";
668       tx += "Complete Test Results (total / pass / fail / timeout / skipped):\n\n";
669       for (var url in this.pagesByURL) {
670         var page = this.pagesByURL[url];
671         var pageTotalFail = page.totalTests - page.totalSuccessful - page.totalSkipped;
672         if (!(page.totalTests == 0 && page.totalTimeouts == 0)) {
673           tx += url + ": " + page.totalTests + " / " +
674               page.totalSuccessful + " / " + pageTotalFail + " / " + page.totalTimeouts + " / " + page.totalSkipped + "\n";
675         }
676       }
677       tx += "\n";
678       tx += "-------------------\n\n";
679       tx += "Generated on: " + (new Date()).toString() + "\n";
680
681       var r = document.getElementById("testResultsAsText");
682       while (r.firstChild) r.removeChild(r.firstChild);
683       r.appendChild(document.createTextNode(tx));
684       document.getElementById("showTextSummary").style.visibility = "visible";
685
686       this.postResultsToServer(tx);
687     } else {
688       var e = document.getElementById("error");
689       e.innerHTML = msg;
690       this.postResultsToServer(msg);
691     }
692   };
693
694   Reporter.prototype.postTestStartToServer = function(resultText) {
695     if(OPTIONS.postResults == undefined || OPTIONS.postResults == 0) {
696       return;
697     }
698
699     var xhr = new XMLHttpRequest();
700     xhr.open('POST', "/start", true);
701     xhr.send(null);
702   };
703
704   Reporter.prototype.postResultsToServer = function(resultText) {
705     if(OPTIONS.postResults == undefined || OPTIONS.postResults == 0) {
706       return;
707     }
708
709     var xhr = new XMLHttpRequest();
710     xhr.open('POST', "/finish", true);
711     xhr.setRequestHeader("Content-Type", "text/plain");
712     xhr.send(resultText);
713   };
714
715   Reporter.prototype.ready = function() {
716     var loading = document.getElementById("loading");
717     loading.style.display = "none";
718     if (!this.noSelectedWebGLVersion) {
719       var button = document.getElementById("runTestsButton");
720       button.disabled = false;
721       this.executeListenerEvents_("ready");
722     }
723   };
724
725   Reporter.prototype.reportFunc = function(type, url, msg, success, skipped) {
726     switch (type) {
727       case reportType.ADD_PAGE:
728         return this.addPage(msg);
729       case reportType.READY:
730         return this.ready();
731       case reportType.START_PAGE:
732         return this.startPage(url);
733       case reportType.TEST_RESULT:
734         return this.addResult(url, msg, success, skipped);
735       case reportType.FINISH_PAGE:
736         return this.finishPage(url, success);
737       case reportType.FINISHED_ALL_TESTS:
738         return this.displayFinalResults(msg, success);
739       default:
740         throw 'unhandled';
741         break;
742     };
743   };
744
745   var getURLOptions = function(obj) {
746     var s = window.location.href;
747     var q = s.indexOf("?");
748     var e = s.indexOf("#");
749     if (e < 0) {
750       e = s.length;
751     }
752     var query = s.substring(q + 1, e);
753     var pairs = query.split("&");
754     for (var ii = 0; ii < pairs.length; ++ii) {
755       var keyValue = pairs[ii].split("=");
756       var key = keyValue[0];
757       var value = decodeURIComponent(keyValue[1]);
758       obj[key] = value;
759     }
760   };
761
762   getURLOptions(OPTIONS);
763
764   var makeVersionSelect = function(currentVersion) {
765     var versionSelect = document.getElementById("testVersion");
766     var foundCurrentVersion = false;
767     var numericCurrentVersion = currentVersion.replace(/[^\d.]/g, '');
768
769     for (var i in testVersions) {
770       var version = testVersions[i];
771       var numericVersion = version.replace(/[^\d.]/g, '');
772       var option = document.createElement("option");
773       option.setAttribute('value', numericVersion);
774       option.innerHTML = version;
775
776       if (numericVersion == numericCurrentVersion) {
777         foundCurrentVersion = true;
778         option.selected = true;
779       }
780
781       versionSelect.appendChild(option);
782     }
783
784     // If the version requested by the query string isn't in the list add it.
785     if (!foundCurrentVersion) {
786       var option = document.createElement("option");
787       option.setAttribute('value', numericCurrentVersion);
788       option.innerHTML = currentVersion + " (unknown)";
789       option.selected = true;
790
791       versionSelect.appendChild(option);
792     }
793
794     versionSelect.addEventListener('change', function(ev) {
795       window.location.href = "?version=" + versionSelect.value;
796     }, false);
797   }
798
799   makeVersionSelect(OPTIONS.version);
800
801   // Make iframes
802   var makeIFrames = function() {
803     var toparea = document.getElementById("toparea");
804     var frame = document.getElementById("frames");
805     var areaWidth = Math.max(100, toparea.clientWidth - 300);
806     var areaHeight = Math.max(100, frame.clientHeight);
807
808     var numCells = OPTIONS.frames;
809
810     var gridWidth = Math.max(1, Math.ceil(Math.sqrt(numCells)));
811     var gridHeight = gridWidth;
812     var bestAspect = 99999;
813     var bestNumEmptyCells = 99999;
814     var bestNumEmptyCellsColumns = 0;
815     var bestNumEmptyCellsAspect = 99999;
816     var minGoodAspect = 1 / 3;
817     var maxGoodAspect = 3 / 1;
818
819     for (var columns = 1; columns <= numCells; ++columns) {
820         var rows = Math.ceil(numCells / columns);
821         var cellWidth = areaWidth / columns;
822         var cellHeight = areaHeight / rows;
823         var cellAspect = cellWidth / cellHeight;
824         if (cellAspect >= minGoodAspect && cellAspect <= maxGoodAspect) {
825             var numEmptyCells = columns * rows - numCells;
826             // Keep the one with the least number of empty cells.
827             if (numEmptyCells < bestNumEmptyCells) {
828                 bestNumEmptyCells = numEmptyCells;
829                 bestNumEmptyCellsColumns = columns;
830                 bestNumEmptyCellsAspect = cellAspect;
831             // If it's the same number of empty cells keep the one
832             // with the best aspect.
833             } else if (numEmptyCells == bestNumEmptyCells &&
834                   Math.abs(cellAspect - 1) <
835                   Math.abs(bestNumEmptyCellsAspect - 1)) {
836                 bestNumEmptyCellsColumns = columns;
837                 bestNumEmptyCellsAspect = cellAspect;
838             }
839         }
840         if (Math.abs(cellAspect - 1) < Math.abs(bestAspect - 1)) {
841             gridWidth = columns;
842             gridHeight = rows;
843             bestAspect = cellAspect;
844         }
845     }
846
847     // if we found an aspect with few empty cells use that.
848     var numEmptyCells = gridWidth * gridHeight - numCells;
849     if (bestNumEmptyCellsColumns && bestNumEmptyCells < numEmptyCells) {
850         gridWidth = bestNumEmptyCellsColumns;
851         gridHeight = Math.ceil(numCells / gridWidth);
852     }
853
854     var table = document.createElement("table");
855     table.style.height = areaHeight + "px";
856     var tbody = document.createElement("tbody");
857     var iframes = [];
858     for (var row = 0; row < gridHeight; ++row) {
859       var tr = document.createElement("tr");
860       for (var column = 0; column < gridWidth; ++column) {
861         var td = document.createElement("td");
862         if (numCells > 0) {
863           --numCells;
864           var iframe = document.createElement("iframe");
865           iframe.setAttribute("scrolling", "yes");
866           iframe.style.width = "100%";
867           iframe.style.height = "100%";
868           iframes.push(iframe);
869           td.appendChild(iframe);
870         }
871         tr.appendChild(td);
872       }
873       tbody.appendChild(tr);
874     }
875     table.appendChild(tbody);
876     frame.appendChild(table);
877     return iframes;
878   };
879   var iframes = makeIFrames();
880
881   var reporter = new Reporter(iframes);
882   var testHarness = new WebGLTestHarnessModule.TestHarness(
883       iframes,
884       '00_test_list.txt',
885       function(type, url, msg, success, skipped) {
886         return reporter.reportFunc(type, url, msg, success, skipped);
887       },
888       OPTIONS);
889   reporter.addEventListener("ready", function() {
890     // Set which tests to include.
891     if (OPTIONS.include) {
892       reporter.disableAllTests();
893       var includes = OPTIONS.include.split(",")
894       for (var ii = 0; ii < includes.length; ++ii) {
895         reporter.enableTest(new RegExp(includes[ii]));
896       }
897     }
898     // Remove tests based on skip=re1,re2 in URL.
899     if (OPTIONS.skip) {
900       var skips = OPTIONS.skip.split(",")
901       for (var ii = 0; ii < skips.length; ++ii) {
902         reporter.disableTest(new RegExp(skips[ii]));
903       }
904     }
905     // Auto run the tests if the run=1 in URL
906     if (OPTIONS.run != undefined && OPTIONS.run != 0) {
907       reporter.postTestStartToServer();
908       testHarness.runTests();
909     }
910   });
911   window.webglTestHarness = testHarness;
912   var button = document.getElementById("runTestsButton");
913   button.disabled = true;
914   button.onclick = function() {
915     autoScroll = autoScrollEnabled;
916     reporter.postTestStartToServer();
917     testHarness.runTests();
918   };
919   var autoScrollCheckbox = document.getElementById("autoScrollCheckbox");
920   autoScrollCheckbox.checked = autoScrollEnabled;
921   autoScrollCheckbox.onclick = function() {
922     autoScrollEnabled = autoScrollCheckbox.checked;
923     autoScroll = autoScrollEnabled;
924   };
925   var textbutton = document.getElementById("showTextSummary");
926   textbutton.onclick = function() {
927     log("click");
928     var htmldiv = document.getElementById("testResultsHTML");
929     var textdiv = document.getElementById("testResultsText");
930     if (textdiv.style.display == "none") {
931       textdiv.style.display = "block";
932       htmldiv.style.display = "none";
933       textbutton.setAttribute("value", "display html summary");
934     } else {
935       textdiv.style.display = "none";
936       htmldiv.style.display = "block";
937       textbutton.setAttribute("value", "display text summary");
938     }
939   };
940   if (reporter.noSelectedWebGLVersion) {
941     button.disabled = true;
942   }
943   if (reporter.noWebGL) {
944     var elem = document.getElementById("nowebgl");
945     elem.style.display = "";
946     reporter.postResultsToServer("Browser does not appear to support WebGL");
947   } else if (reporter.noSelectedWebGLVersion) {
948     var elem = document.getElementById("noselectedwebgl");
949     elem.style.display = "";
950     reporter.postResultsToServer("Browser does not appear to support the selected version of WebGL");
951   }
952 }
953 </script>
954 </head>
955 <body onload="start()">
956
957 <div id="testlist">
958
959         <div id="testResultsHTML">
960           <ul id="results">
961           </ul>
962         </div>
963         <div style="display: none;" id="testResultsText">
964           <pre id="testResultsAsText"></pre>
965         </div>
966
967 </div> <!-- end of container -->
968
969 <div id="header">
970
971 <table>
972   <tr style="height: 300px;">
973     <td>
974       <table id="toparea">
975         <tr>
976           <td style="width: 300px">
977             <div id="info">
978               <img src="resources/webgl-logo.png" /><br />
979               WebGL Conformance Test Runner<br/>
980               Version 
981               <select id="testVersion">
982               </select>
983               <br/>
984               <a href="../../conformance-suites/"><i>(click here for previous versions)</i></a>
985               <br/>
986               <input type="button" value="run tests" id="runTestsButton"/>
987               <br/>
988               <input type="checkbox" id="autoScrollCheckbox"/>
989               <label for="autoScrollCheckbox">auto scroll</label>
990               <br/>
991               <input type="button" style="visibility: hidden;" value="display text summary" id="showTextSummary"/>
992               <div id="nowebgl" class="nowebgl" style="display: none;">
993                 This browser does not appear to support WebGL
994               </div>
995               <div id="noselectedwebgl" class="nowebgl" style="display: none;">
996                 This browser does not appear to support the selected version of WebGL
997               </div>
998             </div>
999           </td>
1000         </tr>
1001         <tr>
1002           <td>
1003             <div id="loading">
1004               Loading Tests...
1005             </div>
1006             <div>
1007               Results:
1008               <span id="fullresults">
1009               </span>
1010             </div>
1011           </td>
1012         </tr>
1013         <tr>
1014           <td>
1015             <div id="error-wrap">
1016               <pre id="error"></pre>
1017             </div>
1018           </td>
1019         </tr>
1020       </table>
1021     </td>
1022     <td id="frames"></td>
1023   </tr>
1024 </table>
1025 </div> <!-- end of header -->
1026
1027 </body>
1028 </html>