OLD | NEW |
| (Empty) |
1 <!-- | |
2 Copyright (c) 2010 Mozilla Foundation. All rights reserved. | |
3 Use of this source code is governed by a BSD-style license that can be | |
4 found in the LICENSE file. | |
5 --> | |
6 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
7 "http://www.w3.org/TR/html4/loose.dtd"> | |
8 <html> | |
9 <head> | |
10 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> | |
11 <title>WebGL Program Compiling/Linking Conformance Test</title> | |
12 <link rel="stylesheet" href="../resources/js-test-style.css"/> | |
13 <script src="../resources/js-test-pre.js" type="text/javascript"></script> | |
14 <script src="resources/webgl-test.js" type="text/javascript"></script> | |
15 </head> | |
16 <body> | |
17 <div id="description"></div> | |
18 <div id="console"></div> | |
19 <canvas id="canvas" width="2" height="2"> </canvas> | |
20 <script type="text/javascript"> | |
21 function go() { | |
22 description("Tests that program compiling/linking/using works correctly."); | |
23 | |
24 debug(""); | |
25 debug("Canvas.getContext"); | |
26 | |
27 var gl = create3DContext(document.getElementById("canvas")); | |
28 if (!gl) { | |
29 testFailed("context does not exist"); | |
30 return; | |
31 } | |
32 | |
33 testPassed("context exists"); | |
34 | |
35 gl.clearColor(0.0, 0.0, 0.0, 0.0); | |
36 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
37 | |
38 function doArraysHaveSameContents(a, b) { | |
39 var flags = []; | |
40 function hasUnusedValue(a, value) { | |
41 for (var ii = 0; ii < a.length; ++ii) { | |
42 if (a[ii] === value && !flags[ii]) { | |
43 flags[ii] = true; | |
44 return true; | |
45 } | |
46 } | |
47 return false; | |
48 } | |
49 | |
50 try { | |
51 if (a.length !== b.length) { | |
52 return false; | |
53 } | |
54 for (var ii = 0; ii < a.length; ii++) { | |
55 if (!hasUnusedValue(b, a[ii])) { | |
56 return false; | |
57 } | |
58 } | |
59 } catch (ex) { | |
60 return false; | |
61 } | |
62 return true; | |
63 } | |
64 | |
65 /////// Check compileShader() ///////////////////////////// | |
66 | |
67 var vs = gl.createShader(gl.VERTEX_SHADER); | |
68 gl.shaderSource(vs, "attribute vec4 aVertex; attribute vec4 aColor; varying
vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex; }"); | |
69 gl.compileShader(vs); | |
70 | |
71 assertMsg(gl.getShaderParameter(vs, gl.COMPILE_STATUS) == true, | |
72 "good vertex shader should compile"); | |
73 | |
74 var vs2 = gl.createShader(gl.VERTEX_SHADER); | |
75 gl.shaderSource(vs2, "attribute vec4 aVertex; attribute vec4 aColor; varying
vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex * 0.5; }"); | |
76 gl.compileShader(vs2); | |
77 | |
78 assertMsg(gl.getShaderParameter(vs2, gl.COMPILE_STATUS) == true, | |
79 "good vertex shader #2 should compile"); | |
80 | |
81 var vsBad = gl.createShader(gl.VERTEX_SHADER); | |
82 gl.shaderSource(vsBad, "WILL NOT COMPILE;"); | |
83 gl.compileShader(vsBad); | |
84 | |
85 assertMsg(gl.getShaderParameter(vsBad, gl.COMPILE_STATUS) == false, | |
86 "bad vertex shader should fail to compile"); | |
87 | |
88 var fs = gl.createShader(gl.FRAGMENT_SHADER); | |
89 gl.shaderSource(fs, "#ifdef GL_ES\nprecision mediump float;\n#endif\n varyin
g vec4 vColor; void main() { gl_FragColor = vColor; }"); | |
90 gl.compileShader(fs); | |
91 | |
92 assertMsg(gl.getShaderParameter(fs, gl.COMPILE_STATUS) == true, | |
93 "good fragment shader should compile"); | |
94 | |
95 var fs2 = gl.createShader(gl.FRAGMENT_SHADER); | |
96 gl.shaderSource(fs2, "#ifdef GL_ES\nprecision mediump float;\n#endif\n varyi
ng vec4 vColor; void main() { gl_FragColor = vColor * 0.5; }"); | |
97 gl.compileShader(fs2); | |
98 | |
99 assertMsg(gl.getShaderParameter(fs2, gl.COMPILE_STATUS) == true, | |
100 "good fragment shader #2 should compile"); | |
101 | |
102 var fsBad = gl.createShader(gl.FRAGMENT_SHADER); | |
103 gl.shaderSource(fsBad, "WILL NOT COMPILE;"); | |
104 gl.compileShader(fsBad); | |
105 | |
106 assertMsg(gl.getShaderParameter(fsBad, gl.COMPILE_STATUS) == false, | |
107 "bad fragment shader should fail to compile"); | |
108 | |
109 glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors at this point"); | |
110 | |
111 /////// Check attachShader() ///////////////////////////// | |
112 | |
113 function checkAttachShader(already_attached_shaders, shader, expected_error_
code, errmsg) { | |
114 var prog = gl.createProgram(); | |
115 for (var i = 0; i < already_attached_shaders.length; ++i) | |
116 gl.attachShader(prog, already_attached_shaders[i]); | |
117 if(gl.getError() != gl.NO_ERROR) | |
118 assertMsg(false, "unexpected error in attachShader()"); | |
119 gl.attachShader(prog, shader); | |
120 glErrorShouldBe(gl, expected_error_code, errmsg); | |
121 } | |
122 | |
123 checkAttachShader([], vs, gl.NO_ERROR, "attaching a vertex shader should suc
ceed"); | |
124 checkAttachShader([vs], vs, gl.INVALID_OPERATION, | |
125 "attaching an already attached vertex shader should genera
te INVALID_OPERATION"); | |
126 checkAttachShader([], fs, gl.NO_ERROR, "attaching a fragment shader should s
ucceed"); | |
127 checkAttachShader([fs], fs, gl.INVALID_OPERATION, | |
128 "attaching an already attached fragment shader should gene
rate INVALID_OPERATION"); | |
129 checkAttachShader([vs], vs2, gl.INVALID_OPERATION, | |
130 "attaching shaders of the same type to a program should ge
nerate INVALID_OPERATION"); | |
131 checkAttachShader([fs], fs2, gl.INVALID_OPERATION, | |
132 "attaching shaders of the same type to a program should ge
nerate INVALID_OPERATION"); | |
133 | |
134 /////// Check detachShader() ///////////////////////////// | |
135 | |
136 function checkDetachShader(already_attached_shaders, shader, expected_error_
code, errmsg) { | |
137 var prog = gl.createProgram(); | |
138 for (var i = 0; i < already_attached_shaders.length; ++i) | |
139 gl.attachShader(prog, already_attached_shaders[i]); | |
140 if(gl.getError() != gl.NO_ERROR) | |
141 assertMsg(false, "unexpected error in attachShader()"); | |
142 gl.detachShader(prog, shader); | |
143 glErrorShouldBe(gl, expected_error_code, errmsg); | |
144 } | |
145 | |
146 checkDetachShader([vs], vs, gl.NO_ERROR, "detaching a vertex shader should s
ucceed"); | |
147 checkDetachShader([fs], vs, gl.INVALID_OPERATION, | |
148 "detaching a not already attached vertex shader should gen
erate INVALID_OPERATION"); | |
149 checkDetachShader([fs], fs, gl.NO_ERROR, "detaching a fragment shader should
succeed"); | |
150 checkDetachShader([vs], fs, gl.INVALID_OPERATION, | |
151 "detaching a not already attached fragment shader should g
enerate INVALID_OPERATION"); | |
152 | |
153 /////// Check getAttachedShaders() ///////////////////////////// | |
154 | |
155 function checkGetAttachedShaders(shaders_to_attach, shaders_to_detach, expec
ted_shaders, errmsg) { | |
156 var prog = gl.createProgram(); | |
157 for (var i = 0; i < shaders_to_attach.length; ++i) | |
158 gl.attachShader(prog, shaders_to_attach[i]); | |
159 if(gl.getError() != gl.NO_ERROR) | |
160 assertMsg(false, "unexpected error in attachShader()"); | |
161 for (var i = 0; i < shaders_to_detach.length; ++i) | |
162 gl.detachShader(prog, shaders_to_detach[i]); | |
163 if(gl.getError() != gl.NO_ERROR) | |
164 assertMsg(false, "unexpected error in detachShader()"); | |
165 assertMsg(doArraysHaveSameContents(gl.getAttachedShaders(prog), expected
_shaders), errmsg); | |
166 } | |
167 checkGetAttachedShaders([], [], [], "getAttachedShaders should return an emp
ty list by default"); | |
168 checkGetAttachedShaders([fs], [], [fs], "attaching a single shader should gi
ve the expected list"); | |
169 checkGetAttachedShaders([fs, vs], [], [fs, vs], | |
170 "attaching some shaders should give the expected list"); | |
171 checkGetAttachedShaders([fs], [fs], [], "attaching a shader and detaching it
shoud leave an empty list"); | |
172 checkGetAttachedShaders([fs, vs], [fs, vs], [], | |
173 "attaching some shaders and detaching them in same order shoud leave an
empty list"); | |
174 checkGetAttachedShaders([fs, vs], [vs, fs], [], | |
175 "attaching some shaders and detaching them in random order shoud leave a
n empty list"); | |
176 checkGetAttachedShaders([fs, vs], [vs], [fs], | |
177 "attaching and detaching some shaders should leave the difference list")
; | |
178 checkGetAttachedShaders([fs, vs], [fs], [vs], | |
179 "attaching and detaching some shaders should leave the difference list")
; | |
180 checkGetAttachedShaders([fsBad], [], [fsBad], | |
181 "attaching a shader that failed to compile should still show it in the l
ist"); | |
182 checkGetAttachedShaders([fs, vsBad], [], [fs, vsBad], | |
183 "attaching shaders, including one that failed to compile, should still s
how the it in the list"); | |
184 | |
185 /////// Check linkProgram() and useProgram ///////////////////////////// | |
186 | |
187 function checkLinkAndUse(shaders, deleteShaderAfterAttach, expected_status,
errmsg) { | |
188 var prog = gl.createProgram(); | |
189 for (var i = 0; i < shaders.length; ++i) { | |
190 gl.attachShader(prog, shaders[i]); | |
191 if (deleteShaderAfterAttach) | |
192 gl.deleteShader(shaders[i]); | |
193 } | |
194 gl.bindAttribLocation(prog, 0, "aVertex"); | |
195 gl.bindAttribLocation(prog, 1, "aColor"); | |
196 gl.linkProgram(prog); | |
197 if (gl.getError() != gl.NO_ERROR) | |
198 assertMsg(false, "unexpected error in linkProgram()"); | |
199 assertMsg(gl.getProgramParameter(prog, gl.LINK_STATUS) == expected_statu
s, errmsg); | |
200 if (expected_status == true && gl.getProgramParameter(prog, gl.LINK_STAT
US) == false) | |
201 debug(gl.getProgramInfoLog(prog)); | |
202 if (gl.getError() != gl.NO_ERROR) | |
203 assertMsg(false, "unexpected error in getProgramParameter()"); | |
204 gl.useProgram(prog); | |
205 if (expected_status == true) | |
206 glErrorShouldBe(gl, gl.NO_ERROR, "using a valid program should succe
ed"); | |
207 if (expected_status == false) | |
208 glErrorShouldBe(gl, gl.INVALID_OPERATION, "using an invalid program
should generate INVALID_OPERATION"); | |
209 return prog; | |
210 } | |
211 | |
212 var progGood1 = checkLinkAndUse([vs, fs], false, true, "valid program should
link"); | |
213 var progGood2 = checkLinkAndUse([vs, fs2], false, true, "valid program #2 sh
ould link"); | |
214 var progBad1 = checkLinkAndUse([vs], false, false, "program with no fragment
shader should fail to link"); | |
215 var progBad2 = checkLinkAndUse([fs], false, false, "program with no vertex s
hader should fail to link"); | |
216 var progBad3 = checkLinkAndUse([vsBad, fs], false, false, "program with bad
vertex shader should fail to link"); | |
217 var progBad4 = checkLinkAndUse([vs, fsBad], false, false, "program with bad
fragment shader should fail to link"); | |
218 var progBad5 = checkLinkAndUse([vsBad, fsBad], false, false, "program with b
ad shaders should fail to link"); | |
219 | |
220 gl.useProgram(progGood1); | |
221 glErrorShouldBe(gl, gl.NO_ERROR, "using a valid program shouldn't generate a
GL error"); | |
222 | |
223 var vbuf = gl.createBuffer(); | |
224 gl.bindBuffer(gl.ARRAY_BUFFER, vbuf); | |
225 gl.bufferData(gl.ARRAY_BUFFER, | |
226 new Float32Array([ | |
227 0.0, 0.0, 0.0, 1.0, | |
228 1.0, 0.0, 0.0, 1.0, | |
229 1.0, 1.0, 0.0, 1.0, | |
230 0.0, 1.0, 0.0, 1.0]), | |
231 gl.STATIC_DRAW); | |
232 gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0); | |
233 gl.enableVertexAttribArray(0); | |
234 gl.vertexAttrib3f(1, 1.0, 0.0, 0.0); | |
235 | |
236 glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors at this point #2"); | |
237 | |
238 gl.useProgram(progGood1); | |
239 gl.drawArrays(gl.TRIANGLES, 0, 3); | |
240 glErrorShouldBe(gl, gl.NO_ERROR, "drawing with a valid program shouldn't gen
erate a GL error"); | |
241 | |
242 gl.useProgram(progBad1); | |
243 glErrorShouldBe(gl, gl.INVALID_OPERATION, "using an invalid program should g
enerate INVALID_OPERATION"); | |
244 gl.drawArrays(gl.TRIANGLES, 0, 3); | |
245 glErrorShouldBe(gl, gl.NO_ERROR, "Try to use an invalid program should not c
hange the current rendering state"); | |
246 | |
247 gl.useProgram(progGood2); | |
248 gl.drawArrays(gl.TRIANGLES, 0, 3); | |
249 glErrorShouldBe(gl, gl.NO_ERROR, "drawing with a valid program shouldn't gen
erate a GL error"); | |
250 gl.detachShader(progGood2, fs2); | |
251 gl.attachShader(progGood2, fsBad); | |
252 gl.linkProgram(progGood2); | |
253 assertMsg(gl.getProgramParameter(progGood2, gl.LINK_STATUS) == false, | |
254 "linking should fail with in-use formerly good program, with new b
ad shader attached"); | |
255 | |
256 gl.useProgram(progGood1); | |
257 gl.drawArrays(gl.TRIANGLES, 0, 4); | |
258 glErrorShouldBe(gl, gl.NO_ERROR, "drawing with a valid when last used progra
m shouldn't generate a GL error"); | |
259 | |
260 var progGood1 = checkLinkAndUse([vs, fs], true, true, "delete shaders after
attaching them and before linking program should not affect linkProgram"); | |
261 gl.useProgram(progGood1); | |
262 gl.drawArrays(gl.TRIANGLES, 0, 4); | |
263 glErrorShouldBe(gl, gl.NO_ERROR, "drawing with a valid when last used progra
m shouldn't generate a GL error"); | |
264 | |
265 /////// Check deleteProgram() and deleteShader() ///////////////////////////// | |
266 | |
267 gl.useProgram(progGood1); | |
268 gl.deleteProgram(progGood1); | |
269 gl.drawArrays(gl.TRIANGLES, 0, 4); | |
270 glErrorShouldBe(gl, gl.NO_ERROR, "delete the current program shouldn't chang
e the current rendering state"); | |
271 | |
272 gl.linkProgram(progGood1); | |
273 glErrorShouldBe(gl, gl.NO_ERROR, "The current program shouldn't be deleted")
; | |
274 | |
275 var fs3 = gl.createShader(gl.FRAGMENT_SHADER); | |
276 gl.shaderSource(fs3, "#ifdef GL_ES\nprecision mediump float;\n#endif\n varyi
ng vec4 vColor; void main() { gl_FragColor = vColor; }"); | |
277 gl.compileShader(fs3); | |
278 | |
279 assertMsg(gl.getShaderParameter(fs3, gl.COMPILE_STATUS) == true, | |
280 "good fragment shader should compile"); | |
281 | |
282 gl.deleteShader(fs3); | |
283 gl.compileShader(fs3); | |
284 glErrorShouldBe(gl, gl.INVALID_VALUE, "an unattached shader should be delete
d immediately"); | |
285 | |
286 fs3 = gl.createShader(gl.FRAGMENT_SHADER); | |
287 gl.shaderSource(fs3, "#ifdef GL_ES\nprecision mediump float;\n#endif\n varyi
ng vec4 vColor; void main() { gl_FragColor = vColor; }"); | |
288 gl.compileShader(fs3); | |
289 | |
290 assertMsg(gl.getShaderParameter(fs3, gl.COMPILE_STATUS) == true, | |
291 "good fragment shader should compile"); | |
292 | |
293 gl.detachShader(progGood1, fs); | |
294 gl.attachShader(progGood1, fs3); | |
295 | |
296 gl.deleteShader(fs3); | |
297 gl.compileShader(fs3); | |
298 assertMsg(gl.getShaderParameter(fs3, gl.COMPILE_STATUS) == true, | |
299 "an attached shader shouldn't be deleted"); | |
300 | |
301 gl.useProgram(null); | |
302 gl.linkProgram(progGood1); | |
303 glErrorShouldBe(gl, gl.INVALID_VALUE, "a delete-marked program should be del
eted once it's no longer the current program"); | |
304 | |
305 gl.compileShader(fs3); | |
306 glErrorShouldBe(gl, gl.INVALID_VALUE, "a delete-marked shader should be dele
ted once all its attachments are removed"); | |
307 } | |
308 | |
309 debug(""); | |
310 go(); | |
311 | |
312 successfullyParsed = true; | |
313 </script> | |
314 <script src="../resources/js-test-post.js"></script> | |
315 | |
316 </body> | |
317 </html> | |
OLD | NEW |