2010-07-02 Zhenyao Mo <zmo@google.com>
[WebKit.git] / LayoutTests / fast / canvas / webgl / program-test.html
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2   "http://www.w3.org/TR/html4/loose.dtd">
3 <html>
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6 <title>WebGL Program Compiling/Linking Conformance Test</title>
7 <link rel="stylesheet" href="../../js/resources/js-test-style.css"/>
8 <script src="../../js/resources/js-test-pre.js" type="text/javascript"></script>
9 <script src="resources/webgl-test.js" type="text/javascript"></script>
10 </head>
11 <body>
12 <div id="description"></div>
13 <div id="console"></div>
14 <canvas id="canvas" width="2" height="2"> </canvas>
15 <script type="text/javascript">
16 function go() {
17     description("Tests that program compiling/linking/using works correctly.");
18
19     debug("");
20     debug("Canvas.getContext");
21
22     var gl = create3DContext(document.getElementById("canvas"));
23     if (!gl) {
24         testFailed("context does not exist");
25         return;
26     }
27
28     testPassed("context exists");
29
30     gl.clearColor(0.0, 0.0, 0.0, 0.0);
31     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
32
33
34 /////// Check compileShader() /////////////////////////////
35
36     var vs = gl.createShader(gl.VERTEX_SHADER);
37     gl.shaderSource(vs, "attribute vec4 aVertex; attribute vec4 aColor; varying vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex; }");
38     gl.compileShader(vs);
39
40     assertMsg(gl.getShaderParameter(vs, gl.COMPILE_STATUS) == true,
41               "good vertex shader should compile");
42
43     var vs2 = gl.createShader(gl.VERTEX_SHADER);
44     gl.shaderSource(vs2, "attribute vec4 aVertex; attribute vec4 aColor; varying vec4 vColor; void main() { vColor = aColor; gl_Position = aVertex * 0.5; }");
45     gl.compileShader(vs2);
46
47     assertMsg(gl.getShaderParameter(vs2, gl.COMPILE_STATUS) == true,
48               "good vertex shader #2 should compile");
49
50     var vsBad = gl.createShader(gl.VERTEX_SHADER);
51     gl.shaderSource(vsBad, "WILL NOT COMPILE;");
52     gl.compileShader(vsBad);
53
54     assertMsg(gl.getShaderParameter(vsBad, gl.COMPILE_STATUS) == false,
55               "bad vertex shader should fail to compile");
56
57     var fs = gl.createShader(gl.FRAGMENT_SHADER);
58     gl.shaderSource(fs, "#ifdef GL_ES\nprecision mediump float;\n#endif\n varying vec4 vColor; void main() { gl_FragColor = vColor; }");
59     gl.compileShader(fs);
60
61     assertMsg(gl.getShaderParameter(fs, gl.COMPILE_STATUS) == true,
62               "good fragment shader should compile");
63
64     var fs2 = gl.createShader(gl.FRAGMENT_SHADER);
65     gl.shaderSource(fs2, "#ifdef GL_ES\nprecision mediump float;\n#endif\n varying vec4 vColor; void main() { gl_FragColor = vColor * 0.5; }");
66     gl.compileShader(fs2);
67
68     assertMsg(gl.getShaderParameter(fs2, gl.COMPILE_STATUS) == true,
69               "good fragment shader #2 should compile");
70
71     var fsBad = gl.createShader(gl.FRAGMENT_SHADER);
72     gl.shaderSource(fsBad, "WILL NOT COMPILE;");
73     gl.compileShader(fsBad);
74
75     assertMsg(gl.getShaderParameter(fsBad, gl.COMPILE_STATUS) == false,
76               "bad fragment shader should fail to compile");
77
78     assertMsg(gl.getError() == gl.NO_ERROR,
79               "should be no errors at this point");
80
81 /////// Check attachShader() /////////////////////////////
82
83     function checkAttachShader(already_attached_shaders, shader, expected_error_code, errmsg) {
84         var prog = gl.createProgram();
85         for (var i = 0; i < already_attached_shaders.length; ++i)
86             gl.attachShader(prog, already_attached_shaders[i]);
87         if(gl.getError() != gl.NO_ERROR)
88             assertMsg(false, "unexpected error in attachShader()");
89         gl.attachShader(prog, shader);
90         assertMsg(gl.getError() == expected_error_code, errmsg);
91     }
92
93     checkAttachShader([], vs, gl.NO_ERROR, "attaching a vertex shader should succeed");
94     checkAttachShader([vs], vs, gl.INVALID_OPERATION,
95                       "attaching an already attached vertex shader should generate INVALID_OPERATION");
96     checkAttachShader([], fs, gl.NO_ERROR, "attaching a fragment shader should succeed");
97     checkAttachShader([fs], fs, gl.INVALID_OPERATION,
98                       "attaching an already attached fragment shader should generate INVALID_OPERATION");
99
100 /////// Check detachShader() /////////////////////////////
101
102     function checkDetachShader(already_attached_shaders, shader, expected_error_code, errmsg) {
103         var prog = gl.createProgram();
104         for (var i = 0; i < already_attached_shaders.length; ++i)
105             gl.attachShader(prog, already_attached_shaders[i]);
106         if(gl.getError() != gl.NO_ERROR)
107             assertMsg(false, "unexpected error in attachShader()");
108         gl.detachShader(prog, shader);
109         assertMsg(gl.getError() == expected_error_code, errmsg);
110     }
111
112     checkDetachShader([vs], vs, gl.NO_ERROR, "detaching a vertex shader should succeed");
113     checkDetachShader([fs], vs, gl.INVALID_OPERATION,
114                       "detaching a not already attached vertex shader should generate INVALID_OPERATION");
115     checkDetachShader([fs], fs, gl.NO_ERROR, "detaching a fragment shader should succeed");
116     checkDetachShader([vs], fs, gl.INVALID_OPERATION,
117                       "detaching a not already attached fragment shader should generate INVALID_OPERATION");
118
119 /////// Check getAttachedShaders() /////////////////////////////
120
121     function checkGetAttachedShaders(shaders_to_attach, shaders_to_detach, expected_shaders, errmsg) {
122         var prog = gl.createProgram();
123         for (var i = 0; i < shaders_to_attach.length; ++i)
124             gl.attachShader(prog, shaders_to_attach[i]);
125         if(gl.getError() != gl.NO_ERROR)
126             assertMsg(false, "unexpected error in attachShader()");
127         for (var i = 0; i < shaders_to_detach.length; ++i)
128             gl.detachShader(prog, shaders_to_detach[i]);
129         if(gl.getError() != gl.NO_ERROR)
130             assertMsg(false, "unexpected error in detachShader()");
131         assertMsg(areArraysEqual(gl.getAttachedShaders(prog), expected_shaders), errmsg);
132     }
133     checkGetAttachedShaders([], [], [], "getAttachedShaders should return an empty list by default");
134     checkGetAttachedShaders([fs], [], [fs], "attaching a single shader should give the expected list");
135     checkGetAttachedShaders([fs, vs, fs2, vs2], [], [fs, vs, fs2, vs2],
136         "attaching some shaders should give the expected list");
137     checkGetAttachedShaders([fs], [fs], [], "attaching a shader and detaching it shoud leave an empty list");
138     checkGetAttachedShaders([fs, vs, fs2, vs2], [fs, vs, fs2, vs2], [],
139         "attaching some shaders and detaching them in same order shoud leave an empty list");
140     checkGetAttachedShaders([fs, vs, fs2, vs2], [fs, vs2, vs, fs2], [],
141         "attaching some shaders and detaching them in random order shoud leave an empty list");
142     checkGetAttachedShaders([fs, vs, fs2, vs2], [vs], [fs, fs2, vs2],
143         "attaching and detaching some shaders should leave the difference list");
144     checkGetAttachedShaders([fs, vs, fs2, vs2], [fs, vs2], [vs, fs2],
145         "attaching and detaching some shaders should leave the difference list");
146     checkGetAttachedShaders([fsBad], [], [fsBad],
147         "attaching a shader that failed to compile should still show it in the list");
148     checkGetAttachedShaders([fs, vsBad, fs2], [], [fs, vsBad, fs2],
149         "attaching shaders, including one that failed to compile, should still show the it in the list");
150
151 /////// Check linkProgram() and useProgram /////////////////////////////
152
153     function checkLinkAndUse(shaders, expected_status, errmsg) {
154         var prog = gl.createProgram();
155         for (var i = 0; i < shaders.length; ++i)
156             gl.attachShader(prog, shaders[i]);
157         gl.bindAttribLocation(prog, 0, "aVertex");
158         gl.bindAttribLocation(prog, 1, "aColor");
159         gl.linkProgram(prog);
160         if (gl.getError() != gl.NO_ERROR)
161             assertMsg(false, "unexpected error in linkProgram()");
162         assertMsg(gl.getProgramParameter(prog, gl.LINK_STATUS) == expected_status, errmsg);
163         if (expected_status == true && gl.getProgramParameter(prog, gl.LINK_STATUS) == false)
164             debug(gl.getProgramInfoLog(prog));
165         if (gl.getError() != gl.NO_ERROR)
166             assertMsg(false, "unexpected error in getProgramParameter()");
167         gl.useProgram(prog);
168         if (expected_status == true)
169             assertMsg(gl.getError() == gl.NO_ERROR, "using a valid program should succeed");
170         if (expected_status == false)
171             assertMsg(gl.getError() == gl.INVALID_OPERATION, "using an invalid program should generate INVALID_OPERATION");
172         return prog;
173     }
174
175     var progGood1 = checkLinkAndUse([vs, fs], true, "valid program should link");
176     var progGood2 = checkLinkAndUse([vs, fs2], true, "valid program #2 should link");
177     var progBad1 = checkLinkAndUse([vs], false, "program with no fragment shader should fail to link");
178     var progBad2 = checkLinkAndUse([fs], false, "program with no vertex shader should fail to link");
179     var progBad3 = checkLinkAndUse([vsBad, fs], false, "program with bad vertex shader should fail to link");
180     var progBad4 = checkLinkAndUse([vs, fsBad], false, "program with bad fragment shader should fail to link");
181     var progBad5 = checkLinkAndUse([vsBad, fsBad], false, "program with bad shaders should fail to link");
182
183     gl.useProgram(progGood1);
184     assertMsg(gl.getError() == gl.NO_ERROR,
185               "using a valid program shouldn't generate a GL error");
186
187     var vbuf = gl.createBuffer();
188     gl.bindBuffer(gl.ARRAY_BUFFER, vbuf);
189     gl.bufferData(gl.ARRAY_BUFFER,
190                   new Float32Array([
191                       0.0, 0.0, 0.0, 1.0,
192                       1.0, 0.0, 0.0, 1.0,
193                       1.0, 1.0, 0.0, 1.0,
194                       0.0, 1.0, 0.0, 1.0]),
195                   gl.STATIC_DRAW);
196     gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0);
197     gl.enableVertexAttribArray(0);
198     gl.vertexAttrib3f(1, 1.0, 0.0, 0.0);
199
200     assertMsg(gl.getError() == gl.NO_ERROR,
201               "should be no errors at this point #2");
202
203     gl.useProgram(progGood1);
204     gl.drawArrays(gl.TRIANGLES, 0, 3);
205     assertMsg(gl.getError() == gl.NO_ERROR,
206               "drawing with a valid program shouldn't generate a GL error");
207
208     gl.useProgram(progBad1);
209     assertMsg(gl.getError() == gl.INVALID_OPERATION,
210               "using an invalid program should generate INVALID_OPERATION");
211     gl.drawArrays(gl.TRIANGLES, 0, 3);
212     assertMsg(gl.getError() != gl.NO_ERROR,
213               "drawing with an invalid program should generate some GL error XXX");
214
215     gl.useProgram(progGood2);
216     gl.attachShader(progGood2, fsBad);
217     gl.linkProgram(progGood2);
218     assertMsg(gl.getProgramParameter(progGood2, gl.LINK_STATUS) == false,
219               "linking should fail with in-use formerly good program, with new bad shader attached");
220
221     gl.useProgram(progGood1);
222     gl.drawArrays(gl.TRIANGLES, 0, 4);
223     assertMsg(gl.getError() == gl.NO_ERROR,
224               "drawing with a valid when last used program shouldn't generate a GL error");
225 }
226
227 debug("");
228 successfullyParsed = true;
229
230 go();
231 </script>
232 <script src="../../js/resources/js-test-post.js"></script>
233
234 </body>
235 </html>