Update To 11.40.268.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.getURLWithOptions(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     if (OPTIONS.dumpShaders == 1) {
605       var xhr = new XMLHttpRequest();
606       xhr.open('POST', "/finishIndividualTest", true);
607       xhr.send(null);
608     }
609   };
610
611   Reporter.prototype.displayFinalResults = function(msg, success) {
612     if (success) {
613       var totalTests = 0;
614       var totalSuccessful = 0;
615       var totalTimeouts = 0;
616       var totalSkipped = 0;
617       for (var url in this.pagesByURL) {
618         var page = this.pagesByURL[url];
619         totalTests += page.totalTests;
620         totalSuccessful += page.totalSuccessful;
621         totalTimeouts += page.totalTimeouts;
622         totalSkipped += page.totalSkipped;
623       }
624       var timeout = '';
625       if (totalTimeouts > 0) {
626         timeout = ', ' + totalTimeouts + ' timed out';
627       }
628       var msg = ' (' + totalSuccessful + ' of ' +
629                 totalTests + ' passed' + timeout + ')';
630       this.fullResultsNode.textContent = msg;
631
632       // generate a text summary
633       var tx = "";
634       tx += "WebGL Conformance Test Results\n";
635       tx += "Version " + OPTIONS.version + "\n";
636       tx += "\n";
637       tx += "-------------------\n\n";
638       tx += "User Agent: " + (navigator.userAgent ? navigator.userAgent : "(navigator.userAgent is null)") + "\n";
639       tx += "WebGL VENDOR: " + this.contextInfo["VENDOR"] + "\n";
640       tx += "WebGL VERSION: " + this.contextInfo["VERSION"] + "\n";
641       tx += "WebGL RENDERER: " + this.contextInfo["RENDERER"] + "\n";
642       tx += "Unmasked VENDOR: " + this.contextInfo["UNMASKED_VENDOR"] + "\n";
643       tx += "Unmasked RENDERER: " + this.contextInfo["UNMASKED_RENDERER"] + "\n";
644       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";
645       tx += "\n";
646       tx += "-------------------\n\n";
647       tx += "Test Summary (" + totalTests + " total tests):\n";
648       tx += "Tests PASSED: " + totalSuccessful + "\n";
649       tx += "Tests FAILED: " + (totalTests - totalSuccessful - totalSkipped) + "\n";
650       tx += "Tests TIMED OUT: " + totalTimeouts + "\n";
651       tx += "Tests SKIPPED: " + totalSkipped + "\n";
652       tx += "\n";
653       tx += "-------------------\n\n";
654       if (totalSuccessful < totalTests) {
655         tx += "Failures:\n\n";
656         for (var url in this.pagesByURL) {
657             var page = this.pagesByURL[url];
658             var pageTotalFail = page.totalTests - page.totalSuccessful - page.totalSkipped;
659             if (!(page.totalTests == 0 && page.totalTimeouts == 0) &&
660                 pageTotalFail > 0)
661             {
662             tx += url + ": " + pageTotalFail + " tests failed";
663             if (page.totalTimeouts)
664                 tx += " (" + page.totalTimeouts + " timed out)";
665             tx += "\n";
666             }
667         }
668       } else {
669         tx += "All tests PASSED\n\n";
670       }
671       tx += "\n";
672       tx += "-------------------\n\n";
673       tx += "Complete Test Results (total / pass / fail / timeout / skipped):\n\n";
674       for (var url in this.pagesByURL) {
675         var page = this.pagesByURL[url];
676         var pageTotalFail = page.totalTests - page.totalSuccessful - page.totalSkipped;
677         if (!(page.totalTests == 0 && page.totalTimeouts == 0)) {
678           tx += url + ": " + page.totalTests + " / " +
679               page.totalSuccessful + " / " + pageTotalFail + " / " + page.totalTimeouts + " / " + page.totalSkipped + "\n";
680         }
681       }
682       tx += "\n";
683       tx += "-------------------\n\n";
684       tx += "Generated on: " + (new Date()).toString() + "\n";
685
686       var r = document.getElementById("testResultsAsText");
687       while (r.firstChild) r.removeChild(r.firstChild);
688       r.appendChild(document.createTextNode(tx));
689       document.getElementById("showTextSummary").style.visibility = "visible";
690
691       this.postResultsToServer(tx);
692     } else {
693       var e = document.getElementById("error");
694       e.innerHTML = msg;
695       this.postResultsToServer(msg);
696     }
697   };
698
699   Reporter.prototype.postTestStartToServer = function(resultText) {
700     if(OPTIONS.postResults == undefined || OPTIONS.postResults == 0) {
701       return;
702     }
703
704     var xhr = new XMLHttpRequest();
705     xhr.open('POST', "/start", true);
706     xhr.send(null);
707   };
708
709   Reporter.prototype.postResultsToServer = function(resultText) {
710     if(OPTIONS.postResults == undefined || OPTIONS.postResults == 0) {
711       return;
712     }
713
714     var xhr = new XMLHttpRequest();
715     xhr.open('POST', "/finish", true);
716     xhr.setRequestHeader("Content-Type", "text/plain");
717     xhr.send(resultText);
718   };
719
720   Reporter.prototype.ready = function() {
721     var loading = document.getElementById("loading");
722     loading.style.display = "none";
723     if (!this.noSelectedWebGLVersion) {
724       var button = document.getElementById("runTestsButton");
725       button.disabled = false;
726       this.executeListenerEvents_("ready");
727     }
728   };
729
730   Reporter.prototype.reportFunc = function(type, url, msg, success, skipped) {
731     switch (type) {
732       case reportType.ADD_PAGE:
733         return this.addPage(msg);
734       case reportType.READY:
735         return this.ready();
736       case reportType.START_PAGE:
737         return this.startPage(url);
738       case reportType.TEST_RESULT:
739         return this.addResult(url, msg, success, skipped);
740       case reportType.FINISH_PAGE:
741         return this.finishPage(url, success);
742       case reportType.FINISHED_ALL_TESTS:
743         return this.displayFinalResults(msg, success);
744       default:
745         throw 'unhandled';
746         break;
747     };
748   };
749
750   var getURLOptions = function(obj) {
751     var s = window.location.href;
752     var q = s.indexOf("?");
753     var e = s.indexOf("#");
754     if (e < 0) {
755       e = s.length;
756     }
757     var query = s.substring(q + 1, e);
758     var pairs = query.split("&");
759     for (var ii = 0; ii < pairs.length; ++ii) {
760       var keyValue = pairs[ii].split("=");
761       var key = keyValue[0];
762       var value = decodeURIComponent(keyValue[1]);
763       obj[key] = value;
764     }
765   };
766
767   getURLOptions(OPTIONS);
768
769   var makeVersionSelect = function(currentVersion) {
770     var versionSelect = document.getElementById("testVersion");
771     var foundCurrentVersion = false;
772     var numericCurrentVersion = currentVersion.replace(/[^\d.]/g, '');
773
774     for (var i in testVersions) {
775       var version = testVersions[i];
776       var numericVersion = version.replace(/[^\d.]/g, '');
777       var option = document.createElement("option");
778       option.setAttribute('value', numericVersion);
779       option.innerHTML = version;
780
781       if (numericVersion == numericCurrentVersion) {
782         foundCurrentVersion = true;
783         option.selected = true;
784       }
785
786       versionSelect.appendChild(option);
787     }
788
789     // If the version requested by the query string isn't in the list add it.
790     if (!foundCurrentVersion) {
791       var option = document.createElement("option");
792       option.setAttribute('value', numericCurrentVersion);
793       option.innerHTML = currentVersion + " (unknown)";
794       option.selected = true;
795
796       versionSelect.appendChild(option);
797     }
798
799     versionSelect.addEventListener('change', function(ev) {
800       window.location.href = "?version=" + versionSelect.value;
801     }, false);
802   }
803
804   makeVersionSelect(OPTIONS.version);
805
806   // Make iframes
807   var makeIFrames = function() {
808     var toparea = document.getElementById("toparea");
809     var frame = document.getElementById("frames");
810     var areaWidth = Math.max(100, toparea.clientWidth - 300);
811     var areaHeight = Math.max(100, frame.clientHeight);
812
813     var numCells = OPTIONS.frames;
814
815     var gridWidth = Math.max(1, Math.ceil(Math.sqrt(numCells)));
816     var gridHeight = gridWidth;
817     var bestAspect = 99999;
818     var bestNumEmptyCells = 99999;
819     var bestNumEmptyCellsColumns = 0;
820     var bestNumEmptyCellsAspect = 99999;
821     var minGoodAspect = 1 / 3;
822     var maxGoodAspect = 3 / 1;
823
824     for (var columns = 1; columns <= numCells; ++columns) {
825         var rows = Math.ceil(numCells / columns);
826         var cellWidth = areaWidth / columns;
827         var cellHeight = areaHeight / rows;
828         var cellAspect = cellWidth / cellHeight;
829         if (cellAspect >= minGoodAspect && cellAspect <= maxGoodAspect) {
830             var numEmptyCells = columns * rows - numCells;
831             // Keep the one with the least number of empty cells.
832             if (numEmptyCells < bestNumEmptyCells) {
833                 bestNumEmptyCells = numEmptyCells;
834                 bestNumEmptyCellsColumns = columns;
835                 bestNumEmptyCellsAspect = cellAspect;
836             // If it's the same number of empty cells keep the one
837             // with the best aspect.
838             } else if (numEmptyCells == bestNumEmptyCells &&
839                   Math.abs(cellAspect - 1) <
840                   Math.abs(bestNumEmptyCellsAspect - 1)) {
841                 bestNumEmptyCellsColumns = columns;
842                 bestNumEmptyCellsAspect = cellAspect;
843             }
844         }
845         if (Math.abs(cellAspect - 1) < Math.abs(bestAspect - 1)) {
846             gridWidth = columns;
847             gridHeight = rows;
848             bestAspect = cellAspect;
849         }
850     }
851
852     // if we found an aspect with few empty cells use that.
853     var numEmptyCells = gridWidth * gridHeight - numCells;
854     if (bestNumEmptyCellsColumns && bestNumEmptyCells < numEmptyCells) {
855         gridWidth = bestNumEmptyCellsColumns;
856         gridHeight = Math.ceil(numCells / gridWidth);
857     }
858
859     var table = document.createElement("table");
860     table.style.height = areaHeight + "px";
861     var tbody = document.createElement("tbody");
862     var iframes = [];
863     for (var row = 0; row < gridHeight; ++row) {
864       var tr = document.createElement("tr");
865       for (var column = 0; column < gridWidth; ++column) {
866         var td = document.createElement("td");
867         if (numCells > 0) {
868           --numCells;
869           var iframe = document.createElement("iframe");
870           iframe.setAttribute("scrolling", "yes");
871           iframe.style.width = "100%";
872           iframe.style.height = "100%";
873           iframes.push(iframe);
874           td.appendChild(iframe);
875         }
876         tr.appendChild(td);
877       }
878       tbody.appendChild(tr);
879     }
880     table.appendChild(tbody);
881     frame.appendChild(table);
882     return iframes;
883   };
884   var iframes = makeIFrames();
885
886   var reporter = new Reporter(iframes);
887   var testHarness = new WebGLTestHarnessModule.TestHarness(
888       iframes,
889       '00_test_list.txt',
890       function(type, url, msg, success, skipped) {
891         return reporter.reportFunc(type, url, msg, success, skipped);
892       },
893       OPTIONS);
894   reporter.addEventListener("ready", function() {
895     // Set which tests to include.
896     if (OPTIONS.include) {
897       reporter.disableAllTests();
898       var includes = OPTIONS.include.split(",")
899       for (var ii = 0; ii < includes.length; ++ii) {
900         reporter.enableTest(new RegExp(includes[ii]));
901       }
902     }
903     // Remove tests based on skip=re1,re2 in URL.
904     if (OPTIONS.skip) {
905       var skips = OPTIONS.skip.split(",")
906       for (var ii = 0; ii < skips.length; ++ii) {
907         reporter.disableTest(new RegExp(skips[ii]));
908       }
909     }
910     // Auto run the tests if the run=1 in URL
911     if (OPTIONS.run != undefined && OPTIONS.run != 0) {
912       reporter.postTestStartToServer();
913       testHarness.runTests();
914     }
915   });
916   window.webglTestHarness = testHarness;
917   var button = document.getElementById("runTestsButton");
918   button.disabled = true;
919   button.onclick = function() {
920     autoScroll = autoScrollEnabled;
921     reporter.postTestStartToServer();
922     testHarness.runTests();
923   };
924   var autoScrollCheckbox = document.getElementById("autoScrollCheckbox");
925   autoScrollCheckbox.checked = autoScrollEnabled;
926   autoScrollCheckbox.onclick = function() {
927     autoScrollEnabled = autoScrollCheckbox.checked;
928     autoScroll = autoScrollEnabled;
929   };
930   var textbutton = document.getElementById("showTextSummary");
931   textbutton.onclick = function() {
932     log("click");
933     var htmldiv = document.getElementById("testResultsHTML");
934     var textdiv = document.getElementById("testResultsText");
935     if (textdiv.style.display == "none") {
936       textdiv.style.display = "block";
937       htmldiv.style.display = "none";
938       textbutton.setAttribute("value", "display html summary");
939     } else {
940       textdiv.style.display = "none";
941       htmldiv.style.display = "block";
942       textbutton.setAttribute("value", "display text summary");
943     }
944   };
945   if (reporter.noSelectedWebGLVersion) {
946     button.disabled = true;
947   }
948   if (reporter.noWebGL) {
949     var elem = document.getElementById("nowebgl");
950     elem.style.display = "";
951     reporter.postResultsToServer("Browser does not appear to support WebGL");
952   } else if (reporter.noSelectedWebGLVersion) {
953     var elem = document.getElementById("noselectedwebgl");
954     elem.style.display = "";
955     reporter.postResultsToServer("Browser does not appear to support the selected version of WebGL");
956   }
957 }
958 </script>
959 </head>
960 <body onload="start()">
961
962 <div id="testlist">
963
964         <div id="testResultsHTML">
965           <ul id="results">
966           </ul>
967         </div>
968         <div style="display: none;" id="testResultsText">
969           <pre id="testResultsAsText"></pre>
970         </div>
971
972 </div> <!-- end of container -->
973
974 <div id="header">
975
976 <table>
977   <tr style="height: 300px;">
978     <td>
979       <table id="toparea">
980         <tr>
981           <td style="width: 300px">
982             <div id="info">
983               <img src="resources/webgl-logo.png" /><br />
984               WebGL Conformance Test Runner<br/>
985               Version 
986               <select id="testVersion">
987               </select>
988               <br/>
989               <a href="../../conformance-suites/"><i>(click here for previous versions)</i></a>
990               <br/>
991               <input type="button" value="run tests" id="runTestsButton"/>
992               <br/>
993               <input type="checkbox" id="autoScrollCheckbox"/>
994               <label for="autoScrollCheckbox">auto scroll</label>
995               <br/>
996               <input type="button" style="visibility: hidden;" value="display text summary" id="showTextSummary"/>
997               <div id="nowebgl" class="nowebgl" style="display: none;">
998                 This browser does not appear to support WebGL
999               </div>
1000               <div id="noselectedwebgl" class="nowebgl" style="display: none;">
1001                 This browser does not appear to support the selected version of WebGL
1002               </div>
1003             </div>
1004           </td>
1005         </tr>
1006         <tr>
1007           <td>
1008             <div id="loading">
1009               Loading Tests...
1010             </div>
1011             <div>
1012               Results:
1013               <span id="fullresults">
1014               </span>
1015             </div>
1016           </td>
1017         </tr>
1018         <tr>
1019           <td>
1020             <div id="error-wrap">
1021               <pre id="error"></pre>
1022             </div>
1023           </td>
1024         </tr>
1025       </table>
1026     </td>
1027     <td id="frames"></td>
1028   </tr>
1029 </table>
1030 </div> <!-- end of header -->
1031
1032 </body>
1033 </html>