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);
147 // Safe the shaders so we test shared shader.
149 fShaderDB[fSource] = fShader;
153 if (debugShaders && fShader) {
154 wtu.addShaderSource(consoleDiv, fLabel + " translated for driver",
155 debugShaders.getTranslatedShaderSource(fShader));
158 if (vShader && fShader) {
159 var program = gl.createProgram();
160 gl.attachShader(program, vShader);
161 gl.attachShader(program, fShader);
163 if (vSource.indexOf("vPosition") >= 0) {
164 gl.bindAttribLocation(program, 0, "vPosition");
166 if (vSource.indexOf("texCoord0") >= 0) {
167 gl.bindAttribLocation(program, 1, "texCoord0");
169 gl.linkProgram(program);
170 var linked = (gl.getProgramParameter(program, gl.LINK_STATUS) != 0);
172 var error = gl.getProgramInfoLog(program);
173 log("*** Error linking program '"+program+"':"+error);
175 if (!info.ignoreResults && linked != info.linkSuccess) {
176 testFailed("[unexpected link status] " + passMsg);
180 if (!info.ignoreResults && info.linkSuccess) {
181 testFailed("[link failed] " + passMsg);
186 if (parseInt(wtu.getUrlOptions().dumpShaders)) {
189 shaderSuccess: info.vShaderSuccess,
195 shaderSuccess: info.fShaderSuccess,
199 wtu.dumpShadersInfo(gl, window.location.pathname, passMsg, vInfo, fInfo);
207 gl.useProgram(program);
208 wtu.setupUnitQuad(gl);
209 wtu.clearAndDrawUnitQuad(gl);
211 var div = document.createElement("div");
212 div.className = "testimages";
213 wtu.insertImage(div, "result", wtu.makeImageFromCanvas(gl.canvas));
214 div.appendChild(document.createElement('br'));
215 consoleDiv.appendChild(div);
216 wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green", 0);
219 function runTests(shaderInfos) {
220 var wtu = WebGLTestUtils;
221 var canvas = document.createElement('canvas');
224 var gl = wtu.create3DContext(canvas);
226 testFailed("context does not exist");
232 var runNextTest = function() {
233 if (testIndex == shaderInfos.length) {
238 runOneTest(gl, shaderInfos[testIndex++]);
239 setTimeout(runNextTest, 1);
244 function loadExternalShaders(filename, passMsg) {
245 var shaderInfos = [];
246 var lines = wtu.readFileList(filename);
247 for (var ii = 0; ii < lines.length; ++ii) {
249 vShaderSource: defaultVertexShader,
250 vShaderSuccess: true,
251 fShaderSource: defaultFragmentShader,
252 fShaderSuccess: true,
256 var line = lines[ii];
257 var files = line.split(/ +/);
259 for (var jj = 0; jj < files.length; ++jj) {
260 var file = files[jj];
261 var shaderSource = wtu.readFile(file);
262 var firstLine = shaderSource.split("\n")[0];
263 var success = undefined;
264 if (firstLine.indexOf("fail") >= 0) {
266 } else if (firstLine.indexOf("succeed") >= 0) {
269 if (success === undefined) {
270 testFailed("bad first line in " + file + ":" + firstLine);
273 if (!wtu.startsWith(firstLine, "// ")) {
274 testFailed("bad first line in " + file + ":" + firstLine);
277 passMsg = passMsg + (passMsg.length ? ", " : "") + firstLine.substr(3);
278 if (wtu.endsWith(file, ".vert")) {
279 info.vShaderSource = shaderSource;
280 info.vShaderSuccess = success;
281 } else if (wtu.endsWith(file, ".frag")) {
282 info.fShaderSource = shaderSource;
283 info.fShaderSuccess = success;
286 info.linkSuccess = info.vShaderSuccess && info.fShaderSuccess;
287 info.passMsg = passMsg;
288 shaderInfos.push(info);
293 function getSource(elem) {
295 return str.replace(/^\s*/, '').replace(/\s*$/, '');
298 function getPassMessage(source) {
299 var lines = source.split('\n');
300 return lines[0].substring(3);
303 function getSuccess(msg) {
304 if (msg.indexOf("fail") >= 0) {
307 if (msg.indexOf("succeed") >= 0) {
310 testFailed("bad test description. Must have 'fail' or 'succeed'");
313 function setupTest() {
314 var vShaderElem = document.getElementById('vertexShader');
315 var vShaderSource = defaultVertexShader;
316 var vShaderSuccess = true;
318 var fShaderElem = document.getElementById('fragmentShader');
319 var fShaderSource = defaultFragmentShader;
320 var fShaderSuccess = true;
322 var passMsg = undefined;
325 vShaderSource = getSource(vShaderElem);
326 passMsg = getPassMessage(vShaderSource);
327 vShaderSuccess = getSuccess(passMsg);
331 fShaderSource = getSource(fShaderElem);
332 passMsg = getPassMessage(fShaderSource);
333 fShaderSuccess = getSuccess(passMsg);
336 var linkSuccess = vShaderSuccess && fShaderSuccess;
338 if (passMsg === undefined) {
339 testFailed("no test shader found.");
345 vShaderSource: vShaderSource,
346 vShaderSuccess: vShaderSuccess,
347 fShaderSource: fShaderSource,
348 fShaderSuccess: fShaderSuccess,
349 linkSuccess: linkSuccess,
357 var info = setupTest();
358 description(info.passMsg);
362 function runRenderTests(tests) {
363 for (var ii = 0; ii < tests.length; ++ii) {
364 tests[ii].render = true
369 function runRenderTest() {
370 var info = setupTest();
371 description(info.passMsg);
372 runRenderTests([info]);
378 runRenderTest: runRenderTest,
379 runRenderTests: runRenderTests,
380 loadExternalShaders: loadExternalShaders,