oes-vertex-array-object.html (28249B)
1 <!-- 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. 5 --> 6 7 <!DOCTYPE html> 8 <html> 9 <head> 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. --> 16 <!-- 17 <script src="../../../demos/google/resources/OESVertexArrayObject.js"></script> 18 --> 19 </head> 20 <body> 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; 27 varying vec4 v_color; 28 void main(void) { 29 gl_Position = a_position; 30 v_color = a_color; 31 } 32 </script> 33 <script id="fshader" type="x-shader/x-fragment"> 34 precision mediump float; 35 varying vec4 v_color; 36 void main(void) { 37 gl_FragColor = v_color; 38 } 39 </script> 40 <script> 41 "use strict"; 42 description("This test verifies the functionality of the OES_vertex_array_object extension, if it is available."); 43 44 debug(""); 45 46 var wtu = WebGLTestUtils; 47 var canvas = document.getElementById("canvas"); 48 var gl = wtu.create3DContext(canvas); 49 var ext = null; 50 var vao = null; 51 52 var contextA; 53 var contextB; 54 var extA; 55 var extB; 56 var vertexArrayA; 57 var vertexArrayB; 58 59 if (!gl) { 60 testFailed("WebGL context does not exist"); 61 } else { 62 testPassed("WebGL context exists"); 63 64 // Setup emulated OESVertexArrayObject if it has been included. 65 if (window.setupVertexArrayObject) { 66 debug("using emulated OES_vertex_array_object"); 67 setupVertexArrayObject(gl); 68 } 69 70 // Run tests with extension disabled 71 runBindingTestDisabled(); 72 73 // Query the extension and store globally so shouldBe can access it 74 ext = gl.getExtension("OES_vertex_array_object"); 75 if (!ext) { 76 testPassed("No OES_vertex_array_object support -- this is legal"); 77 78 runSupportedTest(false); 79 } else { 80 testPassed("Successfully enabled OES_vertex_array_object extension"); 81 82 runSupportedTest(true); 83 runBindingTestEnabled(); 84 runObjectTest(); 85 runAttributeTests(); 86 runAttributeValueTests(); 87 runDrawTests(); 88 runUnboundDeleteTests(); 89 runBoundDeleteTests(); 90 runArrayBufferBindTests(); 91 runInvalidContextTests(); 92 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); 93 } 94 } 95 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"); 101 } else { 102 testFailed("OES_vertex_array_object listed as supported but getExtension failed"); 103 } 104 } else { 105 if (extensionEnabled) { 106 testFailed("OES_vertex_array_object not listed as supported but getExtension succeeded"); 107 } else { 108 testPassed("OES_vertex_array_object not listed as supported and getExtension failed -- this is legal"); 109 } 110 } 111 } 112 113 function runBindingTestDisabled() { 114 debug(""); 115 debug("Testing binding enum with extension disabled"); 116 117 // Use the constant directly as we don't have the extension 118 var VERTEX_ARRAY_BINDING_OES = 0x85B5; 119 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"); 122 } 123 124 function runBindingTestEnabled() { 125 debug(""); 126 debug("Testing binding enum with extension enabled"); 127 128 shouldBe("ext.VERTEX_ARRAY_BINDING_OES", "0x85B5"); 129 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"); 132 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"); 136 } else { 137 testFailed("Default value of VERTEX_ARRAY_BINDING_OES is not null"); 138 } 139 140 debug(""); 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"); 148 } else { 149 testFailed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is not expected VAO") 150 } 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"); 154 } else { 155 testFailed("gl.getParameter(ext.VERTEX_ARRAY_BINDING_OES) is not expected VAO") 156 } 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); 164 } 165 166 function runObjectTest() { 167 debug(""); 168 debug("Testing object creation"); 169 170 vao = ext.createVertexArrayOES(); 171 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "createVertexArrayOES should not set an error"); 172 shouldBeNonNull("vao"); 173 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)"); 180 181 shouldBeFalse("ext.isVertexArrayOES(null)"); 182 183 ext.deleteVertexArrayOES(vao); 184 vao = null; 185 } 186 187 function runAttributeTests() { 188 debug(""); 189 debug("Testing attributes work across bindings"); 190 191 var states = []; 192 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); 197 198 var state = {}; 199 states.push(state); 200 201 var vao = state.vao = ext.createVertexArrayOES(); 202 ext.bindVertexArrayOES(vao); 203 204 var enableArray = (n % 2 == 0); 205 if (enableArray) { 206 gl.enableVertexAttribArray(n); 207 } else { 208 gl.disableVertexAttribArray(n); 209 } 210 211 if (enableArray) { 212 var buffer = state.buffer = gl.createBuffer(); 213 gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 214 gl.bufferData(gl.ARRAY_BUFFER, 1024, gl.STATIC_DRAW); 215 216 gl.vertexAttribPointer(n, 1 + n % 4, gl.FLOAT, true, n * 4, n * 4); 217 } 218 219 if (enableArray) { 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); 223 } 224 225 ext.bindVertexArrayOES(null); 226 } 227 228 var anyMismatch = false; 229 for (var n = 0; n < attrCount; n++) { 230 var state = states[n]; 231 232 ext.bindVertexArrayOES(state.vao); 233 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"); 238 anyMismatch = true; 239 } 240 241 var buffer = gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING); 242 if (shouldBeEnabled) { 243 if (buffer == state.buffer) { 244 // Matched 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)) { 250 // Matched 251 } else { 252 testFailed("VERTEX_ATTRIB_ARRAY_* not preserved"); 253 anyMismatch = true; 254 } 255 } else { 256 testFailed("VERTEX_ATTRIB_ARRAY_BUFFER_BINDING not preserved"); 257 anyMismatch = true; 258 } 259 } else { 260 // GL_CURRENT_VERTEX_ATTRIB is not preserved 261 if (buffer) { 262 testFailed("VERTEX_ATTRIB_ARRAY_BUFFER_BINDING not preserved"); 263 anyMismatch = true; 264 } 265 } 266 267 var elbuffer = gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING); 268 if (shouldBeEnabled) { 269 if (elbuffer == state.elbuffer) { 270 // Matched 271 } else { 272 testFailed("ELEMENT_ARRAY_BUFFER_BINDING not preserved"); 273 anyMismatch = true; 274 } 275 } else { 276 if (elbuffer == null) { 277 // Matched 278 } else { 279 testFailed("ELEMENT_ARRAY_BUFFER_BINDING not preserved"); 280 anyMismatch = true; 281 } 282 } 283 } 284 ext.bindVertexArrayOES(null); 285 if (!anyMismatch) { 286 testPassed("All attributes preserved across bindings"); 287 } 288 289 for (var n = 0; n < attrCount; n++) { 290 var state = states[n]; 291 ext.deleteVertexArrayOES(state.vao); 292 } 293 } 294 295 function runAttributeValueTests() { 296 debug(""); 297 debug("Testing that attribute values are not attached to bindings"); 298 299 var v; 300 var vao0 = ext.createVertexArrayOES(); 301 var anyFailed = false; 302 303 ext.bindVertexArrayOES(null); 304 gl.vertexAttrib4f(0, 0, 1, 2, 3); 305 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?"); 309 anyFailed = true; 310 } 311 312 ext.bindVertexArrayOES(vao0); 313 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"); 317 anyFailed = true; 318 } 319 320 gl.vertexAttrib4f(0, 4, 5, 6, 7); 321 ext.bindVertexArrayOES(null); 322 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"); 326 anyFailed = true; 327 } 328 329 if (!anyFailed) { 330 testPassed("Vertex attribute values are not attached to bindings") 331 } 332 333 ext.bindVertexArrayOES(null); 334 ext.deleteVertexArrayOES(vao0); 335 } 336 337 function runDrawTests() { 338 debug(""); 339 debug("Testing draws with various VAO bindings"); 340 341 canvas.width = 50; canvas.height = 50; 342 gl.viewport(0, 0, canvas.width, canvas.height); 343 344 var vao0 = ext.createVertexArrayOES(); 345 var vao1 = ext.createVertexArrayOES(); 346 var vao2 = ext.createVertexArrayOES(); 347 348 var positionLocation = 0; 349 var colorLocation = 1; 350 351 var program = wtu.setupSimpleVertexColorProgram(gl, positionLocation, colorLocation); 352 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); 365 366 // Test switching between VAOs that have different number of enabled arrays 367 if (colorsInArray) { 368 var vertexObject = gl.createBuffer(); 369 gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); 370 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 371 0.0, 0.0, 0.0, 1.0, 372 0.0, 0.0, 0.0, 1.0, 373 0.0, 0.0, 0.0, 1.0, 374 0.0, 0.0, 0.0, 1.0, 375 0.0, 0.0, 0.0, 1.0, 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); 379 } else { 380 gl.disableVertexAttribArray(colorLocation); 381 } 382 }; 383 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); 394 } 395 }; 396 function verifyDraw(drawDescription, s, colorsInArray) { 397 wtu.clearAndDrawUnitQuad(gl); 398 var expectedInside = colorsInArray ? 0 : 128; 399 verifyDiagonalPixels(s, expectedInside, drawDescription); 400 }; 401 402 // Setup all bindings 403 setupQuad(1, true); 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); 410 411 gl.vertexAttrib4f(colorLocation, 0.5, 0.5, 0.5, 1); 412 413 // Verify drawing 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); 422 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); 429 430 // Disable global vertex attrib array 431 gl.disableVertexAttribArray(positionLocation); 432 gl.disableVertexAttribArray(colorLocation); 433 434 // Check that constant values are treated correctly as not being part of VAO state. 435 var positionLoc = 0; 436 var colorLoc = 1; 437 var gridRes = 1; 438 wtu.setupIndexedQuad(gl, gridRes, positionLoc); 439 // Set the vertex color to red. 440 gl.vertexAttrib4f(colorLoc, 1, 0, 0, 1); 441 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"); 453 } 454 455 function runUnboundDeleteTests() { 456 debug(""); 457 debug("Testing using buffers that are deleted when attached to unbound VAOs"); 458 459 var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position", "a_color"]); 460 gl.useProgram(program); 461 462 var positionBuffer = gl.createBuffer(); 463 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 464 gl.bufferData( 465 gl.ARRAY_BUFFER, 466 new Float32Array([ 467 1.0, 1.0, 468 -1.0, 1.0, 469 -1.0, -1.0, 470 1.0, -1.0]), 471 gl.STATIC_DRAW); 472 473 var colors = [ 474 [255, 0, 0, 255], 475 [ 0, 255, 0, 255], 476 [ 0, 0, 255, 255], 477 [ 0, 255, 255, 255] 478 ]; 479 var colorBuffers = []; 480 var elementBuffers = []; 481 var vaos = []; 482 for (var ii = 0; ii < colors.length; ++ii) { 483 var vao = ext.createVertexArrayOES(); 484 vaos.push(vao); 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); 490 491 var elementBuffer = gl.createBuffer(); 492 elementBuffers.push(elementBuffer); 493 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer); 494 gl.bufferData( 495 gl.ELEMENT_ARRAY_BUFFER, 496 new Uint8Array([0, 1, 2, 0, 2, 3]), 497 gl.STATIC_DRAW); 498 499 // Setup the color attrib 500 var color = colors[ii]; 501 if (ii < 3) { 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] 510 ]), gl.STATIC_DRAW); 511 gl.enableVertexAttribArray(1); 512 gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, 0); 513 } else { 514 gl.vertexAttrib4f(1, color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255); 515 } 516 } 517 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"); 528 } 529 } 530 531 ext.bindVertexArrayOES(null); 532 gl.deleteBuffer(positionBuffer); 533 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); 541 } 542 543 // Clean up. 544 for (var ii = 0; ii < colorBuffers.length; ++ii) { 545 ext.deleteVertexArrayOES(vaos[ii]); 546 } 547 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"); 552 } 553 } 554 } 555 556 function runBoundDeleteTests() { 557 debug("Testing using buffers that are deleted when attached to bound VAOs"); 558 559 var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position", "a_color"]); 560 gl.useProgram(program); 561 562 var positionBuffer = gl.createBuffer(); 563 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 564 gl.bufferData( 565 gl.ARRAY_BUFFER, 566 new Float32Array([ 567 1.0, 1.0, 568 -1.0, 1.0, 569 -1.0, -1.0, 570 1.0, -1.0]), 571 gl.STATIC_DRAW); 572 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( 577 [ 255, 0, 0, 255, 578 0, 255, 0, 255, 579 0, 0, 255, 255, 580 0, 255, 255, 255 581 ]), gl.STATIC_DRAW); 582 583 var vaos = []; 584 var elementBuffers = []; 585 for (var ii = 0; ii < 4; ++ii) { 586 var vao = ext.createVertexArrayOES(); 587 vaos.push(vao); 588 ext.bindVertexArrayOES(vao); 589 590 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 591 gl.enableVertexAttribArray(0); 592 gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0); 593 594 var elementBuffer = gl.createBuffer(); 595 elementBuffers.push(elementBuffer); 596 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer); 597 gl.bufferData( 598 gl.ELEMENT_ARRAY_BUFFER, 599 new Uint8Array([0, 1, 2, 0, 2, 3]), 600 gl.STATIC_DRAW); 601 602 gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 603 gl.enableVertexAttribArray(1); 604 gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, 0); 605 } 606 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]); 610 611 gl.deleteBuffer(colorBuffer); 612 gl.deleteBuffer(positionBuffer); 613 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"); 618 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 + "."); 622 } 623 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 + "."); 627 } 628 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."); 634 635 if (gl.isBuffer(positionBuffer)) { 636 testFailed("References from unbound VAOs don't keep Position buffer alive."); 637 } 638 if (gl.isBuffer(colorBuffer)) { 639 testFailed("References from unbound VAOs don't keep Color buffer alive"); 640 } 641 } 642 } 643 644 function runArrayBufferBindTests() { 645 debug(""); 646 debug("Testing that buffer bindings on VAOs don't affect default VAO ARRAY_BUFFER binding."); 647 648 ext.bindVertexArrayOES(null); 649 650 var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_color", "a_position"]); 651 gl.useProgram(program); 652 653 // create shared element buffer 654 var elementBuffer = gl.createBuffer(); 655 // bind to default 656 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer); 657 gl.bufferData( 658 gl.ELEMENT_ARRAY_BUFFER, 659 new Uint8Array([0, 1, 2, 0, 2, 3]), 660 gl.STATIC_DRAW); 661 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( 666 [ 0, 255, 0, 255, 667 0, 255, 0, 255, 668 0, 255, 0, 255, 669 0, 255, 0, 255, 670 ]), gl.STATIC_DRAW); 671 672 // shared position buffer. 673 var positionBuffer = gl.createBuffer(); 674 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 675 gl.bufferData( 676 gl.ARRAY_BUFFER, 677 new Float32Array([ 678 1.0, 1.0, 679 -1.0, 1.0, 680 -1.0, -1.0, 681 1.0, -1.0]), 682 gl.STATIC_DRAW); 683 684 // attach position buffer to default 685 gl.enableVertexAttribArray(1); 686 gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0); 687 688 // now create VAO 689 var vao = ext.createVertexArrayOES(); 690 ext.bindVertexArrayOES(vao); 691 692 // attach the position buffer VAO 693 gl.enableVertexAttribArray(1); 694 gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0); 695 696 var vaoColorBuffer = gl.createBuffer(); 697 gl.bindBuffer(gl.ARRAY_BUFFER, vaoColorBuffer); 698 gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array( 699 [ 255, 0, 0, 255, 700 255, 0, 0, 255, 701 255, 0, 0, 255, 702 255, 0, 0, 255, 703 ]), gl.STATIC_DRAW); 704 gl.enableVertexAttribArray(0); 705 gl.vertexAttribPointer(0, 4, gl.UNSIGNED_BYTE, true, 0, 0); 706 707 // now set the buffer back to the nonVAOColorBuffer 708 gl.bindBuffer(gl.ARRAY_BUFFER, nonVAOColorBuffer); 709 710 // bind to VAO 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"); 714 715 // unbind VAO 716 ext.bindVertexArrayOES(null); 717 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"); 725 } 726 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(); 734 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)"); 739 740 debug("") 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"); 750 751 debug("") 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)"); 755 756 debug("") 757 debug("Invalid delete operations do not delete"); 758 shouldBeTrue("extA.isVertexArrayOES(vertexArrayA)"); 759 shouldBeTrue("extB.isVertexArrayOES(vertexArrayB)"); 760 761 debug("") 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)"); 765 766 debug("") 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)"); 772 } 773 774 debug(""); 775 var successfullyParsed = true; 776 </script> 777 <script src="../../js/js-test-post.js"></script> 778 779 </body> 780 </html>