2 Copyright (c) 2019 The Khronos Group Inc.
3 Use of this source code is governed by an MIT-style license that can be
4 found in the LICENSE.txt file.
10 <meta charset=
"utf-8">
11 <title>WebGL OES_vertex_array_object Conformance Tests
</title>
12 <link rel=
"stylesheet" href=
"../../resources/js-test-style.css"/>
13 <script src=
"../../js/js-test-pre.js"></script>
14 <script src=
"../../js/webgl-test-utils.js"></script>
15 <!-- comment in the script tag below to test through JS emulation of the extension. -->
17 <script src="../../../demos/google/resources/OESVertexArrayObject.js"></script>
21 <div id=
"description"></div>
22 <canvas id=
"canvas" style=
"width: 50px; height: 50px;"> </canvas>
23 <div id=
"console"></div>
24 <script id=
"vshader" type=
"x-shader/x-vertex">
25 attribute vec4 a_position;
26 attribute vec4 a_color;
29 gl_Position = a_position;
33 <script id=
"fshader" type=
"x-shader/x-fragment">
34 precision mediump float;
37 gl_FragColor = v_color;
42 description("This test verifies the functionality of the OES_vertex_array_object extension, if it is available.");
46 var wtu
= WebGLTestUtils
;
47 var canvas
= document
.getElementById("canvas");
48 var gl
= wtu
.create3DContext(canvas
);
60 testFailed("WebGL context does not exist");
62 testPassed("WebGL context exists");
64 // Setup emulated OESVertexArrayObject if it has been included.
65 if (window
.setupVertexArrayObject
) {
66 debug("using emulated OES_vertex_array_object");
67 setupVertexArrayObject(gl
);
70 // Run tests with extension disabled
71 runBindingTestDisabled();
73 // Query the extension and store globally so shouldBe can access it
74 ext
= gl
.getExtension("OES_vertex_array_object");
76 testPassed("No OES_vertex_array_object support -- this is legal");
78 runSupportedTest(false);
80 testPassed("Successfully enabled OES_vertex_array_object extension");
82 runSupportedTest(true);
83 runBindingTestEnabled();
86 runAttributeValueTests();
88 runUnboundDeleteTests();
89 runBoundDeleteTests();
90 runArrayBufferBindTests();
91 runInvalidContextTests();
92 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "there should be no errors");
96 function runSupportedTest(extensionEnabled
) {
97 var supported
= gl
.getSupportedExtensions();
98 if (supported
.indexOf("OES_vertex_array_object") >= 0) {
99 if (extensionEnabled
) {
100 testPassed("OES_vertex_array_object listed as supported and getExtension succeeded");
102 testFailed("OES_vertex_array_object listed as supported but getExtension failed");
105 if (extensionEnabled
) {
106 testFailed("OES_vertex_array_object not listed as supported but getExtension succeeded");
108 testPassed("OES_vertex_array_object not listed as supported and getExtension failed -- this is legal");
113 function runBindingTestDisabled() {
115 debug("Testing binding enum with extension disabled");
117 // Use the constant directly as we don't have the extension
118 var VERTEX_ARRAY_BINDING_OES
= 0x85B5;
120 gl
.getParameter(VERTEX_ARRAY_BINDING_OES
);
121 wtu
.glErrorShouldBe(gl
, gl
.INVALID_ENUM
, "VERTEX_ARRAY_BINDING_OES should not be queryable if extension is disabled");
124 function runBindingTestEnabled() {
126 debug("Testing binding enum with extension enabled");
128 shouldBe("ext.VERTEX_ARRAY_BINDING_OES", "0x85B5");
130 gl
.getParameter(ext
.VERTEX_ARRAY_BINDING_OES
);
131 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "VERTEX_ARRAY_BINDING_OES query should succeed if extension is enabled");
133 // Default value is null
134 if (gl
.getParameter(ext
.VERTEX_ARRAY_BINDING_OES
) === null) {
135 testPassed("Default value of VERTEX_ARRAY_BINDING_OES is null");
137 testFailed("Default value of VERTEX_ARRAY_BINDING_OES is not null");
141 debug("Testing binding a VAO");
142 var vao0
= ext
.createVertexArrayOES();
143 var vao1
= ext
.createVertexArrayOES();
144 shouldBeNull("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES)");
145 ext
.bindVertexArrayOES(vao0
);
146 if (gl
.getParameter(ext
.VERTEX_ARRAY_BINDING_OES
) == vao0
) {
147 testPassed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is expected VAO");
149 testFailed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is not expected VAO")
151 ext
.bindVertexArrayOES(vao1
);
152 if (gl
.getParameter(ext
.VERTEX_ARRAY_BINDING_OES
) == vao1
) {
153 testPassed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is expected VAO");
155 testFailed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is not expected VAO")
157 ext
.deleteVertexArrayOES(vao1
);
158 shouldBeNull("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES)");
159 ext
.bindVertexArrayOES(vao1
);
160 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "binding a deleted vertex array object");
161 ext
.bindVertexArrayOES(null);
162 shouldBeNull("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES)");
163 ext
.deleteVertexArrayOES(vao1
);
166 function runObjectTest() {
168 debug("Testing object creation");
170 vao
= ext
.createVertexArrayOES();
171 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "createVertexArrayOES should not set an error");
172 shouldBeNonNull("vao");
174 // Expect false if never bound
175 shouldBeFalse("ext.isVertexArrayOES(vao)");
176 ext
.bindVertexArrayOES(vao
);
177 shouldBeTrue("ext.isVertexArrayOES(vao)");
178 ext
.bindVertexArrayOES(null);
179 shouldBeTrue("ext.isVertexArrayOES(vao)");
181 shouldBeFalse("ext.isVertexArrayOES(null)");
183 ext
.deleteVertexArrayOES(vao
);
187 function runAttributeTests() {
189 debug("Testing attributes work across bindings");
193 var attrCount
= gl
.getParameter(gl
.MAX_VERTEX_ATTRIBS
);
194 for (var n
= 0; n
< attrCount
; n
++) {
195 gl
.bindBuffer(gl
.ARRAY_BUFFER
, null);
196 gl
.bindBuffer(gl
.ELEMENT_ARRAY_BUFFER
, null);
201 var vao
= state
.vao
= ext
.createVertexArrayOES();
202 ext
.bindVertexArrayOES(vao
);
204 var enableArray
= (n
% 2 == 0);
206 gl
.enableVertexAttribArray(n
);
208 gl
.disableVertexAttribArray(n
);
212 var buffer
= state
.buffer
= gl
.createBuffer();
213 gl
.bindBuffer(gl
.ARRAY_BUFFER
, buffer
);
214 gl
.bufferData(gl
.ARRAY_BUFFER
, 1024, gl
.STATIC_DRAW
);
216 gl
.vertexAttribPointer(n
, 1 + n
% 4, gl
.FLOAT
, true, n
* 4, n
* 4);
220 var elbuffer
= state
.elbuffer
= gl
.createBuffer();
221 gl
.bindBuffer(gl
.ELEMENT_ARRAY_BUFFER
, elbuffer
);
222 gl
.bufferData(gl
.ELEMENT_ARRAY_BUFFER
, 1024, gl
.STATIC_DRAW
);
225 ext
.bindVertexArrayOES(null);
228 var anyMismatch
= false;
229 for (var n
= 0; n
< attrCount
; n
++) {
230 var state
= states
[n
];
232 ext
.bindVertexArrayOES(state
.vao
);
234 var shouldBeEnabled
= (n
% 2 == 0);
235 var isEnabled
= gl
.getVertexAttrib(n
, gl
.VERTEX_ATTRIB_ARRAY_ENABLED
);
236 if (shouldBeEnabled
!= isEnabled
) {
237 testFailed("VERTEX_ATTRIB_ARRAY_ENABLED not preserved");
241 var buffer
= gl
.getVertexAttrib(n
, gl
.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
);
242 if (shouldBeEnabled
) {
243 if (buffer
== state
.buffer
) {
245 if ((gl
.getVertexAttrib(n
, gl
.VERTEX_ATTRIB_ARRAY_SIZE
) == 1 + n
% 4) &&
246 (gl
.getVertexAttrib(n
, gl
.VERTEX_ATTRIB_ARRAY_TYPE
) == gl
.FLOAT
) &&
247 (gl
.getVertexAttrib(n
, gl
.VERTEX_ATTRIB_ARRAY_NORMALIZED
) == true) &&
248 (gl
.getVertexAttrib(n
, gl
.VERTEX_ATTRIB_ARRAY_STRIDE
) == n
* 4) &&
249 (gl
.getVertexAttribOffset(n
, gl
.VERTEX_ATTRIB_ARRAY_POINTER
) == n
* 4)) {
252 testFailed("VERTEX_ATTRIB_ARRAY_* not preserved");
256 testFailed("VERTEX_ATTRIB_ARRAY_BUFFER_BINDING not preserved");
260 // GL_CURRENT_VERTEX_ATTRIB is not preserved
262 testFailed("VERTEX_ATTRIB_ARRAY_BUFFER_BINDING not preserved");
267 var elbuffer
= gl
.getParameter(gl
.ELEMENT_ARRAY_BUFFER_BINDING
);
268 if (shouldBeEnabled
) {
269 if (elbuffer
== state
.elbuffer
) {
272 testFailed("ELEMENT_ARRAY_BUFFER_BINDING not preserved");
276 if (elbuffer
== null) {
279 testFailed("ELEMENT_ARRAY_BUFFER_BINDING not preserved");
284 ext
.bindVertexArrayOES(null);
286 testPassed("All attributes preserved across bindings");
289 for (var n
= 0; n
< attrCount
; n
++) {
290 var state
= states
[n
];
291 ext
.deleteVertexArrayOES(state
.vao
);
295 function runAttributeValueTests() {
297 debug("Testing that attribute values are not attached to bindings");
300 var vao0
= ext
.createVertexArrayOES();
301 var anyFailed
= false;
303 ext
.bindVertexArrayOES(null);
304 gl
.vertexAttrib4f(0, 0, 1, 2, 3);
306 v
= gl
.getVertexAttrib(0, gl
.CURRENT_VERTEX_ATTRIB
);
307 if (!(v
[0] == 0 && v
[1] == 1 && v
[2] == 2 && v
[3] == 3)) {
308 testFailed("Vertex attrib value not round-tripped?");
312 ext
.bindVertexArrayOES(vao0
);
314 v
= gl
.getVertexAttrib(0, gl
.CURRENT_VERTEX_ATTRIB
);
315 if (!(v
[0] == 0 && v
[1] == 1 && v
[2] == 2 && v
[3] == 3)) {
316 testFailed("Vertex attrib value reset across bindings");
320 gl
.vertexAttrib4f(0, 4, 5, 6, 7);
321 ext
.bindVertexArrayOES(null);
323 v
= gl
.getVertexAttrib(0, gl
.CURRENT_VERTEX_ATTRIB
);
324 if (!(v
[0] == 4 && v
[1] == 5 && v
[2] == 6 && v
[3] == 7)) {
325 testFailed("Vertex attrib value bound to buffer");
330 testPassed("Vertex attribute values are not attached to bindings")
333 ext
.bindVertexArrayOES(null);
334 ext
.deleteVertexArrayOES(vao0
);
337 function runDrawTests() {
339 debug("Testing draws with various VAO bindings");
341 canvas
.width
= 50; canvas
.height
= 50;
342 gl
.viewport(0, 0, canvas
.width
, canvas
.height
);
344 var vao0
= ext
.createVertexArrayOES();
345 var vao1
= ext
.createVertexArrayOES();
346 var vao2
= ext
.createVertexArrayOES();
348 var positionLocation
= 0;
349 var colorLocation
= 1;
351 var program
= wtu
.setupSimpleVertexColorProgram(gl
, positionLocation
, colorLocation
);
353 function setupQuad(s
, colorsInArray
) {
354 var vertexObject
= gl
.createBuffer();
355 gl
.bindBuffer(gl
.ARRAY_BUFFER
, vertexObject
);
356 gl
.bufferData(gl
.ARRAY_BUFFER
, new Float32Array([
357 1.0 * s
, 1.0 * s
, 0.0,
358 -1.0 * s
, 1.0 * s
, 0.0,
359 -1.0 * s
, -1.0 * s
, 0.0,
360 1.0 * s
, 1.0 * s
, 0.0,
361 -1.0 * s
, -1.0 * s
, 0.0,
362 1.0 * s
, -1.0 * s
, 0.0]), gl
.STATIC_DRAW
);
363 gl
.enableVertexAttribArray(positionLocation
);
364 gl
.vertexAttribPointer(positionLocation
, 3, gl
.FLOAT
, false, 0, 0);
366 // Test switching between VAOs that have different number of enabled arrays
368 var vertexObject
= gl
.createBuffer();
369 gl
.bindBuffer(gl
.ARRAY_BUFFER
, vertexObject
);
370 gl
.bufferData(gl
.ARRAY_BUFFER
, new Float32Array([
376 0.0, 0.0, 0.0, 1.0]), gl
.STATIC_DRAW
);
377 gl
.enableVertexAttribArray(colorLocation
);
378 gl
.vertexAttribPointer(colorLocation
, 4, gl
.FLOAT
, false, 0, 0);
380 gl
.disableVertexAttribArray(colorLocation
);
384 function verifyDiagonalPixels(s
, expectedInside
, drawDescription
) {
385 // Tests pixels along a diagonal running from the center of the canvas to the (0, 0) corner.
386 // Values on the points list indicate relative position along this diagonal.
387 var points
= [0.0, 0.2, 0.4, 0.6, 0.8, 1.0];
388 for (var n
= 0; n
< points
.length
; n
++) {
389 var expected
= points
[n
] <= s
? expectedInside
: 255;
390 var x
= Math
.round((1 - points
[n
]) * canvas
.width
/ 2);
391 var y
= Math
.round((1 - points
[n
]) * canvas
.height
/ 2);
392 wtu
.checkCanvasRect(gl
, x
, y
, 1, 1, [expected
, expected
, expected
, 255],
393 "Drawing " + drawDescription
+ " should pass", 2);
396 function verifyDraw(drawDescription
, s
, colorsInArray
) {
397 wtu
.clearAndDrawUnitQuad(gl
);
398 var expectedInside
= colorsInArray
? 0 : 128;
399 verifyDiagonalPixels(s
, expectedInside
, drawDescription
);
402 // Setup all bindings
404 ext
.bindVertexArrayOES(vao0
);
405 setupQuad(0.5, true);
406 ext
.bindVertexArrayOES(vao1
);
407 setupQuad(0.25, true);
408 ext
.bindVertexArrayOES(vao2
);
409 setupQuad(0.75, false);
411 gl
.vertexAttrib4f(colorLocation
, 0.5, 0.5, 0.5, 1);
414 ext
.bindVertexArrayOES(null);
415 verifyDraw("with the default VAO", 1, true);
416 ext
.bindVertexArrayOES(vao0
);
417 verifyDraw("with VAO #0", 0.5, true);
418 ext
.bindVertexArrayOES(vao1
);
419 verifyDraw("with VAO #1", 0.25, true);
420 ext
.bindVertexArrayOES(vao2
);
421 verifyDraw("with VAO that has the color array disabled", 0.75, false);
423 // Verify bound VAO after delete
424 ext
.bindVertexArrayOES(vao1
);
425 ext
.deleteVertexArrayOES(vao0
);
426 verifyDraw("after deleting another VAO", 0.25, true);
427 ext
.deleteVertexArrayOES(vao1
);
428 verifyDraw("after deleting the VAO that was bound", 1, true);
430 // Disable global vertex attrib array
431 gl
.disableVertexAttribArray(positionLocation
);
432 gl
.disableVertexAttribArray(colorLocation
);
434 // Check that constant values are treated correctly as not being part of VAO state.
438 wtu
.setupIndexedQuad(gl
, gridRes
, positionLoc
);
439 // Set the vertex color to red.
440 gl
.vertexAttrib4f(colorLoc
, 1, 0, 0, 1);
442 var vao0
= ext
.createVertexArrayOES();
443 ext
.bindVertexArrayOES(vao0
);
444 var program
= wtu
.setupSimpleVertexColorProgram(gl
, positionLoc
, colorLoc
);
445 wtu
.setupIndexedQuad(gl
, gridRes
, positionLoc
);
446 // Set the vertex color to green.
447 gl
.vertexAttrib4f(colorLoc
, 0, 1, 0, 1);
448 wtu
.clearAndDrawIndexedQuad(gl
, gridRes
);
449 wtu
.checkCanvas(gl
, [0, 255, 0, 255], "should be green");
450 ext
.deleteVertexArrayOES(vao0
);
451 wtu
.clearAndDrawIndexedQuad(gl
, gridRes
);
452 wtu
.checkCanvas(gl
, [0, 255, 0, 255], "should be green");
455 function runUnboundDeleteTests() {
457 debug("Testing using buffers that are deleted when attached to unbound VAOs");
459 var program
= wtu
.setupProgram(gl
, ["vshader", "fshader"], ["a_position", "a_color"]);
460 gl
.useProgram(program
);
462 var positionBuffer
= gl
.createBuffer();
463 gl
.bindBuffer(gl
.ARRAY_BUFFER
, positionBuffer
);
479 var colorBuffers
= [];
480 var elementBuffers
= [];
482 for (var ii
= 0; ii
< colors
.length
; ++ii
) {
483 var vao
= ext
.createVertexArrayOES();
485 ext
.bindVertexArrayOES(vao
);
486 // Set the position buffer
487 gl
.bindBuffer(gl
.ARRAY_BUFFER
, positionBuffer
);
488 gl
.enableVertexAttribArray(0);
489 gl
.vertexAttribPointer(0, 2, gl
.FLOAT
, false, 0, 0);
491 var elementBuffer
= gl
.createBuffer();
492 elementBuffers
.push(elementBuffer
);
493 gl
.bindBuffer(gl
.ELEMENT_ARRAY_BUFFER
, elementBuffer
);
495 gl
.ELEMENT_ARRAY_BUFFER
,
496 new Uint8Array([0, 1, 2, 0, 2, 3]),
499 // Setup the color attrib
500 var color
= colors
[ii
];
502 var colorBuffer
= gl
.createBuffer();
503 colorBuffers
.push(colorBuffer
);
504 gl
.bindBuffer(gl
.ARRAY_BUFFER
, colorBuffer
);
505 gl
.bufferData(gl
.ARRAY_BUFFER
, new Uint8Array(
506 [ color
[0], color
[1], color
[2], color
[3],
507 color
[0], color
[1], color
[2], color
[3],
508 color
[0], color
[1], color
[2], color
[3],
509 color
[0], color
[1], color
[2], color
[3]
511 gl
.enableVertexAttribArray(1);
512 gl
.vertexAttribPointer(1, 4, gl
.UNSIGNED_BYTE
, true, 0, 0);
514 gl
.vertexAttrib4f(1, color
[0] / 255, color
[1] / 255, color
[2] / 255, color
[3] / 255);
518 // delete the color buffers AND the position buffer.
519 ext
.bindVertexArrayOES(null);
520 for (var ii
= 0; ii
< colorBuffers
.length
; ++ii
) {
521 gl
.deleteBuffer(colorBuffers
[ii
]);
522 gl
.deleteBuffer(elementBuffers
[ii
]);
523 ext
.bindVertexArrayOES(vaos
[ii
]);
524 var boundBuffer
= gl
.getVertexAttrib(1, gl
.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
);
525 // The buffers should still be valid at this point, since it was attached to the VAO
526 if(boundBuffer
!= colorBuffers
[ii
]) {
527 testFailed("buffer removed even though it is still attached to a VAO");
531 ext
.bindVertexArrayOES(null);
532 gl
.deleteBuffer(positionBuffer
);
534 // Render with the deleted buffers. As they are referenced by VAOs they
535 // must still be around.
536 for (var ii
= 0; ii
< colors
.length
; ++ii
) {
537 var color
= colors
[ii
];
538 ext
.bindVertexArrayOES(vaos
[ii
]);
539 gl
.drawElements(gl
.TRIANGLES
, 6, gl
.UNSIGNED_BYTE
, 0);
540 wtu
.checkCanvas(gl
, color
, "should be " + color
);
544 for (var ii
= 0; ii
< colorBuffers
.length
; ++ii
) {
545 ext
.deleteVertexArrayOES(vaos
[ii
]);
548 for (var ii
= 0; ii
< colorBuffers
.length
; ++ii
) {
549 // The buffers should no longer be valid now that the VAOs are deleted
550 if(gl
.isBuffer(colorBuffers
[ii
])) {
551 testFailed("buffer not properly cleaned up after VAO deletion");
556 function runBoundDeleteTests() {
557 debug("Testing using buffers that are deleted when attached to bound VAOs");
559 var program
= wtu
.setupProgram(gl
, ["vshader", "fshader"], ["a_position", "a_color"]);
560 gl
.useProgram(program
);
562 var positionBuffer
= gl
.createBuffer();
563 gl
.bindBuffer(gl
.ARRAY_BUFFER
, positionBuffer
);
573 // Setup the color attrib
574 var colorBuffer
= gl
.createBuffer();
575 gl
.bindBuffer(gl
.ARRAY_BUFFER
, colorBuffer
);
576 gl
.bufferData(gl
.ARRAY_BUFFER
, new Uint8Array(
584 var elementBuffers
= [];
585 for (var ii
= 0; ii
< 4; ++ii
) {
586 var vao
= ext
.createVertexArrayOES();
588 ext
.bindVertexArrayOES(vao
);
590 gl
.bindBuffer(gl
.ARRAY_BUFFER
, positionBuffer
);
591 gl
.enableVertexAttribArray(0);
592 gl
.vertexAttribPointer(0, 2, gl
.FLOAT
, false, 0, 0);
594 var elementBuffer
= gl
.createBuffer();
595 elementBuffers
.push(elementBuffer
);
596 gl
.bindBuffer(gl
.ELEMENT_ARRAY_BUFFER
, elementBuffer
);
598 gl
.ELEMENT_ARRAY_BUFFER
,
599 new Uint8Array([0, 1, 2, 0, 2, 3]),
602 gl
.bindBuffer(gl
.ARRAY_BUFFER
, colorBuffer
);
603 gl
.enableVertexAttribArray(1);
604 gl
.vertexAttribPointer(1, 4, gl
.UNSIGNED_BYTE
, true, 0, 0);
607 // delete the color buffers AND the position buffer, that are bound to the current VAO
608 for (var ii
= 0; ii
< vaos
.length
; ++ii
) {
609 ext
.bindVertexArrayOES(vaos
[ii
]);
611 gl
.deleteBuffer(colorBuffer
);
612 gl
.deleteBuffer(positionBuffer
);
614 // After the first iteration, deleteBuffer will be a no-op, and will not unbind its matching
615 // bind points on the now-bound VAO like it did on the first iteration.
616 var expectRetained
= (ii
!= 0);
617 var shouldBeStr
= (expectRetained
? "retained" : "cleared");
619 var boundPositionBuffer
= gl
.getVertexAttrib(0, gl
.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
);
620 if (expectRetained
!= (boundPositionBuffer
== positionBuffer
)) {
621 testFailed("Position attrib stored buffer should be " + shouldBeStr
+ ".");
624 var boundColorBuffer
= gl
.getVertexAttrib(1, gl
.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
);
625 if (expectRetained
!= (boundColorBuffer
== colorBuffer
)) {
626 testFailed("Color attrib stored buffer should be " + shouldBeStr
+ ".");
629 // If retained, everything should still work. If cleared, drawing should now fail.
630 gl
.drawElements(gl
.TRIANGLES
, 6, gl
.UNSIGNED_BYTE
, 0);
631 var expectedError
= (expectRetained
? gl
.NO_ERROR
: gl
.INVALID_OPERATION
);
632 wtu
.glErrorShouldBe(gl
, expectedError
,
633 "Draw call should " + (expectRetained
? "not " : "") + "fail.");
635 if (gl
.isBuffer(positionBuffer
)) {
636 testFailed("References from unbound VAOs don't keep Position buffer alive.");
638 if (gl
.isBuffer(colorBuffer
)) {
639 testFailed("References from unbound VAOs don't keep Color buffer alive");
644 function runArrayBufferBindTests() {
646 debug("Testing that buffer bindings on VAOs don't affect default VAO ARRAY_BUFFER binding.");
648 ext
.bindVertexArrayOES(null);
650 var program
= wtu
.setupProgram(gl
, ["vshader", "fshader"], ["a_color", "a_position"]);
651 gl
.useProgram(program
);
653 // create shared element buffer
654 var elementBuffer
= gl
.createBuffer();
656 gl
.bindBuffer(gl
.ELEMENT_ARRAY_BUFFER
, elementBuffer
);
658 gl
.ELEMENT_ARRAY_BUFFER
,
659 new Uint8Array([0, 1, 2, 0, 2, 3]),
662 // first create the buffers for no VAO draw.
663 var nonVAOColorBuffer
= gl
.createBuffer();
664 gl
.bindBuffer(gl
.ARRAY_BUFFER
, nonVAOColorBuffer
);
665 gl
.bufferData(gl
.ARRAY_BUFFER
, new Uint8Array(
672 // shared position buffer.
673 var positionBuffer
= gl
.createBuffer();
674 gl
.bindBuffer(gl
.ARRAY_BUFFER
, positionBuffer
);
684 // attach position buffer to default
685 gl
.enableVertexAttribArray(1);
686 gl
.vertexAttribPointer(1, 2, gl
.FLOAT
, false, 0, 0);
689 var vao
= ext
.createVertexArrayOES();
690 ext
.bindVertexArrayOES(vao
);
692 // attach the position buffer VAO
693 gl
.enableVertexAttribArray(1);
694 gl
.vertexAttribPointer(1, 2, gl
.FLOAT
, false, 0, 0);
696 var vaoColorBuffer
= gl
.createBuffer();
697 gl
.bindBuffer(gl
.ARRAY_BUFFER
, vaoColorBuffer
);
698 gl
.bufferData(gl
.ARRAY_BUFFER
, new Uint8Array(
704 gl
.enableVertexAttribArray(0);
705 gl
.vertexAttribPointer(0, 4, gl
.UNSIGNED_BYTE
, true, 0, 0);
707 // now set the buffer back to the nonVAOColorBuffer
708 gl
.bindBuffer(gl
.ARRAY_BUFFER
, nonVAOColorBuffer
);
711 gl
.bindBuffer(gl
.ELEMENT_ARRAY_BUFFER
, elementBuffer
);
712 gl
.drawElements(gl
.TRIANGLES
, 6, gl
.UNSIGNED_BYTE
, 0);
713 wtu
.checkCanvas(gl
, [255, 0, 0, 255], "should be red");
716 ext
.bindVertexArrayOES(null);
718 // At this point the nonVAOColorBuffer should be still be bound.
719 // If the WebGL impl is emulating VAOs it must make sure
720 // it correctly restores this binding.
721 gl
.enableVertexAttribArray(0);
722 gl
.vertexAttribPointer(0, 4, gl
.UNSIGNED_BYTE
, true, 0, 0);
723 gl
.drawElements(gl
.TRIANGLES
, 6, gl
.UNSIGNED_BYTE
, 0);
724 wtu
.checkCanvas(gl
, [0, 255, 0, 255], "should be green");
727 function runInvalidContextTests() {
728 contextA
= wtu
.create3DContext(undefined, undefined, 1);
729 contextB
= wtu
.create3DContext(undefined, undefined, 1);
730 extA
= contextA
.getExtension("OES_vertex_array_object");
731 extB
= contextB
.getExtension("OES_vertex_array_object");
732 vertexArrayA
= extA
.createVertexArrayOES();
733 vertexArrayB
= extB
.createVertexArrayOES();
735 wtu
.shouldGenerateGLError(contextA
, contextA
.NO_ERROR
, "extA.bindVertexArrayOES(vertexArrayA)");
736 wtu
.shouldGenerateGLError(contextA
, contextA
.NO_ERROR
, "extA.bindVertexArrayOES(null)");
737 wtu
.shouldGenerateGLError(contextB
, contextB
.NO_ERROR
, "extB.bindVertexArrayOES(vertexArrayB)");
738 wtu
.shouldGenerateGLError(contextB
, contextB
.NO_ERROR
, "extB.bindVertexArrayOES(null)");
741 debug("State queries validate context");
742 shouldBeFalse("extA.isVertexArrayOES(vertexArrayB)");
743 wtu
.glErrorShouldBe(contextA
, gl
.NO_ERROR
, "there should be no errors from invalid request");
744 shouldBeFalse("extB.isVertexArrayOES(vertexArrayA)");
745 wtu
.glErrorShouldBe(contextB
, gl
.NO_ERROR
, "there should be no errors from invalid request");
746 shouldBeTrue("extA.isVertexArrayOES(vertexArrayA)");
747 wtu
.glErrorShouldBe(contextA
, gl
.NO_ERROR
, "there should be no errors from valid request");
748 shouldBeTrue("extB.isVertexArrayOES(vertexArrayB)");
749 wtu
.glErrorShouldBe(contextB
, gl
.NO_ERROR
, "there should be no errors from valid request");
752 debug("Deleting an object from another context generates an error");
753 wtu
.shouldGenerateGLError(contextA
, contextA
.INVALID_OPERATION
, "extA.deleteVertexArrayOES(vertexArrayB)");
754 wtu
.shouldGenerateGLError(contextB
, contextB
.INVALID_OPERATION
, "extB.deleteVertexArrayOES(vertexArrayA)");
757 debug("Invalid delete operations do not delete");
758 shouldBeTrue("extA.isVertexArrayOES(vertexArrayA)");
759 shouldBeTrue("extB.isVertexArrayOES(vertexArrayB)");
762 debug("Cannot bind VAOs from other contexts");
763 wtu
.shouldGenerateGLError(contextA
, contextA
.INVALID_OPERATION
, "extA.bindVertexArrayOES(vertexArrayB)");
764 wtu
.shouldGenerateGLError(contextB
, contextB
.INVALID_OPERATION
, "extB.bindVertexArrayOES(vertexArrayA)");
767 debug("Context checks happen even for deleted objects");
768 wtu
.shouldGenerateGLError(contextA
, contextA
.NO_ERROR
, "extA.deleteVertexArrayOES(vertexArrayA)");
769 wtu
.shouldGenerateGLError(contextB
, contextB
.NO_ERROR
, "extB.deleteVertexArrayOES(vertexArrayB)");
770 wtu
.shouldGenerateGLError(contextA
, contextA
.INVALID_OPERATION
, "extA.deleteVertexArrayOES(vertexArrayB)");
771 wtu
.shouldGenerateGLError(contextB
, contextB
.INVALID_OPERATION
, "extB.deleteVertexArrayOES(vertexArrayA)");
775 var successfullyParsed
= true;
777 <script src=
"../../js/js-test-post.js"></script>