tor-browser

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

webgl-compressed-texture-pvrtc.html (13603B)


      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 <title>WebGL WEBGL_compressed_texture_pvrtc Conformance Tests</title>
     15 <style>
     16 img {
     17 border: 1px solid black;
     18 margin-right: 1em;
     19 }
     20 .testimages {
     21 }
     22 
     23 .testimages br {
     24  clear: both;
     25 }
     26 
     27 .testimages > div {
     28  float: left;
     29  margin: 1em;
     30 }
     31 </style>
     32 </head>
     33 <body>
     34 <div id="description"></div>
     35 <canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
     36 <div id="console"></div>
     37 <script>
     38 "use strict";
     39 description("This test verifies the functionality of the WEBGL_compressed_texture_pvrtc extension, if it is available.");
     40 
     41 debug("");
     42 
     43 var pvrtc_4x4_2bpp = new Uint8Array([
     44  0x77, 0x22, 0x77, 0x22, 0xbb, 0x2b, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     45  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     46 ]);
     47 
     48 var pvrtc_4x4_4bpp = new Uint8Array([
     49  0x1b, 0x1b, 0x1b, 0x1b, 0xba, 0x2b, 0x00, 0x80, 0x1b, 0x1b, 0x1b, 0x1b, 0xba, 0x2b, 0x00, 0x80,
     50  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     51 ]);
     52 
     53 var pvrtc_4x4_rgba_decoded = new Uint8Array([
     54  0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xba, 0x44,
     55  0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xb5, 0x44,
     56  0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xb5, 0x44,
     57  0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xb7, 0x44,
     58 ]);
     59 
     60 var pvrtc_4x4_rgb_decoded = new Uint8Array([
     61  0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xba, 0xff,
     62  0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xb5, 0xff,
     63  0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xb5, 0xff,
     64  0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xb7, 0xff,
     65 ]);
     66 
     67 var wtu = WebGLTestUtils;
     68 var contextVersion = wtu.getDefault3DContextVersion();
     69 var canvas = document.getElementById("canvas");
     70 var gl = wtu.create3DContext(canvas, {antialias: false});
     71 var program = wtu.setupTexturedQuad(gl);
     72 var ext = null;
     73 var vao = null;
     74 var validFormats = {
     75    COMPRESSED_RGB_PVRTC_4BPPV1_IMG      : 0x8C00,
     76    COMPRESSED_RGB_PVRTC_2BPPV1_IMG      : 0x8C01,
     77    COMPRESSED_RGBA_PVRTC_4BPPV1_IMG     : 0x8C02,
     78    COMPRESSED_RGBA_PVRTC_2BPPV1_IMG     : 0x8C03,
     79 };
     80 var name;
     81 var supportedFormats;
     82 
     83 if (!gl) {
     84    testFailed("WebGL context does not exist");
     85 } else {
     86    testPassed("WebGL context exists");
     87 
     88    // Run tests with extension disabled
     89    runTestDisabled();
     90 
     91    // Query the extension and store globally so shouldBe can access it
     92    ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_pvrtc");
     93    if (!ext) {
     94        testPassed("No WEBGL_compressed_texture_pvrtc support -- this is legal");
     95        runSupportedTest(false);
     96    } else {
     97        testPassed("Successfully enabled WEBGL_compressed_texture_pvrtc extension");
     98 
     99        runSupportedTest(true);
    100        runTestExtension();
    101    }
    102 }
    103 
    104 function runSupportedTest(extensionEnabled) {
    105    var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_pvrtc");
    106    if (name !== undefined) {
    107        if (extensionEnabled) {
    108            testPassed("WEBGL_compressed_texture_pvrtc listed as supported and getExtension succeeded");
    109        } else {
    110            testFailed("WEBGL_compressed_texture_pvrtc listed as supported but getExtension failed");
    111        }
    112    } else {
    113        if (extensionEnabled) {
    114            testFailed("WEBGL_compressed_texture_pvrtc not listed as supported but getExtension succeeded");
    115        } else {
    116            testPassed("WEBGL_compressed_texture_pvrtc not listed as supported and getExtension failed -- this is legal");
    117        }
    118    }
    119 }
    120 
    121 
    122 function runTestDisabled() {
    123    debug("Testing binding enum with extension disabled");
    124 
    125    supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
    126    shouldBe("supportedFormats", "[]");
    127 }
    128 
    129 function formatExists(format, supportedFormats) {
    130    for (var ii = 0; ii < supportedFormats.length; ++ii) {
    131        if (format == supportedFormats[ii]) {
    132            testPassed("supported format " + formatToString(format) + " is exists");
    133            return;
    134        }
    135    }
    136    testFailed("supported format " + formatToString(format) + " does not exist");
    137 }
    138 
    139 function formatToString(format) {
    140    for (var p in ext) {
    141        if (ext[p] == format) {
    142            return p;
    143        }
    144    }
    145    return "0x" + format.toString(16);
    146 }
    147 
    148 function runTestExtension() {
    149    debug("Testing WEBGL_compressed_texture_pvrtc");
    150 
    151    // check that all format enums exist.
    152    for (name in validFormats) {
    153        var expected = "0x" + validFormats[name].toString(16);
    154        var actual = "ext['" + name + "']";
    155        shouldBe(actual, expected);
    156    }
    157 
    158    supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
    159    // There should be exactly 4 formats for both WebGL 1.0 and WebGL 2.0.
    160    shouldBe("supportedFormats.length", "4");
    161 
    162    // check that all 4 formats exist
    163    for (var name in validFormats.length) {
    164        formatExists(validFormats[name], supportedFormats);
    165    }
    166 
    167    // Test each format
    168    testPVRTC_RGBA_2BPP();
    169    testPVRTC_RGB_2BPP();
    170    testPVRTC_RGBA_4BPP();
    171    testPVRTC_RGB_4BPP();
    172 }
    173 
    174 function testPVRTC_RGBA_2BPP() {
    175    var tests = [
    176        {   width: 4,
    177            height: 4,
    178            channels: 4,
    179            data: pvrtc_4x4_2bpp,
    180            raw: pvrtc_4x4_rgba_decoded,
    181            format: ext.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
    182        }
    183    ];
    184    testPVRTCTextures(tests);
    185 }
    186 
    187 function testPVRTC_RGB_2BPP() {
    188    var tests = [
    189        {   width: 4,
    190            height: 4,
    191            channels: 4,
    192            data: pvrtc_4x4_2bpp,
    193            raw: pvrtc_4x4_rgb_decoded,
    194            format: ext.COMPRESSED_RGB_PVRTC_2BPPV1_IMG
    195        }
    196    ];
    197    testPVRTCTextures(tests);
    198 }
    199 
    200 function testPVRTC_RGBA_4BPP() {
    201    var tests = [
    202        {   width: 4,
    203            height: 4,
    204            channels: 4,
    205            data: pvrtc_4x4_4bpp,
    206            raw: pvrtc_4x4_rgba_decoded,
    207            format: ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
    208        }
    209    ];
    210    testPVRTCTextures(tests);
    211 }
    212 
    213 function testPVRTC_RGB_4BPP() {
    214    var tests = [
    215        {   width: 4,
    216            height: 4,
    217            channels: 4,
    218            data: pvrtc_4x4_4bpp,
    219            raw: pvrtc_4x4_rgb_decoded,
    220            format: ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG
    221        }
    222    ];
    223    testPVRTCTextures(tests);
    224 }
    225 
    226 function testPVRTCTextures(tests) {
    227    debug("<hr/>");
    228    for (var ii = 0; ii < tests.length; ++ii) {
    229        testPVRTCTexture(tests[ii]);
    230    }
    231 }
    232 
    233 function testPVRTCTexture(test) {
    234    var data = new Uint8Array(test.data);
    235    var width = test.width;
    236    var height = test.height;
    237    var format = test.format;
    238    var uncompressedData = test.raw;
    239 
    240    canvas.width = width;
    241    canvas.height = height;
    242    gl.viewport(0, 0, width, height);
    243    debug("testing " + formatToString(format) + " " + width + "x" + height);
    244 
    245    var tex = gl.createTexture();
    246    gl.bindTexture(gl.TEXTURE_2D, tex);
    247    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    248    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    249    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    250    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    251    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
    252    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
    253    gl.generateMipmap(gl.TEXTURE_2D);
    254    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture");
    255    wtu.clearAndDrawUnitQuad(gl);
    256    compareRect(width, height, test.channels, width, height, uncompressedData, data, format, undefined, "NEAREST");
    257    // Test again with linear filtering.
    258    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    259    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    260    wtu.clearAndDrawUnitQuad(gl);
    261    compareRect(width, height, test.channels, width, height, uncompressedData, data, format, undefined, "LINEAR");
    262 
    263    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data);
    264    wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border");
    265 
    266    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data);
    267    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
    268    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data);
    269    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
    270    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data);
    271    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
    272    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data);
    273    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
    274 
    275    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data);
    276    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "compressedTexSubImage2D allowed for reloading of complete textures");
    277 
    278    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 2, height, format, data);
    279    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
    280    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 2, format, data);
    281    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
    282    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 2, 0, width - 2, height, format, data);
    283    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
    284    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 2, width, height - 2, format, data);
    285    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
    286 }
    287 
    288 function insertImg(element, caption, img) {
    289    var div = document.createElement("div");
    290    div.appendChild(img);
    291    var label = document.createElement("div");
    292    label.appendChild(document.createTextNode(caption));
    293    div.appendChild(label);
    294    element.appendChild(div);
    295 }
    296 
    297 function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) {
    298    var scale = 8;
    299    var c = document.createElement("canvas");
    300    c.width = imageWidth * scale;
    301    c.height = imageHeight * scale;
    302    var ctx = c.getContext("2d");
    303    for (var yy = 0; yy < imageHeight; ++yy) {
    304        for (var xx = 0; xx < imageWidth; ++xx) {
    305            var offset = (yy * dataWidth + xx) * 4;
    306            ctx.fillStyle = "rgba(" +
    307                    data[offset + 0] + "," +
    308                    data[offset + 1] + "," +
    309                    data[offset + 2] + "," +
    310                    (alpha ? data[offset + 3] / 255 : 1) + ")";
    311            ctx.fillRect(xx * scale, yy * scale, scale, scale);
    312        }
    313    }
    314    return wtu.makeImageFromCanvas(c);
    315 }
    316 function compareRect(
    317        actualWidth, actualHeight, actualChannels,
    318        dataWidth, dataHeight, expectedData,
    319        testData, testFormat, tolerance, filteringMode) {
    320    if(typeof(tolerance) == 'undefined') { tolerance = 5; }
    321    var actual = new Uint8Array(actualWidth * actualHeight * 4);
    322    gl.readPixels(
    323            0, 0, actualWidth, actualHeight, gl.RGBA, gl.UNSIGNED_BYTE, actual);
    324 
    325    var div = document.createElement("div");
    326    div.className = "testimages";
    327    insertImg(div, "expected", makeImage(
    328            actualWidth, actualHeight, dataWidth, expectedData,
    329            actualChannels == 4));
    330    insertImg(div, "actual", makeImage(
    331            actualWidth, actualHeight, actualWidth, actual,
    332            actualChannels == 4));
    333    div.appendChild(document.createElement('br'));
    334    document.getElementById("console").appendChild(div);
    335 
    336    var failed = false;
    337    for (var yy = 0; yy < actualHeight; ++yy) {
    338        for (var xx = 0; xx < actualWidth; ++xx) {
    339            var actualOffset = (yy * actualWidth + xx) * 4;
    340            var expectedOffset = (yy * dataWidth + xx) * 4;
    341            var expected = [
    342                    expectedData[expectedOffset + 0],
    343                    expectedData[expectedOffset + 1],
    344                    expectedData[expectedOffset + 2],
    345                    (actualChannels == 3 ? 255 : expectedData[expectedOffset + 3])
    346            ];
    347            for (var jj = 0; jj < 4; ++jj) {
    348                if (Math.abs(actual[actualOffset + jj] - expected[jj]) > tolerance) {
    349                    failed = true;
    350                    var was = actual[actualOffset + 0].toString();
    351                    for (var j = 1; j < 4; ++j) {
    352                        was += "," + actual[actualOffset + j];
    353                    }
    354                    testFailed('at (' + xx + ', ' + yy +
    355                                         ') expected: ' + expected + ' was ' + was);
    356                }
    357            }
    358        }
    359    }
    360    if (!failed) {
    361        testPassed("texture rendered correctly with " + filteringMode + " filtering");
    362    }
    363 }
    364 
    365 debug("");
    366 var successfullyParsed = true;
    367 </script>
    368 <script src="../../js/js-test-post.js"></script>
    369 
    370 </body>
    371 </html>