tor-browser

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

element-index-uint.html (16431B)


      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 Uint element indices 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 
     16 <script id="vs" type="x-shader/x-vertex">
     17 attribute vec4 vPosition;
     18 attribute vec4 vColor;
     19 varying vec4 color;
     20 void main() {
     21    gl_Position = vPosition;
     22    color = vColor;
     23 }
     24 </script>
     25 <script id="fs" type="x-shader/x-fragment">
     26 precision mediump float;
     27 varying vec4 color;
     28 void main() {
     29  gl_FragColor = color;
     30 }
     31 </script>
     32 <script id="vsCheckOutOfBounds" type="x-shader/x-vertex">
     33    precision mediump float;
     34    attribute vec2 position;
     35    attribute vec4 vecRandom;
     36    varying vec4 v_color;
     37 
     38    // Per the spec, each component can either contain existing contents
     39    // of the buffer or 0.
     40    bool testFloatComponent(float component) {
     41        return (component == 0.2 || component == 0.0);
     42    }
     43    // The last component is additionally allowed to be 1.0.
     44    bool testLastFloatComponent(float component) {
     45        return testFloatComponent(component) || component == 1.0;
     46    }
     47 
     48    void main() {
     49        if (testFloatComponent(vecRandom.x) &&
     50            testFloatComponent(vecRandom.y) &&
     51            testFloatComponent(vecRandom.z) &&
     52            testLastFloatComponent(vecRandom.w)) {
     53            v_color = vec4(0.0, 1.0, 0.0, 1.0); // green -- Out of range
     54        } else {
     55            v_color = vec4(1.0, 0.0, 0.0, 1.0); // red -- Unexpected value
     56        }
     57        gl_Position = vec4(position, 0.0, 1.0);
     58    }
     59 </script>
     60 
     61 </head>
     62 <body>
     63 <div id="description"></div>
     64 <div id="console"></div>
     65 <script>
     66 "use strict";
     67 description("This test verifies the functionality of the Uint element indices.");
     68 
     69 debug("");
     70 
     71 var wtu = WebGLTestUtils;
     72 var gl = null;
     73 var canvas = null;
     74 
     75 // Test both STATIC_DRAW and DYNAMIC_DRAW as a regression test
     76 // for a bug in ANGLE which has since been fixed.
     77 for (var ii = 0; ii < 2; ++ii) {
     78    canvas = document.createElement("canvas");
     79    canvas.width = 50;
     80    canvas.height = 50;
     81 
     82    gl = wtu.create3DContext(canvas, null, 2);
     83 
     84    if (!gl) {
     85        testFailed("WebGL context does not exist");
     86    } else {
     87        testPassed("WebGL context exists");
     88 
     89        var drawType = (ii == 0) ? gl.STATIC_DRAW : gl.DYNAMIC_DRAW;
     90        debug("Testing " + ((ii == 0) ? "STATIC_DRAW" : "DYNAMIC_DRAW"));
     91 
     92        runDrawTests(drawType);
     93 
     94        // These tests are tweaked duplicates of the buffers/index-validation* tests
     95        // using unsigned int indices to ensure that behavior remains consistent
     96        runIndexValidationTests(drawType);
     97        runIndexOutOfRangeTests(drawType);
     98        runResizedBufferTests(drawType);
     99        runCrashWithBufferSubDataTests(drawType);
    100 
    101        wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
    102    }
    103 }
    104 
    105 function runDrawTests(drawType) {
    106    debug("Test that draws with unsigned integer indices produce the expected results");
    107 
    108    canvas.width = 50; canvas.height = 50;
    109    gl.viewport(0, 0, canvas.width, canvas.height);
    110 
    111    var program = wtu.setupNoTexCoordTextureProgram(gl);
    112 
    113    function setupDraw(s) {
    114        // Create a vertex buffer that cannot be fully indexed via shorts
    115        var quadArrayLen = 65537 * 3;
    116        var quadArray = new Float32Array(quadArrayLen);
    117 
    118        // Leave all but the last 4 values zero-ed out
    119        var idx = quadArrayLen - 12;
    120 
    121        // Initialized the last 4 values to a quad
    122        quadArray[idx++] = 1.0 * s;
    123        quadArray[idx++] = 1.0 * s;
    124        quadArray[idx++] = 0.0;
    125 
    126        quadArray[idx++] = -1.0 * s;
    127        quadArray[idx++] = 1.0 * s;
    128        quadArray[idx++] = 0.0;
    129 
    130        quadArray[idx++] = -1.0 * s;
    131        quadArray[idx++] = -1.0 * s;
    132        quadArray[idx++] = 0.0;
    133 
    134        quadArray[idx++] = 1.0 * s;
    135        quadArray[idx++] = -1.0 * s;
    136        quadArray[idx++] = 0.0;
    137 
    138        var vertexObject = gl.createBuffer();
    139        gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
    140        gl.bufferData(gl.ARRAY_BUFFER, quadArray, drawType);
    141 
    142        // Create an unsigned int index buffer that indexes the last 4 vertices
    143        var baseIndex = (quadArrayLen / 3) - 4;
    144 
    145        var indexObject = gl.createBuffer();
    146        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
    147        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array([
    148            baseIndex + 0,
    149            baseIndex + 1,
    150            baseIndex + 2,
    151            baseIndex + 2,
    152            baseIndex + 3,
    153            baseIndex + 0]), drawType);
    154 
    155        var opt_positionLocation = 0;
    156        gl.enableVertexAttribArray(opt_positionLocation);
    157        gl.vertexAttribPointer(opt_positionLocation, 3, gl.FLOAT, false, 0, 0);
    158    };
    159    function readLocation(x, y) {
    160        var pixels = new Uint8Array(1 * 1 * 4);
    161        gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
    162        return pixels;
    163    };
    164    function testPixel(blockList, allowList) {
    165        function testList(list, expected) {
    166            for (var n = 0; n < list.length; n++) {
    167                var l = list[n];
    168                var x = -Math.floor(l * canvas.width / 2) + canvas.width / 2;
    169                var y = -Math.floor(l * canvas.height / 2) + canvas.height / 2;
    170                var source = readLocation(x, y);
    171                if (Math.abs(source[0] - expected) > 2) {
    172                    return false;
    173                }
    174            }
    175            return true;
    176        }
    177        return testList(blockList, 0) && testList(allowList, 255);
    178    };
    179    function verifyDraw(drawNumber, s) {
    180        gl.clearColor(1.0, 1.0, 1.0, 1.0);
    181        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    182        gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, 0);
    183 
    184        var blockList = [];
    185        var allowList = [];
    186        var points = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0];
    187        for (var n = 0; n < points.length; n++) {
    188            if (points[n] <= s) {
    189                blockList.push(points[n]);
    190            } else {
    191                allowList.push(points[n]);
    192            }
    193        }
    194        if (testPixel(blockList, allowList)) {
    195            testPassed("Draw " + drawNumber + " passed pixel test");
    196        } else {
    197            testFailed("Draw " + drawNumber + " failed pixel test");
    198        }
    199    };
    200 
    201    setupDraw(0.5);
    202    verifyDraw(0, 0.5);
    203 }
    204 
    205 function runIndexValidationTests(drawType) {
    206    description("Tests that index validation verifies the correct number of indices");
    207 
    208    function sizeInBytes(type) {
    209      switch (type) {
    210      case gl.BYTE:
    211      case gl.UNSIGNED_BYTE:
    212        return 1;
    213      case gl.SHORT:
    214      case gl.UNSIGNED_SHORT:
    215        return 2;
    216      case gl.INT:
    217      case gl.UNSIGNED_INT:
    218      case gl.FLOAT:
    219        return 4;
    220      default:
    221        throw "unknown type";
    222      }
    223    }
    224 
    225    var program = wtu.loadStandardProgram(gl);
    226 
    227    // 3 vertices => 1 triangle, interleaved data
    228    var dataComplete = new Float32Array([0, 0, 0, 1,
    229                                         0, 0, 1,
    230                                         1, 0, 0, 1,
    231                                         0, 0, 1,
    232                                         1, 1, 1, 1,
    233                                         0, 0, 1]);
    234    var dataIncomplete = new Float32Array([0, 0, 0, 1,
    235                                           0, 0, 1,
    236                                           1, 0, 0, 1,
    237                                           0, 0, 1,
    238                                           1, 1, 1, 1]);
    239    var indices = new Uint32Array([0, 1, 2]);
    240 
    241    debug("Testing with valid indices");
    242 
    243    var bufferComplete = gl.createBuffer();
    244    gl.bindBuffer(gl.ARRAY_BUFFER, bufferComplete);
    245    gl.bufferData(gl.ARRAY_BUFFER, dataComplete, drawType);
    246    var elements = gl.createBuffer();
    247    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elements);
    248    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, drawType);
    249    gl.useProgram(program);
    250    var vertexLoc = gl.getAttribLocation(program, "a_vertex");
    251    var normalLoc = gl.getAttribLocation(program, "a_normal");
    252    gl.vertexAttribPointer(vertexLoc, 4, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 0);
    253    gl.enableVertexAttribArray(vertexLoc);
    254    gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
    255    gl.enableVertexAttribArray(normalLoc);
    256    shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
    257    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    258    shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
    259    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    260 
    261    var bufferIncomplete = gl.createBuffer();
    262    gl.bindBuffer(gl.ARRAY_BUFFER, bufferIncomplete);
    263    gl.bufferData(gl.ARRAY_BUFFER, dataIncomplete, drawType);
    264    gl.vertexAttribPointer(vertexLoc, 4, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 0);
    265    gl.enableVertexAttribArray(vertexLoc);
    266    gl.disableVertexAttribArray(normalLoc);
    267    debug("Enable vertices, valid");
    268    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    269    shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
    270    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    271 
    272    debug("Test with enabled attribute that does not belong to current program");
    273 
    274    gl.disableVertexAttribArray(normalLoc);
    275    var extraLoc = Math.max(vertexLoc, normalLoc) + 1;
    276    gl.enableVertexAttribArray(extraLoc);
    277    debug("Enable an extra attribute with null");
    278    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    279    shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
    280    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION);
    281    debug("Enable an extra attribute with insufficient data buffer");
    282    gl.vertexAttribPointer(extraLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
    283    wtu.glErrorShouldBe(gl, gl.NO_ERROR);
    284    shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
    285    debug("Pass large negative index to vertexAttribPointer");
    286    gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), -2000000000 * sizeInBytes(gl.FLOAT));
    287    wtu.glErrorShouldBe(gl, gl.INVALID_VALUE);
    288    shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_INT, 0)');
    289 }
    290 
    291 function runIndexOutOfRangeTests(drawType) {
    292    debug("Testing with out-of-range indices");
    293 
    294    var bufferPos = gl.createBuffer();
    295    gl.bindBuffer(gl.ARRAY_BUFFER, bufferPos);
    296    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
    297        1.0,  1.0,
    298        -1.0,  1.0,
    299        -1.0, -1.0,
    300        1.0, -1.0]), drawType);
    301    gl.enableVertexAttribArray(0);
    302    gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
    303 
    304    var bufferIncomplete = gl.createBuffer();
    305    gl.bindBuffer(gl.ARRAY_BUFFER, bufferIncomplete);
    306    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2]), drawType);
    307    gl.enableVertexAttribArray(1);
    308    gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);
    309 
    310    var glProgram = wtu.setupProgram(gl, ["vsCheckOutOfBounds", wtu.simpleVertexColorFragmentShader], ["position", "vecRandom"]);
    311    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Shader and buffer setup successfully");
    312 
    313    var indices = new Uint32Array([0, 1, 2, 0, 2, 3]);
    314    var elements = gl.createBuffer();
    315    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elements);
    316    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, drawType);
    317 
    318    gl.clearColor(0.0, 0.0, 1.0, 1.0);  // Start with blue to indicate no pixels touched.
    319    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    320 
    321 
    322 
    323    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, 0);
    324    var error = gl.getError();
    325    if (error === gl.INVALID_OPERATION) {
    326        testPassed("drawElements flagged INVALID_OPERATION, which is valid so long as all canvas pixels were not touched.");
    327        wtu.checkCanvas(gl, [0, 0, 255, 255]);
    328    } else if (error === gl.NO_ERROR) {
    329        testPassed("drawElements flagged NO_ERROR, which is valid so long as all canvas pixels are green.");
    330        wtu.checkCanvas(gl, [0, 255, 0, 255]);
    331    } else {
    332        testFailed("Invalid error flagged by drawElements. Should be INVALID_OPERATION or NO_ERROR");
    333    }
    334 
    335    debug("Test that client data is always copied during bufferData and bufferSubData calls");
    336 
    337    indices[5] = 1;
    338    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, 0);
    339    var error = gl.getError();
    340    if (error === gl.INVALID_OPERATION) {
    341        testPassed("drawElements flagged INVALID_OPERATION, which is valid so long as all canvas pixels were not touched.");
    342        wtu.checkCanvas(gl, [0, 0, 255, 255]);
    343    } else if (error === gl.NO_ERROR) {
    344        testPassed("drawElements flagged NO_ERROR, which is valid so long as all canvas pixels are green.");
    345        wtu.checkCanvas(gl, [0, 255, 0, 255]);
    346    } else {
    347        testFailed("Invalid error flagged by drawElements. Should be INVALID_OPERATION or NO_ERROR");
    348    }
    349 }
    350 
    351 function runResizedBufferTests(drawType) {
    352    debug("Test that updating the size of a vertex buffer is properly noticed by the WebGL implementation.");
    353 
    354    var program = wtu.setupProgram(gl, ["vs", "fs"], ["vPosition", "vColor"]);
    355    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after initialization");
    356 
    357    var vertexObject = gl.createBuffer();
    358    gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
    359    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
    360        [-1,1,0, 1,1,0, -1,-1,0,
    361         -1,-1,0, 1,1,0, 1,-1,0]), drawType);
    362    gl.enableVertexAttribArray(0);
    363    gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
    364    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after vertex setup");
    365 
    366    var texCoordObject = gl.createBuffer();
    367    gl.bindBuffer(gl.ARRAY_BUFFER, texCoordObject);
    368    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
    369        [0,0, 1,0, 0,1,
    370         0,1, 1,0, 1,1]), drawType);
    371    gl.enableVertexAttribArray(1);
    372    gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
    373    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after texture coord setup");
    374 
    375    // Now resize these buffers because we want to change what we're drawing.
    376    gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
    377    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
    378        -1,1,0, 1,1,0, -1,-1,0, 1,-1,0,
    379        -1,1,0, 1,1,0, -1,-1,0, 1,-1,0]), drawType);
    380    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after vertex redefinition");
    381    gl.bindBuffer(gl.ARRAY_BUFFER, texCoordObject);
    382    gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array([
    383        255, 0, 0, 255,
    384        255, 0, 0, 255,
    385        255, 0, 0, 255,
    386        255, 0, 0, 255,
    387        0, 255, 0, 255,
    388        0, 255, 0, 255,
    389        0, 255, 0, 255,
    390        0, 255, 0, 255]), drawType);
    391    gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, false, 0, 0);
    392    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after texture coordinate / color redefinition");
    393 
    394    var numQuads = 2;
    395    var indices = new Uint32Array(numQuads * 6);
    396    for (var ii = 0; ii < numQuads; ++ii) {
    397        var offset = ii * 6;
    398        var quad = (ii == (numQuads - 1)) ? 4 : 0;
    399        indices[offset + 0] = quad + 0;
    400        indices[offset + 1] = quad + 1;
    401        indices[offset + 2] = quad + 2;
    402        indices[offset + 3] = quad + 2;
    403        indices[offset + 4] = quad + 1;
    404        indices[offset + 5] = quad + 3;
    405    }
    406    var indexObject = gl.createBuffer();
    407    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
    408    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, drawType);
    409    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setting up indices");
    410    gl.drawElements(gl.TRIANGLES, numQuads * 6, gl.UNSIGNED_INT, 0);
    411    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
    412 }
    413 
    414 function runCrashWithBufferSubDataTests(drawType) {
    415    debug('Verifies that the index validation code which is within bufferSubData does not crash.')
    416 
    417    var elementBuffer = gl.createBuffer();
    418    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
    419    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 256, drawType);
    420    var data = new Uint32Array(127);
    421    gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 64, data);
    422    wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "after attempting to update a buffer outside of the allocated bounds");
    423    testPassed("bufferSubData, when buffer object was initialized with null, did not crash");
    424 }
    425 
    426 debug("");
    427 var successfullyParsed = true;
    428 </script>
    429 <script src="../../js/js-test-post.js"></script>
    430 
    431 </body>
    432 </html>