cd07943709f181385d52c40bcd94a48d0e30d25d
[WebKit-https.git] / LayoutTests / fast / canvas / webgl / oes-vertex-array-object.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title>WebGL OES_vertex_array_object Conformance Tests</title>
6 <script src="resources/desktop-gl-constants.js" type="text/javascript"></script>
7 <script src="../../js/resources/js-test-pre.js"></script>
8 <script src="resources/webgl-test.js"></script>
9 <script src="resources/webgl-test-utils.js"></script>
10 </head>
11 <body>
12 <div id="description"></div>
13 <canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
14 <div id="console"></div>
15 <script id="vshader", type="x-shader/x-vertex">
16 attribute vec4 a_position;
17 attribute vec4 a_color;
18 varying vec4 v_color;
19 void main(void) {
20     gl_Position = a_position;
21     v_color = a_color;
22 }
23 </script>
24 <script id="fshader", type="x-shader/x-fragment">
25 precision mediump float;
26 varying vec4 v_color;
27 void main(void) {
28     gl_FragColor = v_color;
29 }
30 </script>
31 <script>
32 description("This test verifies the functionality of the OES_vertex_array_object extension, if it is available.");
33
34 debug("");
35
36 var wtu = WebGLTestUtils;
37 var canvas = document.getElementById("canvas");
38 var gl = create3DContext(canvas);
39 var ext = null;
40 var vao = null;
41
42 if (!gl) {
43     testFailed("WebGL context does not exist");
44 } else {
45     testPassed("WebGL context exists");
46
47     // Setup emulated OESVertexArrayObject if it has been included.
48     if (window.setupVertexArrayObject) {
49         debug("using emuated OES_vertex_array_object");
50         setupVertexArrayObject(gl);
51     }
52
53     // Run tests with extension disabled
54     runBindingTestDisabled();
55
56     // Query the extension and store globally so shouldBe can access it
57     ext = gl.getExtension("OES_vertex_array_object");
58     if (!ext) {
59         testPassed("No OES_vertex_array_object support -- this is legal");
60
61         runSupportedTest(false);
62     } else {
63         testPassed("Successfully enabled OES_vertex_array_object extension");
64
65         runSupportedTest(true);
66         runBindingTestEnabled();
67         runObjectTest();
68         runAttributeTests();
69         runAttributeValueTests();
70         runDrawTests();
71         runDeleteTests();
72         runArrayBufferBindTests();
73         glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
74     }
75 }
76
77 function runSupportedTest(extensionEnabled) {
78     var supported = gl.getSupportedExtensions();
79     if (supported.indexOf("OES_vertex_array_object") >= 0) {
80         if (extensionEnabled) {
81             testPassed("OES_vertex_array_object listed as supported and getExtension succeeded");
82         } else {
83             testFailed("OES_vertex_array_object listed as supported but getExtension failed");
84         }
85     } else {
86         if (extensionEnabled) {
87             testFailed("OES_vertex_array_object not listed as supported but getExtension succeeded");
88         } else {
89             testPassed("OES_vertex_array_object not listed as supported and getExtension failed -- this is legal");
90         }
91     }
92 }
93
94 function runBindingTestDisabled() {
95     debug("Testing binding enum with extension disabled");
96     
97     // Use the constant directly as we don't have the extension
98     var VERTEX_ARRAY_BINDING_OES = 0x85B5;
99     
100     gl.getParameter(VERTEX_ARRAY_BINDING_OES);
101     glErrorShouldBe(gl, gl.INVALID_ENUM, "VERTEX_ARRAY_BINDING_OES should not be queryable if extension is disabled");
102 }
103
104 function runBindingTestEnabled() {
105     debug("Testing binding enum with extension enabled");
106     
107     shouldBe("ext.VERTEX_ARRAY_BINDING_OES", "0x85B5");
108     
109     gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES);
110     glErrorShouldBe(gl, gl.NO_ERROR, "VERTEX_ARRAY_BINDING_OES query should succeed if extension is enable");
111     
112     // Default value is null
113     if (gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) === null) {
114         testPassed("Default value of VERTEX_ARRAY_BINDING_OES is null");
115     } else {
116         testFailed("Default value of VERTEX_ARRAY_BINDING_OES is not null");
117     }
118     
119     debug("Testing binding a VAO");
120     var vao0 = ext.createVertexArrayOES();
121     var vao1 = ext.createVertexArrayOES();
122     shouldBeNull("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES)");
123     ext.bindVertexArrayOES(vao0);
124     if (gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) == vao0) {
125         testPassed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is expected VAO");
126     } else {
127         testFailed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is not expected VAO")
128     }
129     ext.bindVertexArrayOES(vao1);
130     if (gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) == vao1) {
131         testPassed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is expected VAO");
132     } else {
133         testFailed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is not expected VAO")
134     }
135     ext.deleteVertexArrayOES(vao1);
136     shouldBeNull("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES)");
137     ext.bindVertexArrayOES(vao1);
138     glErrorShouldBe(gl, gl.INVALID_OPERATION, "binding a deleted vertex array object");
139     ext.bindVertexArrayOES(null);
140     shouldBeNull("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES)");
141     ext.deleteVertexArrayOES(vao1);
142 }
143
144 function runObjectTest() {
145     debug("Testing object creation");
146     
147     vao = ext.createVertexArrayOES();
148     glErrorShouldBe(gl, gl.NO_ERROR, "createVertexArrayOES should not set an error");
149     shouldBeNonNull("vao");
150     
151     // Expect false if never bound
152     shouldBeFalse("ext.isVertexArrayOES(vao)");
153     ext.bindVertexArrayOES(vao);
154     shouldBeTrue("ext.isVertexArrayOES(vao)");
155     ext.bindVertexArrayOES(null);
156     shouldBeTrue("ext.isVertexArrayOES(vao)");
157     
158     shouldBeFalse("ext.isVertexArrayOES()");
159     shouldBeFalse("ext.isVertexArrayOES(null)");
160     
161     ext.deleteVertexArrayOES(vao);
162     vao = null;
163 }
164
165 function runAttributeTests() {
166     debug("Testing attributes work across bindings");
167     
168     var states = [];
169     
170     var attrCount = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
171     for (var n = 0; n < attrCount; n++) {
172         gl.bindBuffer(gl.ARRAY_BUFFER, null);
173         gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
174         
175         var state = {};
176         states.push(state);
177         
178         var vao = state.vao = ext.createVertexArrayOES();
179         ext.bindVertexArrayOES(vao);
180         
181         if (n % 2 == 0) {
182             gl.enableVertexAttribArray(n);
183         } else {
184             gl.disableVertexAttribArray(n);
185         }
186         
187         if (n % 2 == 0) {
188             var buffer = state.buffer = gl.createBuffer();
189             gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
190             gl.bufferData(gl.ARRAY_BUFFER, 1024, gl.STATIC_DRAW);
191             
192             gl.vertexAttribPointer(n, 1 + n % 4, gl.FLOAT, true, n * 4, n * 4);
193         }
194         
195         if (n % 2 == 0) {
196             var elbuffer = state.elbuffer = gl.createBuffer();
197             gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elbuffer);
198             gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 1024, gl.STATIC_DRAW);
199         }
200         
201         ext.bindVertexArrayOES(null);
202     }
203     
204     var anyMismatch = false;
205     for (var n = 0; n < attrCount; n++) {
206         var state = states[n];
207         
208         ext.bindVertexArrayOES(state.vao);
209         
210         var isEnabled = gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_ENABLED);
211         if ((n % 2 == 1) || isEnabled) {
212             // Valid
213         } else {
214             testFailed("VERTEX_ATTRIB_ARRAY_ENABLED not preserved");
215             anyMismatch = true;
216         }
217         
218         var buffer = gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
219         if (n % 2 == 0) {
220             if (buffer == state.buffer) {
221                 // Matched
222                 if ((gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_SIZE) == 1 + n % 4) &&
223                     (gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_TYPE) == gl.FLOAT) &&
224                     (gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED) == true) &&
225                     (gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_STRIDE) == n * 4) &&
226                     (gl.getVertexAttribOffset(n, gl.VERTEX_ATTRIB_ARRAY_POINTER) == n * 4)) {
227                     // Matched
228                 } else {
229                     testFailed("VERTEX_ATTRIB_ARRAY_* not preserved");
230                     anyMismatch = true;
231                 }
232             } else {
233                 testFailed("VERTEX_ATTRIB_ARRAY_BUFFER_BINDING not preserved");
234                 anyMismatch = true;
235             }
236         } else {
237             // GL_CURRENT_VERTEX_ATTRIB is not preserved
238             if (buffer) {
239                 testFailed("VERTEX_ATTRIB_ARRAY_BUFFER_BINDING not preserved");
240                 anyMismatch = true;
241             }
242         }
243         
244         var elbuffer = gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING);
245         if (n % 2 == 0) {
246             if (elbuffer == state.elbuffer) {
247                 // Matched
248             } else {
249                 testFailed("ELEMENT_ARRAY_BUFFER_BINDING not preserved");
250                 anyMismatch = true;
251             }
252         } else {
253             if (elbuffer == null) {
254                 // Matched
255             } else {
256                 testFailed("ELEMENT_ARRAY_BUFFER_BINDING not preserved");
257                 anyMismatch = true;
258             }
259         }
260     }
261     ext.bindVertexArrayOES(null);
262     if (!anyMismatch) {
263         testPassed("All attributes preserved across bindings");
264     }
265     
266     for (var n = 0; n < attrCount; n++) {
267         var state = states[n];
268         ext.deleteVertexArrayOES(state.vao);
269     }
270 }
271
272 function runAttributeValueTests() {
273     debug("Testing that attribute values are not attached to bindings");
274     
275     var v;
276     var vao0 = ext.createVertexArrayOES();
277     var anyFailed = false;
278     
279     ext.bindVertexArrayOES(null);
280     gl.vertexAttrib4f(0, 0, 1, 2, 3);
281     
282     v = gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB);
283     if (!(v[0] == 0 && v[1] == 1 && v[2] == 2 && v[3] == 3)) {
284         testFailed("Vertex attrib value not round-tripped?");
285         anyFailed = true;
286     }
287     
288     ext.bindVertexArrayOES(vao0);
289     
290     v = gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB);
291     if (!(v[0] == 0 && v[1] == 1 && v[2] == 2 && v[3] == 3)) {
292         testFailed("Vertex attrib value reset across bindings");
293         anyFailed = true;
294     }
295     
296     gl.vertexAttrib4f(0, 4, 5, 6, 7);
297     ext.bindVertexArrayOES(null);
298     
299     v = gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB);
300     if (!(v[0] == 4 && v[1] == 5 && v[2] == 6 && v[3] == 7)) {
301         testFailed("Vertex attrib value bound to buffer");
302         anyFailed = true;
303     }
304     
305     if (!anyFailed) {
306         testPassed("Vertex attribute values are not attached to bindings")
307     }
308     
309     ext.bindVertexArrayOES(null);
310     ext.deleteVertexArrayOES(vao0);
311 }
312
313 function runDrawTests() {
314     debug("Testing draws with various VAO bindings");
315     
316     canvas.width = 50; canvas.height = 50;
317     gl.viewport(0, 0, canvas.width, canvas.height);
318     
319     var vao0 = ext.createVertexArrayOES();
320     var vao1 = ext.createVertexArrayOES();
321     
322     var program = wtu.setupSimpleTextureProgram(gl, 0, 1);
323     
324     function setupQuad(s) {
325         var opt_positionLocation = 0;
326         var opt_texcoordLocation = 1;
327         var vertexObject = gl.createBuffer();
328         gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
329         gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
330              1.0 * s,  1.0 * s, 0.0,
331             -1.0 * s,  1.0 * s, 0.0,
332             -1.0 * s, -1.0 * s, 0.0,
333              1.0 * s,  1.0 * s, 0.0,
334             -1.0 * s, -1.0 * s, 0.0,
335              1.0 * s, -1.0 * s, 0.0]), gl.STATIC_DRAW);
336         gl.enableVertexAttribArray(opt_positionLocation);
337         gl.vertexAttribPointer(opt_positionLocation, 3, gl.FLOAT, false, 0, 0);
338
339         var vertexObject = gl.createBuffer();
340         gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
341         gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
342             1.0 * s, 1.0 * s,
343             0.0 * s, 1.0 * s,
344             0.0 * s, 0.0 * s,
345             1.0 * s, 1.0 * s,
346             0.0 * s, 0.0 * s,
347             1.0 * s, 0.0 * s]), gl.STATIC_DRAW);
348         gl.enableVertexAttribArray(opt_texcoordLocation);
349         gl.vertexAttribPointer(opt_texcoordLocation, 2, gl.FLOAT, false, 0, 0);
350     };
351     
352     function readLocation(x, y) {
353         var pixels = new Uint8Array(1 * 1 * 4);
354         gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
355         return pixels;
356     };
357     function testPixel(blackList, whiteList) {
358         function testList(list, expected) {
359             for (var n = 0; n < list.length; n++) {
360                 var l = list[n];
361                 var x = -Math.floor(l * canvas.width / 2) + canvas.width / 2;
362                 var y = -Math.floor(l * canvas.height / 2) + canvas.height / 2;
363                 var source = readLocation(x, y);
364                 if (Math.abs(source[0] - expected) > 2) {
365                     return false;
366                 }
367             }
368             return true;
369         }
370         return testList(blackList, 0) && testList(whiteList, 255);
371     };
372     function verifyDraw(drawNumber, s) {
373         wtu.drawQuad(gl);
374         var blackList = [];
375         var whiteList = [];
376         var points = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0];
377         for (var n = 0; n < points.length; n++) {
378             if (points[n] <= s) {
379                 blackList.push(points[n]);
380             } else {
381                 whiteList.push(points[n]);
382             }
383         }
384         if (testPixel(blackList, whiteList)) {
385             testPassed("Draw " + drawNumber + " passed pixel test");
386         } else {
387             testFailed("Draw " + drawNumber + " failed pixel test");
388         }
389     };
390     
391     // Setup all bindings
392     setupQuad(1);
393     ext.bindVertexArrayOES(vao0);
394     setupQuad(0.5);
395     ext.bindVertexArrayOES(vao1);
396     setupQuad(0.25);
397     
398     // Verify drawing
399     ext.bindVertexArrayOES(null);
400     verifyDraw(0, 1);
401     ext.bindVertexArrayOES(vao0);
402     verifyDraw(1, 0.5);
403     ext.bindVertexArrayOES(vao1);
404     verifyDraw(2, 0.25);
405     
406     ext.bindVertexArrayOES(null);
407     ext.deleteVertexArrayOES(vao0);
408     ext.deleteVertexArrayOES(vao1);
409 }
410
411 function runDeleteTests() {
412     debug("Testing using deleted buffers referenced by VAOs");
413
414     var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position", "a_color"]);
415     gl.useProgram(program);
416
417     var positionBuffer = gl.createBuffer();
418     gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
419     gl.bufferData(
420         gl.ARRAY_BUFFER,
421         new Float32Array([
422            1.0,  1.0,
423           -1.0,  1.0,
424           -1.0, -1.0,
425            1.0, -1.0]),
426         gl.STATIC_DRAW);
427
428     var colors = [
429       [255,   0,   0, 255],
430       [  0, 255,   0, 255],
431       [  0,   0, 255, 255],
432       [  0, 255, 255, 255]
433     ];
434     var colorBuffers = [];
435     var elementBuffers = [];
436     var vaos = [];
437     for (var ii = 0; ii < colors.length; ++ii) {
438       var vao = ext.createVertexArrayOES();
439       vaos.push(vao);
440       ext.bindVertexArrayOES(vao);
441       // Set the position buffer
442       gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
443       gl.enableVertexAttribArray(0);
444       gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
445
446       var elementBuffer = gl.createBuffer();
447       elementBuffers.push(elementBuffer);
448       gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
449       gl.bufferData(
450           gl.ELEMENT_ARRAY_BUFFER,
451           new Uint8Array([0, 1, 2, 0, 2, 3]),
452           gl.STATIC_DRAW);
453
454       // Setup the color attrib
455       var color = colors[ii];
456       if (ii < 3) {
457         var colorBuffer = gl.createBuffer();
458         colorBuffers.push(colorBuffer);
459         gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
460         gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(
461           [ color[0], color[1], color[2], color[3],
462             color[0], color[1], color[2], color[3],
463             color[0], color[1], color[2], color[3],
464             color[0], color[1], color[2], color[3]
465           ]), gl.STATIC_DRAW);
466         gl.enableVertexAttribArray(1);
467         gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, 0);
468       } else {
469         gl.vertexAttrib4f(1, color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255);
470       }
471     }
472
473     // delete the color buffers AND the position buffer.
474     ext.bindVertexArrayOES(null);
475     for (var ii = 0; ii < colorBuffers.length; ++ii) {
476       gl.deleteBuffer(colorBuffers[ii]);
477       gl.deleteBuffer(elementBuffers[ii]);
478       // The buffers should still be valid at this point, since it was attached to the VAO
479       if(!gl.isBuffer(colorBuffers[ii])) {
480         testFailed("buffer removed too early");
481       }
482     }
483     gl.deleteBuffer(positionBuffer);
484
485     // Render with the deleted buffers. As they are referenced by VAOs they
486     // must still be around.
487     for (var ii = 0; ii < colors.length; ++ii) {
488       var color = colors[ii];
489       ext.bindVertexArrayOES(vaos[ii]);
490       gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
491       wtu.checkCanvas(gl, color, "should be " + color);
492     }
493
494     // Clean up.
495     for (var ii = 0; ii < colorBuffers.length; ++ii) {
496       ext.deleteVertexArrayOES(vaos[ii]);
497     }
498
499     for (var ii = 0; ii < colorBuffers.length; ++ii) {
500       // The buffers should no longer be valid now that the VAOs are deleted
501       if(gl.isBuffer(colorBuffers[ii])) {
502         testFailed("buffer not properly cleaned up after VAO deletion");
503       }
504     }
505 }
506
507 function runArrayBufferBindTests() {
508     debug("Testing that VAOs don't effect ARRAY_BUFFER binding.");
509
510     ext.bindVertexArrayOES(null);
511
512     var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_color", "a_position"]);
513     gl.useProgram(program);
514
515     // create shared element buuffer
516     var elementBuffer = gl.createBuffer();
517     // bind to default
518     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
519     gl.bufferData(
520         gl.ELEMENT_ARRAY_BUFFER,
521         new Uint8Array([0, 1, 2, 0, 2, 3]),
522         gl.STATIC_DRAW);
523
524     // first create the buffers for no vao draw.
525     var nonVAOColorBuffer = gl.createBuffer();
526     gl.bindBuffer(gl.ARRAY_BUFFER, nonVAOColorBuffer);
527     gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(
528       [ 0, 255, 0, 255,
529         0, 255, 0, 255,
530         0, 255, 0, 255,
531         0, 255, 0, 255,
532       ]), gl.STATIC_DRAW);
533
534     // shared position buffer.
535     var positionBuffer = gl.createBuffer();
536     gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
537     gl.bufferData(
538         gl.ARRAY_BUFFER,
539         new Float32Array([
540            1.0,  1.0,
541           -1.0,  1.0,
542           -1.0, -1.0,
543            1.0, -1.0]),
544         gl.STATIC_DRAW);
545
546     // attach position buffer to default
547     gl.enableVertexAttribArray(1);
548     gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
549
550     // now create vao
551     var vao = ext.createVertexArrayOES();
552     ext.bindVertexArrayOES(vao);
553
554     // attach the position buffer vao
555     gl.enableVertexAttribArray(1);
556     gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
557
558     var vaoColorBuffer = gl.createBuffer();
559     gl.enableVertexAttribArray(0);
560     gl.vertexAttribPointer(0, 4, gl.UNSIGNED_BYTE, true, 0, 0);
561     gl.bindBuffer(gl.ARRAY_BUFFER, vaoColorBuffer);
562     gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array(
563       [ 255, 0, 0, 255,
564         255, 0, 0, 255,
565         255, 0, 0, 255,
566         255, 0, 0, 255,
567       ]), gl.STATIC_DRAW);
568     gl.enableVertexAttribArray(0);
569     gl.vertexAttribPointer(0, 4, gl.UNSIGNED_BYTE, true, 0, 0);
570
571     // now set the buffer back to the nonVAOColorBuffer
572     gl.bindBuffer(gl.ARRAY_BUFFER, nonVAOColorBuffer);
573
574     // bind to vao
575     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
576     gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
577     wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red");
578
579     // unbind vao
580     ext.bindVertexArrayOES(null);
581
582     // At this point the nonVAOColorBuffer should be still be bound.
583     // If the WebGL impl is emulating VAOs it must make sure
584     // it correctly restores this binding.
585     gl.enableVertexAttribArray(0);
586     gl.vertexAttribPointer(0, 4, gl.UNSIGNED_BYTE, true, 0, 0);
587     gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
588     wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
589 }
590
591 debug("");
592 successfullyParsed = true;
593 </script>
594 <script src="../../resources/js-test-post.js"></script>
595
596 </body>
597 </html>