2 ** Copyright (c) 2012 The Khronos Group Inc.
4 ** Permission is hereby granted, free of charge, to any person obtaining a
5 ** copy of this software and/or associated documentation files (the
6 ** "Materials"), to deal in the Materials without restriction, including
7 ** without limitation the rights to use, copy, modify, merge, publish,
8 ** distribute, sublicense, and/or sell copies of the Materials, and to
9 ** permit persons to whom the Materials are furnished to do so, subject to
10 ** the following conditions:
12 ** The above copyright notice and this permission notice shall be included
13 ** in all copies or substantial portions of the Materials.
15 ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
23 GLSLConformanceTester = (function(){
25 var wtu = WebGLTestUtils;
26 var defaultVertexShader = [
27 "attribute vec4 vPosition;",
30 " gl_Position = vPosition;",
34 var defaultFragmentShader = [
35 "precision mediump float;",
38 " gl_FragColor = vec4(1.0,0.0,0.0,1.0);",
43 if (window.console && window.console.log) {
44 window.console.log(msg);
52 * vShaderSource: the source code for vertex shader
53 * vShaderSuccess: true if vertex shader compilation should
55 * fShaderSource: the source code for fragment shader
56 * fShaderSuccess: true if fragment shader compilation should
58 * linkSuccess: true of link should succeed
59 * passMsg: msg to describe success condition.
60 * render: if true render to unit quad. Green = success
63 function runOneTest(gl, info) {
64 var passMsg = info.passMsg
66 debug("test: " + passMsg);
68 var consoleDiv = document.getElementById("console");
70 if (info.vShaderSource === undefined) {
72 info.vShaderSource = document.getElementById(info.vShaderId).text;
74 info.vShader = 'defaultVertexShader';
75 info.vShaderSource = defaultVertexShader;
78 if (info.fShaderSource === undefined) {
80 info.fShaderSource = document.getElementById(info.fShaderId).text;
82 info.fShader = 'defaultFragmentShader';
83 info.fShaderSource = defaultFragmentShader;
87 var vLabel = (info.vShaderSource == defaultVertexShader ? "default" : "test") + " vertex shader";
88 var fLabel = (info.fShaderSource == defaultFragmentShader ? "default" : "test") + " fragment shader";
90 var vSource = info.vShaderPrep ? info.vShaderPrep(info.vShaderSource) :
93 wtu.addShaderSource(consoleDiv, vLabel, vSource);
95 // Reuse identical shaders so we test shared shader.
96 var vShader = vShaderDB[vSource];
98 vShader = wtu.loadShader(gl, vSource, gl.VERTEX_SHADER);
99 if (info.vShaderTest) {
100 if (!info.vShaderTest(vShader)) {
101 testFailed("[vertex shader test] " + passMsg);
105 // As per GLSL 1.0.17 10.27 we can only check for success on
106 // compileShader, not failure.
107 if (!info.ignoreResults && info.vShaderSuccess && !vShader) {
108 testFailed("[unexpected vertex shader compile status] (expected: " +
109 info.vShaderSuccess + ") " + passMsg);
111 // Save the shaders so we test shared shader.
113 vShaderDB[vSource] = vShader;
117 var debugShaders = gl.getExtension('WEBGL_debug_shaders');
118 if (debugShaders && vShader) {
119 wtu.addShaderSource(consoleDiv, vLabel + " translated for driver",
120 debugShaders.getTranslatedShaderSource(vShader));
123 var fSource = info.fShaderPrep ? info.fShaderPrep(info.fShaderSource) :
126 wtu.addShaderSource(consoleDiv, fLabel, fSource);
128 // Reuse identical shaders so we test shared shader.
129 var fShader = fShaderDB[fSource];
131 fShader = wtu.loadShader(gl, fSource, gl.FRAGMENT_SHADER);
132 if (info.fShaderTest) {
133 if (!info.fShaderTest(fShader)) {
134 testFailed("[fragment shader test] " + passMsg);
138 //debug(fShader == null ? "fail" : "succeed");
139 // As per GLSL 1.0.17 10.27 we can only check for success on
140 // compileShader, not failure.
141 if (!info.ignoreResults && info.fShaderSuccess && !fShader) {
142 testFailed("[unexpected fragment shader compile status] (expected: " +
143 info.fShaderSuccess + ") " + passMsg);
146 // Safe the shaders so we test shared shader.
148 fShaderDB[fSource] = fShader;
152 if (debugShaders && fShader) {
153 wtu.addShaderSource(consoleDiv, fLabel + " translated for driver",
154 debugShaders.getTranslatedShaderSource(fShader));
157 if (vShader && fShader) {
158 var program = gl.createProgram();
159 gl.attachShader(program, vShader);
160 gl.attachShader(program, fShader);
162 if (vSource.indexOf("vPosition") >= 0) {
163 gl.bindAttribLocation(program, 0, "vPosition");
165 if (vSource.indexOf("texCoord0") >= 0) {
166 gl.bindAttribLocation(program, 1, "texCoord0");
168 gl.linkProgram(program);
169 var linked = (gl.getProgramParameter(program, gl.LINK_STATUS) != 0);
171 var error = gl.getProgramInfoLog(program);
172 log("*** Error linking program '"+program+"':"+error);
174 if (!info.ignoreResults && linked != info.linkSuccess) {
175 testFailed("[unexpected link status] " + passMsg);
179 if (!info.ignoreResults && info.linkSuccess) {
180 testFailed("[link failed] " + passMsg);
190 gl.useProgram(program);
191 wtu.setupUnitQuad(gl);
192 wtu.clearAndDrawUnitQuad(gl);
194 var div = document.createElement("div");
195 div.className = "testimages";
196 wtu.insertImage(div, "result", wtu.makeImage(gl.canvas));
197 div.appendChild(document.createElement('br'));
198 consoleDiv.appendChild(div);
199 wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green", 0);
202 function runTests(shaderInfos) {
203 var wtu = WebGLTestUtils;
204 var canvas = document.createElement('canvas');
207 var gl = wtu.create3DContext(canvas);
209 testFailed("context does not exist");
215 var runNextTest = function() {
216 if (testIndex == shaderInfos.length) {
221 runOneTest(gl, shaderInfos[testIndex++]);
222 setTimeout(runNextTest, 1);
227 function loadExternalShaders(filename, passMsg) {
228 var shaderInfos = [];
229 var lines = wtu.readFileList(filename);
230 for (var ii = 0; ii < lines.length; ++ii) {
232 vShaderSource: defaultVertexShader,
233 vShaderSuccess: true,
234 fShaderSource: defaultFragmentShader,
235 fShaderSuccess: true,
239 var line = lines[ii];
240 var files = line.split(/ +/);
242 for (var jj = 0; jj < files.length; ++jj) {
243 var file = files[jj];
244 var shaderSource = wtu.readFile(file);
245 var firstLine = shaderSource.split("\n")[0];
246 var success = undefined;
247 if (firstLine.indexOf("fail") >= 0) {
249 } else if (firstLine.indexOf("succeed") >= 0) {
252 if (success === undefined) {
253 testFailed("bad first line in " + file + ":" + firstLine);
256 if (!wtu.startsWith(firstLine, "// ")) {
257 testFailed("bad first line in " + file + ":" + firstLine);
260 passMsg = passMsg + (passMsg.length ? ", " : "") + firstLine.substr(3);
261 if (wtu.endsWith(file, ".vert")) {
262 info.vShaderSource = shaderSource;
263 info.vShaderSuccess = success;
264 } else if (wtu.endsWith(file, ".frag")) {
265 info.fShaderSource = shaderSource;
266 info.fShaderSuccess = success;
269 info.linkSuccess = info.vShaderSuccess && info.fShaderSuccess;
270 info.passMsg = passMsg;
271 shaderInfos.push(info);
276 function getSource(elem) {
278 return str.replace(/^\s*/, '').replace(/\s*$/, '');
281 function getPassMessage(source) {
282 var lines = source.split('\n');
283 return lines[0].substring(3);
286 function getSuccess(msg) {
287 if (msg.indexOf("fail") >= 0) {
290 if (msg.indexOf("succeed") >= 0) {
293 testFailed("bad test description. Must have 'fail' or 'succeed'");
296 function setupTest() {
297 var vShaderElem = document.getElementById('vertexShader');
298 var vShaderSource = defaultVertexShader;
299 var vShaderSuccess = true;
301 var fShaderElem = document.getElementById('fragmentShader');
302 var fShaderSource = defaultFragmentShader;
303 var fShaderSuccess = true;
305 var passMsg = undefined;
308 vShaderSource = getSource(vShaderElem);
309 passMsg = getPassMessage(vShaderSource);
310 vShaderSuccess = getSuccess(passMsg);
314 fShaderSource = getSource(fShaderElem);
315 passMsg = getPassMessage(fShaderSource);
316 fShaderSuccess = getSuccess(passMsg);
319 var linkSuccess = vShaderSuccess && fShaderSuccess;
321 if (passMsg === undefined) {
322 testFailed("no test shader found.");
328 vShaderSource: vShaderSource,
329 vShaderSuccess: vShaderSuccess,
330 fShaderSource: fShaderSource,
331 fShaderSuccess: fShaderSuccess,
332 linkSuccess: linkSuccess,
340 var info = setupTest();
341 description(info.passMsg);
345 function runRenderTests(tests) {
346 for (var ii = 0; ii < tests.length; ++ii) {
347 tests[ii].render = true
352 function runRenderTest() {
353 var info = setupTest();
354 description(info.passMsg);
355 runRenderTests([info]);
361 runRenderTest: runRenderTest,
362 runRenderTests: runRenderTests,
363 loadExternalShaders: loadExternalShaders,