tor-browser

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

tex-image-and-sub-image-2d-with-array-buffer-view.html (13368B)


      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="16" height="16"></canvas>
     17 <div id="description"></div>
     18 <div id="console"></div>
     19 <script>
     20 "use strict";
     21 description('Verifies texImage2D and texSubImage2D code paths taking ArrayBufferView');
     22 
     23 var wtu = WebGLTestUtils;
     24 
     25 function roundUpToAlignment(value, alignment) {
     26  return Math.floor((value + alignment - 1) / alignment) * alignment;
     27 }
     28 
     29 function generateRGBAData(type, unpackAlignment, sourceData, width, height)
     30 {
     31    var numColors = sourceData.length / 4;
     32    var colorOffset = function(y) {
     33      return 4 * Math.floor(y * numColors / height);
     34    };
     35 
     36    switch (type) {
     37    case gl.UNSIGNED_BYTE: {
     38        var rowWidth = roundUpToAlignment(width * 4, unpackAlignment);
     39        var data = new Uint8Array(height * rowWidth);
     40        for (var y = 0; y < height; ++y) {
     41            var index = y * rowWidth;
     42            var offset = colorOffset(y);
     43            for (var element = 0; element < width * 4; ++element) {
     44                data[index + element] = sourceData[offset + element % 4];
     45            }
     46        }
     47        return data;
     48    }
     49    case gl.UNSIGNED_SHORT_4_4_4_4: {
     50        var rowWidth = roundUpToAlignment(width * 2, unpackAlignment) / 2;
     51        var data = new Uint16Array(height * rowWidth);
     52        for (var y = 0; y < height; ++y) {
     53            var offset = colorOffset(y);
     54            for (var x = 0; x < width; ++x) {
     55                var index = y * rowWidth + x;
     56                data[index] = (((sourceData[offset + 0] & 0xF0) << 8)
     57                             | ((sourceData[offset + 1] & 0xF0) << 4)
     58                             | ((sourceData[offset + 2] & 0xF0) >> 0)
     59                             | ((sourceData[offset + 3] & 0xF0) >> 4));
     60            }
     61        }
     62        return data;
     63    }
     64    case gl.UNSIGNED_SHORT_5_5_5_1: {
     65        var rowWidth = roundUpToAlignment(width * 2, unpackAlignment) / 2;
     66        var data = new Uint16Array(height * rowWidth);
     67        for (var y = 0; y < height; ++y) {
     68            var offset = colorOffset(y);
     69            for (var x = 0; x < width; ++x) {
     70                var index = y * rowWidth + x;
     71                data[index] = (((sourceData[offset + 0] & 0xF8) << 8)
     72                             | ((sourceData[offset + 1] & 0xF8) << 3)
     73                             | ((sourceData[offset + 2] & 0xF8) >> 2)
     74                             | ((sourceData[offset + 3] & 0x80) >> 7));
     75            }
     76        }
     77        return data;
     78    }
     79    }
     80 }
     81 
     82 function typeToString(type)
     83 {
     84    switch (type) {
     85    case gl.UNSIGNED_BYTE:           return 'UNSIGNED_BYTE';
     86    case gl.UNSIGNED_SHORT_5_5_5_1:  return 'UNSIGNED_SHORT_5_5_5_1';
     87    case gl.UNSIGNED_SHORT_4_4_4_4:  return 'UNSIGNED_SHORT_4_4_4_4';
     88    }
     89    return 'Unknown type ' + type;
     90 }
     91 
     92 function runOneIteration(useTexSubImage2D, type, unpackAlignment, flipY, premultiplyAlpha,
     93                         topColor, bottomColor, extraColor, bindingTarget, program)
     94 {
     95    debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') +
     96          ' with type=' + typeToString(type) +
     97          ', unpackAlignment=' + unpackAlignment +
     98          ', flipY=' + flipY + ', premultiplyAlpha=' + premultiplyAlpha +
     99          ', bindingTarget=' + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP'));
    100    gl.colorMask(true, true, true, true);
    101    gl.clearColor(0, 0, 0, 1.0);
    102    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    103    // Enable writes to the RGB channels
    104    gl.colorMask(true, true, true, false);
    105    var texture = gl.createTexture();
    106    // Bind the texture to texture unit 0
    107    gl.bindTexture(bindingTarget, texture);
    108    // Set up texture parameters
    109    gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    110    gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    111    gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    112    gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    113    // Set up pixel store parameters
    114    gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment);
    115    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
    116    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
    117    // Generate the data
    118    var sourceData = [ 255,   0,   0, 255,
    119                       0,   255,   0,   0 ];
    120    var texWidth = 5;   // this must be mod 4 + 1 to test unpackAlignment
    121    // cube map texture must be square.
    122    if (bindingTarget == gl.TEXTURE_CUBE_MAP)
    123        texWidth = 16;
    124    var texHeight = 16;
    125    var data = generateRGBAData(type, unpackAlignment, sourceData, texWidth, texHeight);
    126    if (gl.getError() != gl.NO_ERROR)
    127        testFailed("GL error before texture upload");
    128    var targets = [gl.TEXTURE_2D];
    129    if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
    130        targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X,
    131                   gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
    132                   gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
    133                   gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
    134                   gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
    135                   gl.TEXTURE_CUBE_MAP_NEGATIVE_Z];
    136    }
    137    // Upload the image into the texture
    138    for (var tt = 0; tt < targets.length; ++tt) {
    139        if (useTexSubImage2D) {
    140            // Initialize the texture to black first
    141            gl.texImage2D(targets[tt], 0, gl.RGBA, texWidth, texHeight, 0,
    142                          gl.RGBA, type, null);
    143            if (gl.getError() != gl.NO_ERROR)
    144                testFailed("GL error after texImage2D(null)");
    145            gl.texSubImage2D(targets[tt], 0, 0, 0, texWidth, texHeight, gl.RGBA, type, data);
    146            if (gl.getError() != gl.NO_ERROR)
    147                testFailed("GL error after texSubImage2D");
    148        } else {
    149            gl.texImage2D(targets[tt], 0, gl.RGBA, texWidth, texHeight, 0, gl.RGBA, type, data);
    150            if (gl.getError() != gl.NO_ERROR)
    151                testFailed("GL error after texImage2D");
    152        }
    153    }
    154 
    155    var testWidth  = gl.drawingBufferWidth;
    156    var testHeight = gl.drawingBufferHeight / 2;
    157 
    158    var loc;
    159    if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
    160        loc = gl.getUniformLocation(program, "face");
    161    }
    162 
    163    for (var tt = 0; tt < targets.length; ++tt) {
    164        if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
    165            gl.uniform1i(loc, targets[tt]);
    166        }
    167 
    168        // Draw the triangles
    169        wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
    170 
    171        // Check the top pixel and bottom pixel and make sure they have
    172        // the right color.
    173        var rects = [wtu.makeCheckRect(0, 0, testWidth, testHeight, bottomColor, "bottom pixel should be " + bottomColor, 0),
    174                     wtu.makeCheckRect(0, testHeight, testWidth, testHeight, topColor, "top pixel should be " + topColor, 0)];
    175        wtu.checkCanvasRects(gl, rects);
    176      }
    177 
    178    // Change part of the texture.
    179    var partWidth = 16;
    180    var partHeight = 16;
    181    // make texture double res of part.
    182    var data = generateRGBAData(type, unpackAlignment, sourceData, partWidth * 2, partHeight * 2);
    183    for (var tt = 0; tt < targets.length; ++tt) {
    184        gl.texImage2D(targets[tt], 0, gl.RGBA, partWidth * 2, partHeight * 2, 0, gl.RGBA, type, data);
    185    }
    186    // set part.
    187    var extraData = [
    188      255,   0,   0, 255,
    189        0,   0, 255,   0
    190    ];
    191    var data = generateRGBAData(type, unpackAlignment, extraData, partWidth, partHeight);
    192    for (var tt = 0; tt < targets.length; ++tt) {
    193        gl.texSubImage2D(targets[tt], 0, 0, 0, partWidth, partHeight, gl.RGBA, type, data);
    194    }
    195    var halfWidth  = gl.drawingBufferWidth / 2;
    196    var halfHeight = gl.drawingBufferHeight / 2;
    197    var quarterHeight = gl.drawingBufferHeight / 4;
    198    var red = [255, 0, 0, 255];
    199    var tcolor0 = flipY ? extraColor : red;
    200    var tcolor1 = flipY ? red : extraColor;
    201 
    202    for (var tt = 0; tt < targets.length; ++tt) {
    203        if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
    204            gl.uniform1i(loc, targets[tt]);
    205        }
    206 
    207        wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
    208        wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
    209        var rects = [wtu.makeCheckRect(0, 0, halfWidth, quarterHeight, tcolor0, "bottom left bottom pixels should be " + tcolor0, 0),
    210                     wtu.makeCheckRect(0, quarterHeight, halfWidth, quarterHeight, tcolor1, "bottom left top pixels should be " + tcolor1, 0),
    211                     wtu.makeCheckRect(halfWidth, 0, halfWidth, halfHeight, bottomColor, "bottom right pixels should be " + bottomColor, 0),
    212                     wtu.makeCheckRect(0, halfHeight, testWidth, halfHeight, topColor, "top pixels should be " + topColor, 0)];
    213        wtu.checkCanvasRects(gl, rects);
    214      }
    215 
    216    // set far corner.
    217    for (var tt = 0; tt < targets.length; ++tt) {
    218        gl.texSubImage2D(targets[tt], 0, partWidth, partHeight, partWidth, partHeight, gl.RGBA, type, data);
    219    }
    220    for (var tt = 0; tt < targets.length; ++tt) {
    221        if (bindingTarget == gl.TEXTURE_CUBE_MAP) {
    222            gl.uniform1i(loc, targets[tt]);
    223        }
    224 
    225        wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
    226        var rects = [wtu.makeCheckRect(0, 0, halfWidth, quarterHeight, tcolor0, "bottom left bottom pixels should be " + tcolor0, 0),
    227                     wtu.makeCheckRect(0, quarterHeight, halfWidth, quarterHeight, tcolor1, "bottom left top pixels should be " + tcolor1, 0),
    228                     wtu.makeCheckRect(halfWidth, 0, halfWidth, halfHeight, bottomColor, "bottom left pixels should be " + bottomColor, 0),
    229                     wtu.makeCheckRect(0, halfHeight, halfWidth, halfHeight, topColor, "top right pixels should be " + topColor, 0),
    230                     wtu.makeCheckRect(halfWidth, halfHeight, halfWidth, quarterHeight, tcolor0, "top right bottom pixels should be " + tcolor0, 0),
    231                     wtu.makeCheckRect(halfWidth, halfHeight + quarterHeight, halfWidth, quarterHeight, tcolor1, "top right top pixels should be " + tcolor1, 0)];
    232        wtu.checkCanvasRects(gl, rects);
    233      }
    234 }
    235 
    236 function runTest(bindingTarget, program)
    237 {
    238    var red = [255, 0, 0, 255];
    239    var green = [0, 255, 0, 255];
    240    var blue = [0, 0, 255, 255];
    241    var redPremultiplyAlpha = [255, 0, 0, 255];
    242    var greenPremultiplyAlpha = [0, 0, 0, 255];
    243    var bluePremultiplyAlpha = [0, 0, 0, 255];
    244 
    245    var types = [ gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_5_5_5_1, gl.UNSIGNED_SHORT_4_4_4_4 ];
    246    var unpackAlignments = [ 1, 2, 4, 8 ];
    247 
    248    var cases = [
    249        { sub: false, flipY: true, premultiplyAlpha: false, topColor: red, bottomColor: green, extraColor: blue },
    250        { sub: false, flipY: false, premultiplyAlpha: false, topColor: green, bottomColor: red, extraColor: blue },
    251        { sub: false, flipY: true, premultiplyAlpha: true, topColor: redPremultiplyAlpha, bottomColor: greenPremultiplyAlpha, extraColor: bluePremultiplyAlpha },
    252        { sub: false, flipY: false, premultiplyAlpha: true, topColor: greenPremultiplyAlpha, bottomColor: redPremultiplyAlpha, extraColor: bluePremultiplyAlpha },
    253        { sub: true, flipY: true, premultiplyAlpha: false, topColor: red, bottomColor: green, extraColor: blue },
    254        { sub: true, flipY: false, premultiplyAlpha: false, topColor: green, bottomColor: red, extraColor: blue },
    255        { sub: true, flipY: true, premultiplyAlpha: true, topColor: redPremultiplyAlpha, bottomColor: greenPremultiplyAlpha, extraColor: bluePremultiplyAlpha },
    256        { sub: true, flipY: false, premultiplyAlpha: true, topColor: greenPremultiplyAlpha, bottomColor: redPremultiplyAlpha, extraColor: bluePremultiplyAlpha },
    257    ];
    258 
    259    for (var i in types) {
    260        for (var j in unpackAlignments) {
    261            for (var k in cases) {
    262                runOneIteration(cases[k].sub, types[i], unpackAlignments[j], cases[k].flipY, cases[k].premultiplyAlpha,
    263                                cases[k].topColor, cases[k].bottomColor, cases[k].extraColor, bindingTarget, program);
    264            }
    265        }
    266    }
    267 }
    268 
    269 var gl = wtu.create3DContext("example");
    270 
    271 var program = wtu.setupTexturedQuad(gl);
    272 runTest(gl.TEXTURE_2D, program);
    273 program = wtu.setupTexturedQuadWithCubeMap(gl);
    274 runTest(gl.TEXTURE_CUBE_MAP, program);
    275 
    276 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
    277 
    278 const tex = gl.createTexture();
    279 gl.bindTexture(gl.TEXTURE_2D, tex);
    280 
    281 const validDatas = [
    282  `new Uint8Array(4)`,
    283  `new Uint8Array(new ArrayBuffer(4))`,
    284  `new Uint8ClampedArray(4)`,
    285  `new Uint8ClampedArray(new ArrayBuffer(4))`,
    286 ];
    287 if (window.SharedArrayBuffer) {
    288  validDatas.push(
    289    `new Uint8Array(new SharedArrayBuffer(4))`,
    290    `new Uint8ClampedArray(new SharedArrayBuffer(4))`
    291  );
    292 }
    293 for (const x of validDatas) {
    294  shouldNotThrow(`gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1, 0, gl.RGBA, gl.UNSIGNED_BYTE, ${x});`);
    295  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
    296  shouldNotThrow(`gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, 1,1, gl.RGBA, gl.UNSIGNED_BYTE, ${x});`);
    297  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
    298 }
    299 
    300 var successfullyParsed = true;
    301 </script>
    302 <script src="../../../js/js-test-post.js"></script>
    303 </body>
    304 </html>