tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

vertex-array-object.html (22318B)


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