tor-browser

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

read-pixels-pack-parameters.html (16406B)


      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 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
     12 <script src="../../js/js-test-pre.js"></script>
     13 <script src="../../js/webgl-test-utils.js"></script>
     14 </head>
     15 <body>
     16 <canvas id="example" width="4" height="4"></canvas>
     17 <div id="description"></div>
     18 <div id="console"></div>
     19 <script>
     20 "use strict"
     21 
     22 var wtu = WebGLTestUtils;
     23 var initialColor = [1, 2, 3, 4];
     24 var expectedColor = [[249, 102, 0, 255],
     25                     [2, 200, 102, 255],
     26                     [134, 87, 234, 255],
     27                     [99, 5, 76, 255]];
     28 
     29 function calculatePaddingBytes(bytesPerPixel, packAlignment, width)
     30 {
     31    var padding = 0;
     32    switch (packAlignment) {
     33    case 1:
     34    case 2:
     35    case 4:
     36    case 8:
     37        padding = (bytesPerPixel * width) % packAlignment;
     38        if (padding > 0)
     39            padding = packAlignment - padding;
     40        return padding;
     41    default:
     42        testFailed("should not reach here");
     43        return;
     44    }
     45 }
     46 
     47 function paintWebGLCanvas(gl)
     48 {
     49    var program = wtu.setupTexturedQuad(gl);
     50    gl.disable(gl.DEPTH_TEST);
     51    gl.disable(gl.BLEND);
     52 
     53    var data = new Uint8Array(4 * 4);
     54    for (var ii = 0; ii < 4; ++ii) {
     55        data[ii * 4] = expectedColor[ii][0];
     56        data[ii * 4 + 1] = expectedColor[ii][1];
     57        data[ii * 4 + 2] = expectedColor[ii][2];
     58        data[ii * 4 + 3] = expectedColor[ii][3];
     59    }
     60 
     61    var tex = gl.createTexture();
     62    gl.bindTexture(gl.TEXTURE_2D, tex);
     63    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
     64 
     65    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
     66    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
     67    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
     68    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
     69 
     70    var loc = gl.getUniformLocation(program, "tex");
     71    gl.uniform1i(loc, 0);
     72 
     73    wtu.clearAndDrawUnitQuad(gl);
     74 }
     75 
     76 function samePixel(array, index, refPixel, row, pixelTag)
     77 {
     78    for (var ii = 0; ii < refPixel.length; ++ii) {
     79      if (array[index] == refPixel[ii][0] &&
     80          array[index + 1] == refPixel[ii][1] &&
     81          array[index + 2] == refPixel[ii][2] &&
     82          array[index + 3] == refPixel[ii][3]) {
     83          return true;
     84      }
     85    }
     86    var refPixelText = "";
     87    for (var ii = 0; ii < refPixel.length; ++ii) {
     88        if (ii > 0)
     89            refPixelText += " or ";
     90        refPixelText += "[" + refPixel[ii] + "]";
     91    }
     92    testFailed(pixelTag + " pixel of row " + row + ": expected " + refPixelText + ", got [" +
     93        [array[index], array[index + 1], array[index + 2], array[index + 3]] + "]");
     94    return false;
     95 }
     96 
     97 function runTestIteration(xoffset, yoffset, width, height, packParams, usePixelPackBuffer, packParamsValid)
     98 {
     99    if (!("alignment" in packParams))
    100        packParams.alignment = 4;
    101    if (!("rowLength" in packParams))
    102        packParams.rowLength = 0;
    103    if (!("skipPixels" in packParams))
    104        packParams.skipPixels = 0;
    105    if (!("skipRows" in packParams))
    106        packParams.skipRows = 0;
    107    debug("Testing xoffset = " + xoffset + ", yoffset " + yoffset +
    108          ", width = " + width + ", height = " + height +
    109          ", PACK_ALIGNMENT = " + packParams.alignment + ", PACK_ROW_LENGTH = " + packParams.rowLength +
    110          ", PACK_SKIP_PIXELS = " + packParams.skipPixels + " , PACK_SKIP_ROWS = " + packParams.skipRows);
    111    gl.pixelStorei(gl.PACK_ALIGNMENT, packParams.alignment);
    112    gl.pixelStorei(gl.PACK_ROW_LENGTH, packParams.rowLength);
    113    gl.pixelStorei(gl.PACK_SKIP_PIXELS, packParams.skipPixels);
    114    gl.pixelStorei(gl.PACK_SKIP_ROWS, packParams.skipRows);
    115 
    116    var actualWidth = packParams.rowLength > 0 ? packParams.rowLength : width;
    117 
    118    var bytesPerPixel = 4; // see readPixels' parameters below, the format is gl.RGBA, type is gl.UNSIGNED_BYTE
    119    var padding = calculatePaddingBytes(bytesPerPixel, packParams.alignment, actualWidth);
    120    var bytesPerRow = actualWidth * bytesPerPixel + padding;
    121 
    122    var size = bytesPerRow * (height - 1) + bytesPerPixel * width;
    123    var skipSize = packParams.skipPixels * bytesPerPixel + packParams.skipRows * bytesPerRow;
    124    var array = new Uint8Array(skipSize + size);
    125    for (var ii = 0; ii < skipSize + size; ++ii) {
    126        array[ii] = initialColor[ii % bytesPerPixel];
    127    }
    128    var arrayWrongSize = null;
    129    if (size > 0)
    130        arrayWrongSize = new Uint8Array(skipSize + size - 1);
    131    if (usePixelPackBuffer) {
    132        var offset = 0;
    133 
    134        var buffer = gl.createBuffer();
    135        gl.bindBuffer(gl.PIXEL_PACK_BUFFER, buffer);
    136        if (size > 0) {
    137            gl.bufferData(gl.PIXEL_PACK_BUFFER, arrayWrongSize, gl.STATIC_DRAW);
    138            gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, offset);
    139            wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
    140        }
    141        gl.bufferData(gl.PIXEL_PACK_BUFFER, array, gl.STATIC_DRAW);
    142        gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, offset);
    143    } else {
    144        if (size > 0) {
    145            gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, arrayWrongSize);
    146            wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
    147        }
    148        gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, array);
    149    }
    150    if (packParamsValid) {
    151        wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readPixels should succeed");
    152    } else {
    153        wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Invalid pack params combination");
    154        return;
    155    }
    156 
    157    if (size == 0)
    158        return;
    159 
    160    if (usePixelPackBuffer) {
    161        array = new Uint8Array(skipSize + size);
    162        gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, array);
    163    }
    164 
    165    // Check skipped bytes are unchanged.
    166    for (var ii = 0; ii < skipSize; ++ii) {
    167        if (array[ii] != initialColor[ii % bytesPerPixel]) {
    168            testFailed("skipped bytes changed at index " + ii + ": expected " +
    169                       initialColor[ii % bytesPerPixel] + " got " + array[ii]);
    170            break;
    171        }
    172    }
    173    // Check the first and last pixels of each row.
    174    var canvasWidth = 4;
    175    var canvasHeight = 4;
    176    for (var row = 0; row < height; ++row) {
    177        var refColor;
    178        var yIndex = yoffset + row;
    179        var xIndex;
    180 
    181        // First pixel
    182        var pos = skipSize + bytesPerRow * row;
    183        xIndex = xoffset;
    184        if (xIndex < 0 || xIndex >= canvasWidth || yIndex < 0 || yIndex >= canvasHeight) {
    185            if (row > 0 && usePixelPackBuffer && packParams.rowLength > 0 && packParams.rowLength < width)
    186                refColor = [initialColor, expectedColor[yIndex - 1]];
    187            else
    188                refColor = [initialColor];
    189        } else {
    190            refColor = [expectedColor[yIndex]];
    191        }
    192        samePixel(array, pos, refColor, row, "first");
    193 
    194        // Last pixel
    195        var xSpan;
    196        if (row + 1 == height || packParams.rowLength > width)
    197            xSpan = width;
    198        else
    199            xSpan = actualWidth;
    200        xIndex = xoffset + xSpan - 1;
    201        pos += (xSpan - 1) * bytesPerPixel;
    202        if (xIndex < 0 || xIndex >= canvasWidth || yIndex < 0 || yIndex >= canvasHeight) {
    203            if (row > 0 && usePixelPackBuffer && packParams.rowLength > 0 && packParams.rowLength < width)
    204                refColor = [initialColor, expectedColor[yIndex - 1]];
    205            else
    206                refColor = [initialColor];
    207        } else {
    208            refColor = [expectedColor[yIndex]];
    209        }
    210        samePixel(array, pos, refColor, row, "last");
    211 
    212        // Check padding bytes are unchanged and bytes beyond rowLength set correctly.
    213        pos += bytesPerPixel;
    214        if (row + 1 < height) {
    215            // Beyond bytes filled for PACK_ROW_LENGTH, the row could have extra bytes due to
    216            // padding. These extra bytes could be either filled with pixel data if
    217            // PACK_ROW_LENGTH is set to be less than width, or they could be left unchanged
    218            // if they are beyond |width| pixels.
    219            if (packParams.rowLength > 0 && packParams.rowLength < width) {
    220                var trailingBytes = Math.min((width - packParams.rowLength) * bytesPerPixel,
    221                                             bytesPerRow - packParams.rowLength * bytesPerPixel);
    222                for (var ii = 0; ii < trailingBytes; ++ii) {
    223                    if (array[pos + ii] != refColor[0][ii % bytesPerPixel]) {
    224                        testFailed("Trailing byte " + ii + " after rowLength of row " + row + " : expected " +
    225                                   refColor[0][ii % bytesPerPixel] + ", got " + array[pos + ii]);
    226                        break;
    227                    }
    228                }
    229                pos += trailingBytes;
    230            }
    231            var paddingBytes = skipSize + bytesPerRow * (row + 1) - pos;
    232            for (var ii = 0; ii < paddingBytes; ++ii) {
    233                if (array[pos + ii] != initialColor[ii % bytesPerPixel]) {
    234                    testFailed("Padding byte " + ii + " of row " + row + " changed: expected " +
    235                               initialColor[ii % bytesPerPixel] + ", got " + array[pos + ii]);
    236                    break;
    237                }
    238            }
    239        }
    240    }
    241 }
    242 
    243 function testPackParameters(usePixelPackBuffer)
    244 {
    245    debug("");
    246    var destText = usePixelPackBuffer ? "PIXEL_PACK buffer" : "array buffer";
    247    debug("Verify that reading pixels to " + destText + " works fine with various pack alignments.");
    248    runTestIteration(0, 0, 1, 3, {alignment:1}, usePixelPackBuffer, true);
    249    runTestIteration(0, 0, 1, 3, {alignment:2}, usePixelPackBuffer, true);
    250    runTestIteration(0, 0, 1, 3, {alignment:4}, usePixelPackBuffer, true);
    251    runTestIteration(0, 0, 1, 3, {alignment:8}, usePixelPackBuffer, true);
    252    runTestIteration(0, 0, 2, 3, {alignment:4}, usePixelPackBuffer, true);
    253    runTestIteration(0, 0, 2, 3, {alignment:8}, usePixelPackBuffer, true);
    254    runTestIteration(0, 0, 3, 3, {alignment:4}, usePixelPackBuffer, true);
    255    runTestIteration(0, 0, 3, 3, {alignment:8}, usePixelPackBuffer, true);
    256    runTestIteration(0, 0, 0, 0, {alignment:1}, usePixelPackBuffer, true);
    257    runTestIteration(0, 0, 1, 3, {alignment:4}, usePixelPackBuffer, true);
    258    runTestIteration(0, 0, 1, 3, {alignment:8}, usePixelPackBuffer, true);
    259 
    260    debug("");
    261    debug("Verify that reading pixels to " + destText + " is disallowed when PACK_ROW_LENGTH < width.");
    262    runTestIteration(0, 0, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
    263    runTestIteration(-1, 0, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
    264    runTestIteration(0, -1, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
    265    runTestIteration(-1, -1, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
    266    runTestIteration(-5, 0, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
    267    runTestIteration(0, -5, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
    268    runTestIteration(2, 0, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
    269    runTestIteration(0, 2, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
    270    runTestIteration(2, 2, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
    271    runTestIteration(5, 0, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
    272    runTestIteration(0, 5, 3, 3, {alignment:8, rowLength:2}, usePixelPackBuffer, false);
    273    runTestIteration(0, 0, 3, 3, {alignment:8, rowLength:1}, usePixelPackBuffer, false);
    274 
    275    debug("");
    276    debug("Verify that reading pixels to " + destText + " works fine with PACK_ROW_LENGTH == width.");
    277    runTestIteration(0, 0, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
    278    runTestIteration(-1, 0, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
    279    runTestIteration(0, -1, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
    280    runTestIteration(-1, -1, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
    281    runTestIteration(-5, 0, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
    282    runTestIteration(0, -5, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
    283    runTestIteration(2, 0, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
    284    runTestIteration(0, 2, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
    285    runTestIteration(2, 2, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
    286    runTestIteration(5, 0, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
    287    runTestIteration(0, 5, 3, 3, {alignment:8, rowLength:3}, usePixelPackBuffer, true);
    288 
    289    debug("");
    290    debug("Verify that reading pixels to " + destText + " works fine with PACK_ROW_LENGTH > width and with no padding");
    291    runTestIteration(0, 0, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
    292    runTestIteration(-1, 0, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
    293    runTestIteration(0, -1, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
    294    runTestIteration(-1, -1, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
    295    runTestIteration(-5, 0, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
    296    runTestIteration(0, -5, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
    297    runTestIteration(2, 0, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
    298    runTestIteration(0, 2, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
    299    runTestIteration(2, 2, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
    300    runTestIteration(5, 0, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
    301    runTestIteration(0, 5, 3, 3, {alignment:8, rowLength:4}, usePixelPackBuffer, true);
    302 
    303    debug("");
    304    debug("Verify that reading pixels to " + destText + " works fine with PACK_ROW_LENGTH > width and with padding");
    305    runTestIteration(0, 0, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
    306    runTestIteration(-1, 0, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
    307    runTestIteration(0, -1, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
    308    runTestIteration(-1, -1, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
    309    runTestIteration(-5, 0, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
    310    runTestIteration(0, -5, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
    311    runTestIteration(2, 0, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
    312    runTestIteration(0, 2, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
    313    runTestIteration(2, 2, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
    314    runTestIteration(5, 0, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
    315    runTestIteration(0, 5, 3, 3, {alignment:8, rowLength:5}, usePixelPackBuffer, true);
    316 
    317    debug("");
    318    debug("Verify that reading pixels to " + destText + " works fine with pack skip parameters.");
    319    runTestIteration(0, 0, 3, 3, {alignment:8, skipPixels:2}, usePixelPackBuffer, false);
    320    runTestIteration(0, 0, 3, 3, {alignment:8, skipPixels:1, skipRows:3}, usePixelPackBuffer, false);
    321    runTestIteration(0, 0, 3, 3, {alignment:8, skipRows:3}, usePixelPackBuffer, true);
    322    runTestIteration(0, 0, 2, 3, {alignment:8, skipPixels:2}, usePixelPackBuffer, false);
    323    runTestIteration(0, 0, 2, 3, {alignment:8, skipPixels:1, skipRows:3}, usePixelPackBuffer, false);
    324    runTestIteration(0, 0, 2, 3, {alignment:8, skipRows:3}, usePixelPackBuffer, true);
    325    runTestIteration(0, 0, 2, 3, {skipPixels:1, rowLength:4}, usePixelPackBuffer, true);
    326 }
    327 
    328 debug("");
    329 debug("Canvas.getContext");
    330 
    331 var canvas = document.getElementById("example");
    332 var gl = wtu.create3DContext(canvas, undefined, 2);
    333 
    334 if (!gl) {
    335  testFailed("context does not exist");
    336 } else {
    337  testPassed("context exists");
    338 
    339  debug("");
    340  description('ReadPixels into array buffer');
    341  paintWebGLCanvas(gl);
    342  var usePixelPackBuffer = false;
    343  testPackParameters(usePixelPackBuffer);
    344  usePixelPackBuffer = true;
    345  testPackParameters(usePixelPackBuffer);
    346 }
    347 
    348 debug("");
    349 var successfullyParsed = true;
    350 </script>
    351 <script src="../../js/js-test-post.js"></script>
    352 </body>
    353 </html>