1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/canvas/test/webgl-conformance/conformance/programs/program-test.html Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,327 @@ 1.4 +<!-- 1.5 +Copyright (c) 2011 Mozilla Foundation. All rights reserved. 1.6 +Use of this source code is governed by a BSD-style license that can be 1.7 +found in the LICENSE file. 1.8 +--> 1.9 +<!DOCTYPE html> 1.10 +<html> 1.11 +<head> 1.12 +<meta charset="utf-8"> 1.13 +<title>WebGL Program Compiling/Linking Conformance Test</title> 1.14 +<link rel="stylesheet" href="../../resources/js-test-style.css"/> 1.15 +<script src="../../resources/js-test-pre.js" type="text/javascript"></script> 1.16 +<script src="../resources/webgl-test.js" type="text/javascript"></script> 1.17 +</head> 1.18 +<body> 1.19 +<div id="description"></div> 1.20 +<div id="console"></div> 1.21 +<canvas id="canvas" width="2" height="2"> </canvas> 1.22 +<script type="text/javascript"> 1.23 +function go() { 1.24 + description("Tests that program compiling/linking/using works correctly."); 1.25 + 1.26 + debug(""); 1.27 + debug("Canvas.getContext"); 1.28 + 1.29 + var gl = create3DContext(document.getElementById("canvas")); 1.30 + if (!gl) { 1.31 + testFailed("context does not exist"); 1.32 + return; 1.33 + } 1.34 + 1.35 + testPassed("context exists"); 1.36 + 1.37 + gl.clearColor(0.0, 0.0, 0.0, 0.0); 1.38 + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 1.39 + 1.40 + function doArraysHaveSameContents(a, b) { 1.41 + var flags = []; 1.42 + function hasUnusedValue(a, value) { 1.43 + for (var ii = 0; ii < a.length; ++ii) { 1.44 + if (a[ii] === value && !flags[ii]) { 1.45 + flags[ii] = true; 1.46 + return true; 1.47 + } 1.48 + } 1.49 + return false; 1.50 + } 1.51 + 1.52 + try { 1.53 + if (a.length !== b.length) { 1.54 + return false; 1.55 + } 1.56 + for (var ii = 0; ii < a.length; ii++) { 1.57 + if (!hasUnusedValue(b, a[ii])) { 1.58 + return false; 1.59 + } 1.60 + } 1.61 + } catch (ex) { 1.62 + return false; 1.63 + } 1.64 + return true; 1.65 + } 1.66 + 1.67 +/////// Check compileShader() ///////////////////////////// 1.68 + 1.69 + var vs = gl.createShader(gl.VERTEX_SHADER); 1.70 + gl.shaderSource(vs, "attribute vec4 aVertex; attribute vec4 aColor; varying vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex; }"); 1.71 + gl.compileShader(vs); 1.72 + 1.73 + assertMsg(gl.getShaderParameter(vs, gl.COMPILE_STATUS) == true, 1.74 + "good vertex shader should compile"); 1.75 + 1.76 + var vs2 = gl.createShader(gl.VERTEX_SHADER); 1.77 + gl.shaderSource(vs2, "attribute vec4 aVertex; attribute vec4 aColor; varying vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex * 0.5; }"); 1.78 + gl.compileShader(vs2); 1.79 + 1.80 + assertMsg(gl.getShaderParameter(vs2, gl.COMPILE_STATUS) == true, 1.81 + "good vertex shader #2 should compile"); 1.82 + 1.83 + var vsBad = gl.createShader(gl.VERTEX_SHADER); 1.84 + gl.shaderSource(vsBad, "WILL NOT COMPILE;"); 1.85 + gl.compileShader(vsBad); 1.86 + 1.87 + // GLSL 1.0.17 section 10.27. compile shader does not have to return failure. 1.88 + //assertMsg(gl.getShaderParameter(vsBad, gl.COMPILE_STATUS) == false, 1.89 + // "bad vertex shader should fail to compile"); 1.90 + 1.91 + var fs = gl.createShader(gl.FRAGMENT_SHADER); 1.92 + gl.shaderSource(fs, "precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; }"); 1.93 + gl.compileShader(fs); 1.94 + 1.95 + assertMsg(gl.getShaderParameter(fs, gl.COMPILE_STATUS) == true, 1.96 + "good fragment shader should compile"); 1.97 + 1.98 + var fs2 = gl.createShader(gl.FRAGMENT_SHADER); 1.99 + gl.shaderSource(fs2, "precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor * 0.5; }"); 1.100 + gl.compileShader(fs2); 1.101 + 1.102 + assertMsg(gl.getShaderParameter(fs2, gl.COMPILE_STATUS) == true, 1.103 + "good fragment shader #2 should compile"); 1.104 + 1.105 + var fsBad = gl.createShader(gl.FRAGMENT_SHADER); 1.106 + gl.shaderSource(fsBad, "WILL NOT COMPILE;"); 1.107 + gl.compileShader(fsBad); 1.108 + 1.109 + // GLSL 1.0.17 section 10.27. compile shader does not have to return failure. 1.110 + //assertMsg(gl.getShaderParameter(fsBad, gl.COMPILE_STATUS) == false, 1.111 + // "bad fragment shader should fail to compile"); 1.112 + 1.113 + glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors at this point"); 1.114 + 1.115 +/////// Check attachShader() ///////////////////////////// 1.116 + 1.117 + function checkAttachShader(already_attached_shaders, shader, expected_error_code, errmsg) { 1.118 + var prog = gl.createProgram(); 1.119 + for (var i = 0; i < already_attached_shaders.length; ++i) 1.120 + gl.attachShader(prog, already_attached_shaders[i]); 1.121 + if(gl.getError() != gl.NO_ERROR) 1.122 + assertMsg(false, "unexpected error in attachShader()"); 1.123 + gl.attachShader(prog, shader); 1.124 + glErrorShouldBe(gl, expected_error_code, errmsg); 1.125 + } 1.126 + 1.127 + checkAttachShader([], vs, gl.NO_ERROR, "attaching a vertex shader should succeed"); 1.128 + checkAttachShader([vs], vs, gl.INVALID_OPERATION, 1.129 + "attaching an already attached vertex shader should generate INVALID_OPERATION"); 1.130 + checkAttachShader([], fs, gl.NO_ERROR, "attaching a fragment shader should succeed"); 1.131 + checkAttachShader([fs], fs, gl.INVALID_OPERATION, 1.132 + "attaching an already attached fragment shader should generate INVALID_OPERATION"); 1.133 + checkAttachShader([vs], vs2, gl.INVALID_OPERATION, 1.134 + "attaching shaders of the same type to a program should generate INVALID_OPERATION"); 1.135 + checkAttachShader([fs], fs2, gl.INVALID_OPERATION, 1.136 + "attaching shaders of the same type to a program should generate INVALID_OPERATION"); 1.137 + 1.138 +/////// Check detachShader() ///////////////////////////// 1.139 + 1.140 + function checkDetachShader(already_attached_shaders, shader, expected_error_code, errmsg) { 1.141 + var prog = gl.createProgram(); 1.142 + for (var i = 0; i < already_attached_shaders.length; ++i) 1.143 + gl.attachShader(prog, already_attached_shaders[i]); 1.144 + if(gl.getError() != gl.NO_ERROR) 1.145 + assertMsg(false, "unexpected error in attachShader()"); 1.146 + gl.detachShader(prog, shader); 1.147 + glErrorShouldBe(gl, expected_error_code, errmsg); 1.148 + } 1.149 + 1.150 + checkDetachShader([vs], vs, gl.NO_ERROR, "detaching a vertex shader should succeed"); 1.151 + checkDetachShader([fs], vs, gl.INVALID_OPERATION, 1.152 + "detaching a not already attached vertex shader should generate INVALID_OPERATION"); 1.153 + checkDetachShader([fs], fs, gl.NO_ERROR, "detaching a fragment shader should succeed"); 1.154 + checkDetachShader([vs], fs, gl.INVALID_OPERATION, 1.155 + "detaching a not already attached fragment shader should generate INVALID_OPERATION"); 1.156 + 1.157 +/////// Check getAttachedShaders() ///////////////////////////// 1.158 + 1.159 + function checkGetAttachedShaders(shaders_to_attach, shaders_to_detach, expected_shaders, errmsg) { 1.160 + var prog = gl.createProgram(); 1.161 + for (var i = 0; i < shaders_to_attach.length; ++i) 1.162 + gl.attachShader(prog, shaders_to_attach[i]); 1.163 + if(gl.getError() != gl.NO_ERROR) 1.164 + assertMsg(false, "unexpected error in attachShader()"); 1.165 + for (var i = 0; i < shaders_to_detach.length; ++i) 1.166 + gl.detachShader(prog, shaders_to_detach[i]); 1.167 + if(gl.getError() != gl.NO_ERROR) 1.168 + assertMsg(false, "unexpected error in detachShader()"); 1.169 + assertMsg(doArraysHaveSameContents(gl.getAttachedShaders(prog), expected_shaders), errmsg); 1.170 + } 1.171 + checkGetAttachedShaders([], [], [], "getAttachedShaders should return an empty list by default"); 1.172 + checkGetAttachedShaders([fs], [], [fs], "attaching a single shader should give the expected list"); 1.173 + checkGetAttachedShaders([fs, vs], [], [fs, vs], 1.174 + "attaching some shaders should give the expected list"); 1.175 + checkGetAttachedShaders([fs], [fs], [], "attaching a shader and detaching it shoud leave an empty list"); 1.176 + checkGetAttachedShaders([fs, vs], [fs, vs], [], 1.177 + "attaching some shaders and detaching them in same order shoud leave an empty list"); 1.178 + checkGetAttachedShaders([fs, vs], [vs, fs], [], 1.179 + "attaching some shaders and detaching them in random order shoud leave an empty list"); 1.180 + checkGetAttachedShaders([fs, vs], [vs], [fs], 1.181 + "attaching and detaching some shaders should leave the difference list"); 1.182 + checkGetAttachedShaders([fs, vs], [fs], [vs], 1.183 + "attaching and detaching some shaders should leave the difference list"); 1.184 + checkGetAttachedShaders([fsBad], [], [fsBad], 1.185 + "attaching a shader that failed to compile should still show it in the list"); 1.186 + checkGetAttachedShaders([fs, vsBad], [], [fs, vsBad], 1.187 + "attaching shaders, including one that failed to compile, should still show the it in the list"); 1.188 + 1.189 +/////// Check linkProgram() and useProgram ///////////////////////////// 1.190 + 1.191 + function checkLinkAndUse(shaders, deleteShaderAfterAttach, expected_status, errmsg) { 1.192 + var prog = gl.createProgram(); 1.193 + for (var i = 0; i < shaders.length; ++i) { 1.194 + gl.attachShader(prog, shaders[i]); 1.195 + if (deleteShaderAfterAttach) 1.196 + gl.deleteShader(shaders[i]); 1.197 + } 1.198 + gl.bindAttribLocation(prog, 0, "aVertex"); 1.199 + gl.bindAttribLocation(prog, 1, "aColor"); 1.200 + gl.linkProgram(prog); 1.201 + if (gl.getError() != gl.NO_ERROR) 1.202 + assertMsg(false, "unexpected error in linkProgram()"); 1.203 + assertMsg(gl.getProgramParameter(prog, gl.LINK_STATUS) == expected_status, errmsg); 1.204 + var infolog = gl.getProgramInfoLog(prog); 1.205 + if (gl.getError() != gl.NO_ERROR) 1.206 + assertMsg(false, "unexpected error in getProgramInfoLog()"); 1.207 + if (typeof(infolog) != "string") 1.208 + assertMsg(false, "getProgramInfoLog() did not return a string"); 1.209 + if (expected_status == true && gl.getProgramParameter(prog, gl.LINK_STATUS) == false) 1.210 + debug(infolog); 1.211 + if (gl.getError() != gl.NO_ERROR) 1.212 + assertMsg(false, "unexpected error in getProgramParameter()"); 1.213 + gl.useProgram(prog); 1.214 + if (expected_status == true) 1.215 + glErrorShouldBe(gl, gl.NO_ERROR, "using a valid program should succeed"); 1.216 + if (expected_status == false) 1.217 + glErrorShouldBe(gl, gl.INVALID_OPERATION, "using an invalid program should generate INVALID_OPERATION"); 1.218 + return prog; 1.219 + } 1.220 + 1.221 + var progGood1 = checkLinkAndUse([vs, fs], false, true, "valid program should link"); 1.222 + var progGood2 = checkLinkAndUse([vs, fs2], false, true, "valid program #2 should link"); 1.223 + var progBad1 = checkLinkAndUse([vs], false, false, "program with no fragment shader should fail to link"); 1.224 + var progBad2 = checkLinkAndUse([fs], false, false, "program with no vertex shader should fail to link"); 1.225 + var progBad3 = checkLinkAndUse([vsBad, fs], false, false, "program with bad vertex shader should fail to link"); 1.226 + var progBad4 = checkLinkAndUse([vs, fsBad], false, false, "program with bad fragment shader should fail to link"); 1.227 + var progBad5 = checkLinkAndUse([vsBad, fsBad], false, false, "program with bad shaders should fail to link"); 1.228 + 1.229 + gl.useProgram(progGood1); 1.230 + glErrorShouldBe(gl, gl.NO_ERROR, "using a valid program shouldn't generate a GL error"); 1.231 + 1.232 + var vbuf = gl.createBuffer(); 1.233 + gl.bindBuffer(gl.ARRAY_BUFFER, vbuf); 1.234 + gl.bufferData(gl.ARRAY_BUFFER, 1.235 + new Float32Array([ 1.236 + 0.0, 0.0, 0.0, 1.0, 1.237 + 1.0, 0.0, 0.0, 1.0, 1.238 + 1.0, 1.0, 0.0, 1.0, 1.239 + 0.0, 1.0, 0.0, 1.0]), 1.240 + gl.STATIC_DRAW); 1.241 + gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0); 1.242 + gl.enableVertexAttribArray(0); 1.243 + gl.vertexAttrib3f(1, 1.0, 0.0, 0.0); 1.244 + 1.245 + glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors at this point #2"); 1.246 + 1.247 + gl.useProgram(progGood1); 1.248 + gl.drawArrays(gl.TRIANGLES, 0, 3); 1.249 + glErrorShouldBe(gl, gl.NO_ERROR, "drawing with a valid program shouldn't generate a GL error"); 1.250 + 1.251 + gl.useProgram(progBad1); 1.252 + glErrorShouldBe(gl, gl.INVALID_OPERATION, "using an invalid program should generate INVALID_OPERATION"); 1.253 + gl.drawArrays(gl.TRIANGLES, 0, 3); 1.254 + glErrorShouldBe(gl, gl.NO_ERROR, "Try to use an invalid program should not change the current rendering state"); 1.255 + 1.256 + gl.useProgram(progGood2); 1.257 + gl.drawArrays(gl.TRIANGLES, 0, 3); 1.258 + glErrorShouldBe(gl, gl.NO_ERROR, "drawing with a valid program shouldn't generate a GL error"); 1.259 + gl.detachShader(progGood2, fs2); 1.260 + gl.attachShader(progGood2, fsBad); 1.261 + gl.linkProgram(progGood2); 1.262 + assertMsg(gl.getProgramParameter(progGood2, gl.LINK_STATUS) == false, 1.263 + "linking should fail with in-use formerly good program, with new bad shader attached"); 1.264 + 1.265 + // Invalid link leaves previous valid program intact. 1.266 + gl.drawArrays(gl.TRIANGLES, 0, 3); 1.267 + glErrorShouldBe(gl, gl.NO_ERROR, "drawing with a valid program shouldn't generate a GL error"); 1.268 + 1.269 + gl.useProgram(progGood1); 1.270 + gl.drawArrays(gl.TRIANGLES, 0, 4); 1.271 + glErrorShouldBe(gl, gl.NO_ERROR, "drawing with a valid when last used program shouldn't generate a GL error"); 1.272 + 1.273 + var progGood1 = checkLinkAndUse([vs, fs], true, true, "delete shaders after attaching them and before linking program should not affect linkProgram"); 1.274 + gl.useProgram(progGood1); 1.275 + gl.drawArrays(gl.TRIANGLES, 0, 4); 1.276 + glErrorShouldBe(gl, gl.NO_ERROR, "drawing with a valid when last used program shouldn't generate a GL error"); 1.277 + 1.278 +/////// Check deleteProgram() and deleteShader() ///////////////////////////// 1.279 + 1.280 + gl.useProgram(progGood1); 1.281 + gl.deleteProgram(progGood1); 1.282 + gl.drawArrays(gl.TRIANGLES, 0, 4); 1.283 + glErrorShouldBe(gl, gl.NO_ERROR, "delete the current program shouldn't change the current rendering state"); 1.284 + 1.285 + gl.linkProgram(progGood1); 1.286 + glErrorShouldBe(gl, gl.NO_ERROR, "The current program shouldn't be deleted"); 1.287 + 1.288 + var fs3 = gl.createShader(gl.FRAGMENT_SHADER); 1.289 + gl.shaderSource(fs3, "precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; }"); 1.290 + gl.compileShader(fs3); 1.291 + 1.292 + assertMsg(gl.getShaderParameter(fs3, gl.COMPILE_STATUS) == true, 1.293 + "good fragment shader should compile"); 1.294 + 1.295 + gl.deleteShader(fs3); 1.296 + gl.compileShader(fs3); 1.297 + glErrorShouldBe(gl, gl.INVALID_VALUE, "an unattached shader should be deleted immediately"); 1.298 + 1.299 + fs3 = gl.createShader(gl.FRAGMENT_SHADER); 1.300 + gl.shaderSource(fs3, "precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; }"); 1.301 + gl.compileShader(fs3); 1.302 + 1.303 + assertMsg(gl.getShaderParameter(fs3, gl.COMPILE_STATUS) == true, 1.304 + "good fragment shader should compile"); 1.305 + 1.306 + gl.detachShader(progGood1, fs); 1.307 + gl.attachShader(progGood1, fs3); 1.308 + 1.309 + gl.deleteShader(fs3); 1.310 + gl.compileShader(fs3); 1.311 + assertMsg(gl.getShaderParameter(fs3, gl.COMPILE_STATUS) == true, 1.312 + "an attached shader shouldn't be deleted"); 1.313 + 1.314 + gl.useProgram(null); 1.315 + gl.linkProgram(progGood1); 1.316 + glErrorShouldBe(gl, gl.INVALID_VALUE, "a delete-marked program should be deleted once it's no longer the current program"); 1.317 + 1.318 + gl.compileShader(fs3); 1.319 + glErrorShouldBe(gl, gl.INVALID_VALUE, "a delete-marked shader should be deleted once all its attachments are removed"); 1.320 +} 1.321 + 1.322 +debug(""); 1.323 +go(); 1.324 + 1.325 +successfullyParsed = true; 1.326 +</script> 1.327 +<script>finishTest();</script> 1.328 + 1.329 +</body> 1.330 +</html>