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