Upstream version 6.35.121.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.1",
173   "1.0.2",
174   "1.0.3 (beta)",
175   "2.0.0 (beta)"
176 ];
177
178 function start() {
179
180   function log(msg) {
181     if (window.console && window.console.log) {
182       window.console.log(msg);
183     }
184   }
185
186   function create3DContext(canvas, attrs, version) {
187     if (!canvas) {
188       canvas = document.createElement("canvas");
189     }
190     var context = null;
191     var names;
192     switch (version) {
193       case 2:
194         names = ["webgl2", "experimental-webgl2"]; break;
195       default:
196         names = ["webgl", "experimental-webgl"]; break;
197     }
198     for (var i = 0; i < names.length; ++i) {
199       try {
200         context = canvas.getContext(names[i], attrs);
201       } catch (e) {
202       }
203       if (context) {
204         break;
205       }
206     }
207     return context;
208   }
209
210   var reportType = WebGLTestHarnessModule.TestHarness.reportType;
211   var pageCount = 0;
212   var folderCount = 0;
213   var autoScrollEnabled = true; // Whether the user prefers to auto scroll
214   var autoScroll = true; // Whether auto scroll is actually performed
215
216   var Page = function(reporter, folder, testIndex, url) {
217     this.reporter = reporter;
218     this.folder = folder;
219     this.url = url;
220     this.totalTests = 0;
221     this.totalSuccessful = 0;
222     this.totalTimeouts = 0;
223     this.totalSkipped = 0;
224     this.testIndex = testIndex;
225
226     this.elementId = "page" + pageCount++;
227     var li = reporter.localDoc.createElement('li');
228     li.id = this.elementId;
229     var div = reporter.localDoc.createElement('div');
230     div.classList.add('pageHeader');
231     var check = reporter.localDoc.createElement('input');
232     check.type = 'checkbox';
233     check.checked = true;
234     div.appendChild(check);
235     var button = reporter.localDoc.createElement('input');
236     button.type = 'button';
237     button.value = 'run';
238     button.onclick = function() {
239       autoScroll = false;
240       reporter.runTest(url);
241     };
242     if (reporter.noWebGL) {
243       button.disabled = true;
244     }
245     div.appendChild(button);
246     var a = reporter.localDoc.createElement('a');
247     a.href = url;
248     a.target = "_blank";
249     var node = reporter.localDoc.createTextNode(url);
250     a.appendChild(node);
251     div.appendChild(a);
252     li.setAttribute('class', 'testpage');
253     li.appendChild(div);
254     var ul = reporter.localDoc.createElement('ul');
255     var node = reporter.localDoc.createTextNode('');
256     li.appendChild(ul);
257     div.appendChild(node);
258     this.totalsElem = node;
259     this.resultElem = ul;
260     this.elem = li;
261     this.check = check;
262   };
263
264   Page.prototype.addResult = function(msg, success, skipped) {
265     ++this.totalTests;
266     if (success === undefined) {
267       ++this.totalTimeouts;
268       var result = "timeout";
269       var css = "timeout";
270     } else if (success) {
271       if(skipped) {
272         ++this.totalSkipped;
273       } else {
274         ++this.totalSuccessful;
275       }
276       // don't report success.
277       return;
278     } else {
279       var result = "failed";
280       var css = "fail";
281     }
282
283     var node = this.reporter.localDoc.createTextNode(result + ': ' + msg);
284     var li = this.reporter.localDoc.createElement('li');
285     li.appendChild(node);
286     li.setAttribute('class', css);
287     this.resultElem.appendChild(li);
288   };
289
290   Page.prototype.startPage = function() {
291     if (autoScroll && this.elem.scrollIntoView) {
292       this.elem.scrollIntoView(false);
293     }
294     this.totalTests = 0;
295     this.totalSuccessful = 0;
296     this.totalTimeouts = 0;
297     // remove previous results.
298     while (this.resultElem.hasChildNodes()) {
299       this.resultElem.removeChild(this.resultElem.childNodes[0]);
300     }
301     this.totalsElem.textContent = '';
302
303     var shouldRun = this.check.checked && this.folder.checked();
304
305     if (shouldRun) {
306       this.elem.classList.remove('testpagetimeout');
307       this.elem.classList.remove('testpageskipped');
308       this.elem.classList.remove('testpagefail');
309       this.elem.classList.remove('testpagesuccess');
310     }
311
312     return this.check.checked && this.folder.checked();
313   };
314
315   Page.prototype.firstTestIndex = function() {
316     return this.testIndex;
317   };
318
319   Page.prototype.finishPage = function(success) {
320     if(this.totalSkipped) {
321       var msg = ' (' + this.totalSkipped + ' of ' + this.totalTests + ' skipped)';
322     } else {
323       var msg = ' (' + this.totalSuccessful + ' of ' + this.totalTests + ' passed)';
324     }
325
326     if (success === undefined) {
327       var css = 'testpagetimeout';
328       msg = '(*timeout*)';
329       ++this.totalTests;
330       ++this.totalTimeouts;
331     } else if (this.totalSkipped) {
332       var css = 'testpageskipped';
333     } else if (this.totalSuccessful != this.totalTests) {
334       var css = 'testpagefail';
335     } else {
336       var css = 'testpagesuccess';
337     }
338     this.elem.classList.add(css);
339     this.totalsElem.textContent = msg;
340   };
341
342   Page.prototype.enableTest = function(re) {
343     if (this.url.match(re)) {
344       this.check.checked = true;
345       this.folder.enableUp_();
346     }
347   };
348
349   Page.prototype.disableTest = function(re) {
350     if (this.url.match(re)) {
351       this.check.checked = false;
352     }
353   };
354
355   var Folder = function(reporter, folder, depth, opt_name) {
356     this.reporter = reporter;
357     this.depth = depth;
358     this.name = opt_name || "";
359     this.displayName = this.name;
360     if (folder && folder.displayName) {
361       this.displayName = folder.displayName + '/' + this.displayName;
362     }
363     this.subFolders = {};
364     this.pages = [];
365     this.items = [];
366     this.folder = folder;
367     var that = this;
368
369     var doc = reporter.localDoc;
370     this.elementId = "folder" + folderCount++;
371     var li = doc.createElement('li');
372     li.id = this.elementId;
373     li.classList.add("folder");
374     var div = doc.createElement('div');
375     div.classList.add('folderHeader');
376     var check = doc.createElement('input');
377     check.type = 'checkbox';
378     check.checked = true;
379     div.appendChild(check);
380     var button = doc.createElement('input');
381     button.type = 'button';
382     button.value = 'run';
383     button.onclick = function() {
384       autoScroll = autoScrollEnabled;
385       that.run();
386     };
387     if (reporter.noWebGL) {
388       button.disabled = true;
389     }
390     div.appendChild(button);
391     var h = doc.createElement('span');
392     h.classList.add('folderName');
393     h.appendChild(doc.createTextNode(this.displayName));
394     div.appendChild(h);
395     var ul = doc.createElement('ul');
396     li.appendChild(div);
397     li.appendChild(ul);
398     this.childUL = ul;
399     this.elem = li;
400     this.check = check;
401     this.folderHeader = div;
402   };
403
404   Folder.prototype.checked = function() {
405     return this.check.checked &&
406         (this.folder ? this.folder.checked() : true);
407   };
408
409   Folder.prototype.firstTestIndex = function() {
410     return this.items[0].firstTestIndex();
411   };
412
413   Folder.prototype.numChildren = function() {
414     var numChildren = 0;
415     for (var name in this.subFolders) {
416       numChildren += this.subFolders[name].numChildren();
417     }
418     return numChildren + this.pages.length;
419   };
420
421   Folder.prototype.run = function() {
422     var firstTestIndex = this.firstTestIndex();
423     var count = this.numChildren();
424     log("run tests: " + firstTestIndex + " to " + (firstTestIndex + count - 1))
425     testHarness.runTests({start: firstTestIndex, count: count});
426   };
427
428   Folder.prototype.getSubFolder = function(name) {
429     var subFolder = this.subFolders[name];
430     if (subFolder === undefined) {
431       subFolder = new Folder(this.reporter, this, this.depth + 1, name);
432       this.subFolders[name] = subFolder;
433       this.items.push(subFolder);
434       this.childUL.appendChild(subFolder.elem);
435     }
436     return subFolder;
437   };
438
439   Folder.prototype.getOrCreateFolder = function(url) {
440     var parts = url.split('/');
441     var folder = this;
442     for (var pp = 0; pp < parts.length - 1; ++pp) {
443       folder = folder.getSubFolder(parts[pp]);
444     }
445     return folder;
446   };
447
448   Folder.prototype.addPage = function(page) {
449     this.pages.push(page);
450     this.items.push(page);
451     this.childUL.appendChild(page.elem);
452     this.folderHeader.classList.add('hasPages');
453   };
454
455   Folder.prototype.disableTest = function(re, opt_forceRecurse) {
456     var recurse = true;
457     if (this.name.match(re)) {
458       this.check.checked = false;
459       recurse = opt_forceRecurse;
460     }
461     if (recurse) {
462       for (var name in this.subFolders) {
463         this.subFolders[name].disableTest(re, opt_forceRecurse);
464       }
465       for (var ii = 0; ii < this.pages.length; ++ii) {
466         this.pages[ii].disableTest(re);
467       }
468     }
469   };
470
471   Folder.prototype.enableUp_ = function() {
472     this.check.checked = true;
473     var parent = this.folder;
474     if (parent) {
475       parent.enableUp_();
476     }
477   }
478
479   Folder.prototype.enableTest = function(re) {
480     if (this.name.match(re)) {
481       this.enableUp_();
482     }
483     for (var name in this.subFolders) {
484       this.subFolders[name].enableTest(re);
485     }
486     for (var ii = 0; ii < this.pages.length; ++ii) {
487       this.pages[ii].enableTest(re);
488     }
489   };
490
491   var Reporter = function(iframes) {
492     this.localDoc = document;
493     this.resultElem = document.getElementById("results");
494     this.fullResultsElem = document.getElementById("fullresults");
495     var node = this.localDoc.createTextNode('');
496     this.fullResultsElem.appendChild(node);
497     this.fullResultsNode = node;
498     this.iframes = iframes;
499     this.currentPageElem = null;
500     this.totalPages = 0;
501     this.pagesByURL = {};
502
503     // Check to see if WebGL is supported
504     var canvas = document.createElement("canvas");
505     var ctx = create3DContext(canvas, null, 1);
506     this.noWebGL = !ctx;
507
508     // Check to see if WebGL2 is supported
509     this.noWebGL2 = true;
510     var canvas2 = document.createElement("canvas");
511     var ctx2 = create3DContext(canvas2, null, 2);
512
513     // If the WebGL2 context could be created use it instead
514     if (ctx2) {
515       this.noWebGL2 = false;
516       ctx = ctx2;
517     }
518
519     this.contextInfo = {};
520     this.root = new Folder(this, null, 0, "all");
521     this.resultElem.appendChild(this.root.elem);
522     this.callbacks = { };
523
524     if (ctx) {
525       this.contextInfo["VENDOR"] = ctx.getParameter(ctx.VENDOR);
526       this.contextInfo["VERSION"] = ctx.getParameter(ctx.VERSION);
527       this.contextInfo["RENDERER"] = ctx.getParameter(ctx.RENDERER);
528       this.contextInfo["RED_BITS"] = ctx.getParameter(ctx.RED_BITS);
529       this.contextInfo["GREEN_BITS"] = ctx.getParameter(ctx.GREEN_BITS);
530       this.contextInfo["BLUE_BITS"] = ctx.getParameter(ctx.BLUE_BITS);
531       this.contextInfo["ALPHA_BITS"] = ctx.getParameter(ctx.ALPHA_BITS);
532       this.contextInfo["DEPTH_BITS"] = ctx.getParameter(ctx.DEPTH_BITS);
533       this.contextInfo["STENCIL_BITS"] = ctx.getParameter(ctx.STENCIL_BITS);
534
535       var ext = ctx.getExtension("WEBGL_debug_renderer_info");
536       if (ext) {
537         this.contextInfo["UNMASKED_VENDOR"] = ctx.getParameter(ext.UNMASKED_VENDOR_WEBGL);
538         this.contextInfo["UNMASKED_RENDERER"] = ctx.getParameter(ext.UNMASKED_RENDERER_WEBGL);
539       }
540     }
541   };
542
543   Reporter.prototype.enableTest = function(name) {
544     this.root.enableTest(name);
545   };
546
547   Reporter.prototype.disableTest = function(name) {
548     this.root.disableTest(name);
549   };
550
551   Reporter.prototype.disableAllTests = function() {
552     this.root.disableTest(".*", true);
553   };
554
555   Reporter.prototype.addEventListener = function(type, func) {
556     if (!this.callbacks[type]) {
557       this.callbacks[type] = [];
558     }
559     this.callbacks[type].push(func);
560   };
561
562   Reporter.prototype.executeListenerEvents_ = function(type) {
563     var callbacks = this.callbacks[type].slice(0);
564     for (var ii = 0; ii < callbacks.length; ++ii) {
565       setTimeout(callbacks[ii], 0);
566     }
567   };
568
569   Reporter.prototype.runTest = function(url) {
570     var page = this.pagesByURL[url];
571     testHarness.runTests({start: page.firstTestIndex(), count: 1});
572   };
573
574   Reporter.prototype.getFolder = function(url) {
575     return this.root.getOrCreateFolder(url);
576   };
577
578   Reporter.prototype.addPage = function(url) {
579     var folder = this.getFolder(url);
580     var page = new Page(this, folder, this.totalPages, url);
581     folder.addPage(page);
582     ++this.totalPages;
583     this.pagesByURL[url] = page;
584   };
585
586   Reporter.prototype.startPage = function(url) {
587     var page = this.pagesByURL[url];
588     return page.startPage();
589   };
590
591   Reporter.prototype.addResult = function(url, msg, success, skipped) {
592     var page = this.pagesByURL[url];
593     page.addResult(msg, success, skipped);
594   };
595
596   Reporter.prototype.finishPage = function(url, success) {
597     var page = this.pagesByURL[url];
598     page.finishPage(success);
599   };
600
601   Reporter.prototype.displayFinalResults = function(msg, success) {
602     if (success) {
603       var totalTests = 0;
604       var totalSuccessful = 0;
605       var totalTimeouts = 0;
606       var totalSkipped = 0;
607       for (var url in this.pagesByURL) {
608         var page = this.pagesByURL[url];
609         totalTests += page.totalTests;
610         totalSuccessful += page.totalSuccessful;
611         totalTimeouts += page.totalTimeouts;
612         totalSkipped += page.totalSkipped;
613       }
614       var timeout = '';
615       if (totalTimeouts > 0) {
616         timeout = ', ' + totalTimeouts + ' timed out';
617       }
618       var msg = ' (' + totalSuccessful + ' of ' +
619                 totalTests + ' passed' + timeout + ')';
620       this.fullResultsNode.textContent = msg;
621
622       // generate a text summary
623       var tx = "";
624       tx += "WebGL Conformance Test Results\n";
625       tx += "Subset: Version " + OPTIONS.version + "\n";
626       tx += "\n";
627       tx += "-------------------\n\n";
628       tx += "User Agent: " + (navigator.userAgent ? navigator.userAgent : "(navigator.userAgent is null)") + "\n";
629       tx += "WebGL VENDOR: " + this.contextInfo["VENDOR"] + "\n";
630       tx += "WebGL VERSION: " + this.contextInfo["VERSION"] + "\n";
631       tx += "WebGL RENDERER: " + this.contextInfo["RENDERER"] + "\n";
632       tx += "Unmasked VENDOR: " + this.contextInfo["UNMASKED_VENDOR"] + "\n";
633       tx += "Unmasked RENDERER: " + this.contextInfo["UNMASKED_RENDERER"] + "\n";
634       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";
635       tx += "\n";
636       tx += "-------------------\n\n";
637       tx += "Test Summary (" + totalTests + " total tests):\n";
638       tx += "Tests PASSED: " + totalSuccessful + "\n";
639       tx += "Tests FAILED: " + (totalTests - totalSuccessful - totalSkipped) + "\n";
640       tx += "Tests TIMED OUT: " + totalTimeouts + "\n";
641       tx += "Tests SKIPPED: " + totalSkipped + "\n";
642       tx += "\n";
643       tx += "-------------------\n\n";
644       if (totalSuccessful < totalTests) {
645         tx += "Failures:\n\n";
646         for (var url in this.pagesByURL) {
647             var page = this.pagesByURL[url];
648             var pageTotalFail = page.totalTests - page.totalSuccessful - page.totalSkipped;
649             if (!(page.totalTests == 0 && page.totalTimeouts == 0) &&
650                 pageTotalFail > 0)
651             {
652             tx += url + ": " + pageTotalFail + " tests failed";
653             if (page.totalTimeouts)
654                 tx += " (" + page.totalTimeouts + " timed out)";
655             tx += "\n";
656             }
657         }
658       } else {
659         tx += "All tests PASSED\n\n";
660       }
661       tx += "\n";
662       tx += "-------------------\n\n";
663       tx += "Complete Test Results (total / pass / fail / timeout / skipped):\n\n";
664       for (var url in this.pagesByURL) {
665         var page = this.pagesByURL[url];
666         var pageTotalFail = page.totalTests - page.totalSuccessful - page.totalSkipped;
667         if (!(page.totalTests == 0 && page.totalTimeouts == 0)) {
668           tx += url + ": " + page.totalTests + " / " +
669               page.totalSuccessful + " / " + pageTotalFail + " / " + page.totalTimeouts + " / " + page.totalSkipped + "\n";
670         }
671       }
672       tx += "\n";
673       tx += "-------------------\n\n";
674       tx += "Generated on: " + (new Date()).toString() + "\n";
675
676       var r = document.getElementById("testResultsAsText");
677       while (r.firstChild) r.removeChild(r.firstChild);
678       r.appendChild(document.createTextNode(tx));
679       document.getElementById("showTextSummary").style.visibility = "visible";
680
681       this.postResultsToServer(tx);
682     } else {
683       var e = document.getElementById("error");
684       e.innerHTML = msg;
685       this.postResultsToServer(msg);
686     }
687   };
688
689   Reporter.prototype.postTestStartToServer = function(resultText) {
690     if(OPTIONS.postResults == undefined || OPTIONS.postResults == 0) {
691       return;
692     }
693
694     var xhr = new XMLHttpRequest();
695     xhr.open('POST', "/start", true);
696     xhr.send(null);
697   };
698
699   Reporter.prototype.postResultsToServer = function(resultText) {
700     if(OPTIONS.postResults == undefined || OPTIONS.postResults == 0) {
701       return;
702     }
703
704     var xhr = new XMLHttpRequest();
705     xhr.open('POST', "/finish", true);
706     xhr.setRequestHeader("Content-Type", "text/plain");
707     xhr.send(resultText);
708   };
709
710   Reporter.prototype.ready = function() {
711     var loading = document.getElementById("loading");
712     loading.style.display = "none";
713     if (!this.noWebGL) {
714       var button = document.getElementById("runTestsButton");
715       button.disabled = false;
716       this.executeListenerEvents_("ready");
717     }
718   };
719
720   Reporter.prototype.reportFunc = function(type, url, msg, success, skipped) {
721     switch (type) {
722       case reportType.ADD_PAGE:
723         return this.addPage(msg);
724       case reportType.READY:
725         return this.ready();
726       case reportType.START_PAGE:
727         return this.startPage(url);
728       case reportType.TEST_RESULT:
729         return this.addResult(url, msg, success, skipped);
730       case reportType.FINISH_PAGE:
731         return this.finishPage(url, success);
732       case reportType.FINISHED_ALL_TESTS:
733         return this.displayFinalResults(msg, success);
734       default:
735         throw 'unhandled';
736         break;
737     };
738   };
739
740   var getURLOptions = function(obj) {
741     var s = window.location.href;
742     var q = s.indexOf("?");
743     var e = s.indexOf("#");
744     if (e < 0) {
745       e = s.length;
746     }
747     var query = s.substring(q + 1, e);
748     var pairs = query.split("&");
749     for (var ii = 0; ii < pairs.length; ++ii) {
750       var keyValue = pairs[ii].split("=");
751       var key = keyValue[0];
752       var value = decodeURIComponent(keyValue[1]);
753       obj[key] = value;
754     }
755   };
756
757   getURLOptions(OPTIONS);
758
759   var makeVersionSelect = function(currentVersion) {
760     var versionSelect = document.getElementById("testVersion");
761     var foundCurrentVersion = false;
762     var numericCurrentVersion = currentVersion.replace(/[^\d.]/g, '');
763
764     for (var i in testVersions) {
765       var version = testVersions[i];
766       var numericVersion = version.replace(/[^\d.]/g, '');
767       var option = document.createElement("option");
768       option.setAttribute('value', numericVersion);
769       option.innerHTML = version;
770
771       if (numericVersion == numericCurrentVersion) {
772         foundCurrentVersion = true;
773         option.selected = true;
774       }
775
776       versionSelect.appendChild(option);
777     }
778
779     // If the version requested by the query string isn't in the list add it.
780     if (!foundCurrentVersion) {
781       var option = document.createElement("option");
782       option.setAttribute('value', numericCurrentVersion);
783       option.innerHTML = currentVersion + " (unknown)";
784       option.selected = true;
785
786       versionSelect.appendChild(option);
787     }
788
789     versionSelect.addEventListener('change', function(ev) {
790       window.location.href = "?version=" + versionSelect.value;
791     }, false);
792   }
793
794   makeVersionSelect(OPTIONS.version);
795
796   // Make iframes
797   var makeIFrames = function() {
798     var toparea = document.getElementById("toparea");
799     var frame = document.getElementById("frames");
800     var areaWidth = Math.max(100, toparea.clientWidth - 300);
801     var areaHeight = Math.max(100, frame.clientHeight);
802
803     var numCells = OPTIONS.frames;
804
805     var gridWidth = Math.max(1, Math.ceil(Math.sqrt(numCells)));
806     var gridHeight = gridWidth;
807     var bestAspect = 99999;
808     var bestNumEmptyCells = 99999;
809     var bestNumEmptyCellsColumns = 0;
810     var bestNumEmptyCellsAspect = 99999;
811     var minGoodAspect = 1 / 3;
812     var maxGoodAspect = 3 / 1;
813
814     for (var columns = 1; columns <= numCells; ++columns) {
815         var rows = Math.ceil(numCells / columns);
816         var cellWidth = areaWidth / columns;
817         var cellHeight = areaHeight / rows;
818         var cellAspect = cellWidth / cellHeight;
819         if (cellAspect >= minGoodAspect && cellAspect <= maxGoodAspect) {
820             var numEmptyCells = columns * rows - numCells;
821             // Keep the one with the least number of empty cells.
822             if (numEmptyCells < bestNumEmptyCells) {
823                 bestNumEmptyCells = numEmptyCells;
824                 bestNumEmptyCellsColumns = columns;
825                 bestNumEmptyCellsAspect = cellAspect;
826             // If it's the same number of empty cells keep the one
827             // with the best aspect.
828             } else if (numEmptyCells == bestNumEmptyCells &&
829                   Math.abs(cellAspect - 1) <
830                   Math.abs(bestNumEmptyCellsAspect - 1)) {
831                 bestNumEmptyCellsColumns = columns;
832                 bestNumEmptyCellsAspect = cellAspect;
833             }
834         }
835         if (Math.abs(cellAspect - 1) < Math.abs(bestAspect - 1)) {
836             gridWidth = columns;
837             gridHeight = rows;
838             bestAspect = cellAspect;
839         }
840     }
841
842     // if we found an aspect with few empty cells use that.
843     var numEmptyCells = gridWidth * gridHeight - numCells;
844     if (bestNumEmptyCellsColumns && bestNumEmptyCells < numEmptyCells) {
845         gridWidth = bestNumEmptyCellsColumns;
846         gridHeight = Math.ceil(numCells / gridWidth);
847     }
848
849     var table = document.createElement("table");
850     table.style.height = areaHeight + "px";
851     var tbody = document.createElement("tbody");
852     var iframes = [];
853     for (var row = 0; row < gridHeight; ++row) {
854       var tr = document.createElement("tr");
855       for (var column = 0; column < gridWidth; ++column) {
856         var td = document.createElement("td");
857         if (numCells > 0) {
858           --numCells;
859           var iframe = document.createElement("iframe");
860           iframe.setAttribute("scrolling", "yes");
861           iframe.style.width = "100%";
862           iframe.style.height = "100%";
863           iframes.push(iframe);
864           td.appendChild(iframe);
865         }
866         tr.appendChild(td);
867       }
868       tbody.appendChild(tr);
869     }
870     table.appendChild(tbody);
871     frame.appendChild(table);
872     return iframes;
873   };
874   var iframes = makeIFrames();
875
876   var reporter = new Reporter(iframes);
877   var testHarness = new WebGLTestHarnessModule.TestHarness(
878       iframes,
879       '00_test_list.txt',
880       function(type, url, msg, success, skipped) {
881         return reporter.reportFunc(type, url, msg, success, skipped);
882       },
883       OPTIONS);
884   reporter.addEventListener("ready", function() {
885     // Set which tests to include.
886     if (OPTIONS.include) {
887       reporter.disableAllTests();
888       var includes = OPTIONS.include.split(",")
889       for (var ii = 0; ii < includes.length; ++ii) {
890         reporter.enableTest(new RegExp(includes[ii]));
891       }
892     }
893     // Remove tests based on skip=re1,re2 in URL.
894     if (OPTIONS.skip) {
895       var skips = OPTIONS.skip.split(",")
896       for (var ii = 0; ii < skips.length; ++ii) {
897         reporter.disableTest(new RegExp(skips[ii]));
898       }
899     }
900     // Auto run the tests if the run=1 in URL
901     if (OPTIONS.run != undefined && OPTIONS.run != 0) {
902       reporter.postTestStartToServer();
903       testHarness.runTests();
904     }
905   });
906   window.webglTestHarness = testHarness;
907   var button = document.getElementById("runTestsButton");
908   button.disabled = true;
909   button.onclick = function() {
910     autoScroll = autoScrollEnabled;
911     reporter.postTestStartToServer();
912     testHarness.runTests();
913   };
914   var autoScrollCheckbox = document.getElementById("autoScrollCheckbox");
915   autoScrollCheckbox.checked = autoScrollEnabled;
916   autoScrollCheckbox.onclick = function() {
917     autoScrollEnabled = autoScrollCheckbox.checked;
918     autoScroll = autoScrollEnabled;
919   };
920   var textbutton = document.getElementById("showTextSummary");
921   textbutton.onclick = function() {
922     log("click");
923     var htmldiv = document.getElementById("testResultsHTML");
924     var textdiv = document.getElementById("testResultsText");
925     if (textdiv.style.display == "none") {
926       textdiv.style.display = "block";
927       htmldiv.style.display = "none";
928       textbutton.setAttribute("value", "display html summary");
929     } else {
930       textdiv.style.display = "none";
931       htmldiv.style.display = "block";
932       textbutton.setAttribute("value", "display text summary");
933     }
934   };
935   if (reporter.noWebGL) {
936     button.disabled = true;
937     var elem = document.getElementById("nowebgl");
938     elem.style.display = "";
939     reporter.postResultsToServer("Browser does not appear to support WebGL");
940   }
941 }
942 </script>
943 </head>
944 <body onload="start()">
945
946 <div id="testlist">
947
948         <div id="testResultsHTML">
949           <ul id="results">
950           </ul>
951         </div>
952         <div style="display: none;" id="testResultsText">
953           <pre id="testResultsAsText"></pre>
954         </div>
955
956 </div> <!-- end of container -->
957
958 <div id="header">
959
960 <table>
961   <tr style="height: 300px;">
962     <td>
963       <table id="toparea">
964         <tr>
965           <td style="width: 300px">
966             <div id="info">
967               <img src="resources/webgl-logo.png" /><br />
968               WebGL Conformance Test Runner<br/>
969               Subset: Version 
970               <select id="testVersion">
971               </select>
972               <br/>
973               <a href="../../conformance-suites/"><i>(click here for previous versions)</i></a>
974               <br/>
975               <input type="button" value="run tests" id="runTestsButton"/>
976               <br/>
977               <input type="checkbox" id="autoScrollCheckbox"/>
978               <label for="autoScrollCheckbox">auto scroll</label>
979               <br/>
980               <input type="button" style="visibility: hidden;" value="display text summary" id="showTextSummary"/>
981               <div id="nowebgl" class="nowebgl" style="display: none;">
982                 This browser does not appear to support WebGL
983               </div>
984             </div>
985           </td>
986         </tr>
987         <tr>
988           <td>
989             <div id="loading">
990               Loading Tests...
991             </div>
992             <div>
993               Results:
994               <span id="fullresults">
995               </span>
996             </div>
997           </td>
998         </tr>
999         <tr>
1000           <td>
1001             <div id="error-wrap">
1002               <pre id="error"></pre>
1003             </div>
1004           </td>
1005         </tr>
1006       </table>
1007     </td>
1008     <td id="frames"></td>
1009   </tr>
1010 </table>
1011 </div> <!-- end of header -->
1012
1013 </body>
1014 </html>