tor-browser

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

gl-teximage.html (16639B)


      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 texImage2D conformance test.</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 <canvas id="example" width="256" height="16" style="width: 256px; height: 48px;"></canvas>
     18 <div id="description"></div>
     19 <div id="console"></div>
     20 <script>
     21 "use strict";
     22 enableJSTestPreVerboseLogging();
     23 description("Test texImage2D conversions.");
     24 var wtu = WebGLTestUtils;
     25 var gl = wtu.create3DContext("example");
     26 gl.disable(gl.DITHER);
     27 var program = wtu.setupTexturedQuad(gl);
     28 var successfullyParsed;
     29 
     30 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
     31 
     32 var imgURLs = [
     33  '../../../resources/1-channel.jpg',
     34  '../../../resources/gray-ramp-256-with-128-alpha.png',
     35  '../../../resources/gray-ramp-256.png',
     36  '../../../resources/gray-ramp-default-gamma.png',
     37  '../../../resources/gray-ramp-gamma0.1.png',
     38  '../../../resources/gray-ramp-gamma1.0.png',
     39  '../../../resources/gray-ramp-gamma2.0.png',
     40  '../../../resources/gray-ramp-gamma4.0.png',
     41  '../../../resources/gray-ramp-gamma9.0.png',
     42  '../../../resources/gray-ramp.png',
     43  '../../../resources/zero-alpha.png',
     44  '../../../resources/3x3.png',
     45  '../../../resources/blue-1x1.jpg',
     46  '../../../resources/red-indexed.png',
     47  '../../../resources/transparent-on-left-indexed.png',
     48  '../../../resources/green-2x2-16bit.png',
     49  '../../../resources/small-square-with-colorspin-profile.jpg',
     50  '../../../resources/small-square-with-colorspin-profile.png',
     51  '../../../resources/small-square-with-cie-rgb-profile.png',
     52  '../../../resources/small-square-with-colormatch-profile.png',
     53  '../../../resources/small-square-with-e-srgb-profile.png',
     54  '../../../resources/small-square-with-smpte-c-profile.png',
     55  '../../../resources/small-square-with-srgb-iec61966-2.1-profile.png'];
     56 
     57 
     58 wtu.loadImagesAsync(imgURLs, runTests);
     59 
     60 function runTests(imgs) {
     61  var loc = gl.getUniformLocation(program, "tex");
     62  gl.uniform1i(loc, 0);
     63 
     64  gl.disable(gl.BLEND);
     65  gl.disable(gl.DEPTH_TEST);
     66 
     67  var width = gl.canvas.width;
     68  var height = gl.canvas.height;
     69 
     70  function checkPixel(x, y, color) {
     71    wtu.checkCanvasRect(gl, x, y, 1, 1, color);
     72  }
     73 
     74  function checkPixelRange(x, y, color, allowedRange) {
     75    var msg = "pixel " + x + ", " + y + " should be within " +
     76              allowedRange + " units of " +
     77              color[0] + ", " +
     78              color[1] + ", " +
     79              color[2] + ", " +
     80              color[3];
     81    wtu.checkCanvasRect(gl, x, y, 1, 1, color, msg, allowedRange);
     82  }
     83 
     84  var tex = gl.createTexture();
     85  gl.bindTexture(gl.TEXTURE_2D, tex);
     86  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
     87  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
     88  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
     89  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
     90 
     91  var buf = new Uint8Array(width * height * 4);
     92 
     93  debug("");
     94  debug("check pixels are NOT pre-multiplied");
     95  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
     96                imgs['../../../resources/zero-alpha.png']);
     97  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
     98  wtu.clearAndDrawUnitQuad(gl);
     99 
    100  var left = 0;
    101  var middle = Math.floor(width / 2);
    102  var right = width - 1;
    103  var bottom = 0;
    104  var center = Math.floor(height / 2);
    105  var top = height - 1;
    106  checkPixel(left,   top,    [  0,   0,   0, 255]);
    107  checkPixel(middle, top,    [255,   0, 255, 255]);
    108  checkPixel(right,  top,    [  0,   0, 255, 255]);
    109  checkPixel(left,   center, [128, 128, 128, 255]);
    110  checkPixel(middle, center, [255, 255, 255, 255]);
    111  checkPixel(right,  center, [  0, 255, 255, 255]);
    112  checkPixel(left,   bottom, [255,   0,   0, 255]);
    113  checkPixel(middle, bottom, [255, 255,   0, 255]);
    114  checkPixel(right,  bottom, [  0, 255,   0, 255]);
    115 
    116  debug("");
    117  debug("check quantization");
    118  var quantInfo = [
    119    {format: gl.RGBA, type: gl.UNSIGNED_BYTE,          counts: [256, 256, 256, 256]},
    120    {format: gl.RGBA, type: gl.UNSIGNED_SHORT_4_4_4_4, counts: [ 16,  16,  16,  16]},
    121    {format: gl.RGB,  type: gl.UNSIGNED_SHORT_5_6_5,   counts: [ 32,  64,  32,   1]},
    122    {format: gl.RGBA, type: gl.UNSIGNED_SHORT_5_5_5_1, counts: [ 32,  32,  32,   2]}];
    123  for (var qq = 0; qq < quantInfo.length; ++qq) {
    124    var info = quantInfo[qq];
    125    gl.texImage2D(
    126        gl.TEXTURE_2D, 0, info.format, info.format, info.type,
    127        imgs['../../../resources/gray-ramp-256.png']);
    128    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
    129    wtu.clearAndDrawUnitQuad(gl);
    130    gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
    131    var counts = [{ }, { }, { }, { }];
    132    var numUniqueValues = [0, 0, 0, 0];
    133    // Count the number of unique values in each channel.
    134    for (var ii = 0; ii < width * height * 4; ii += 4) {
    135      for (var jj = 0; jj < 4; ++jj) {
    136        var v = buf[ii + jj];
    137        if (!counts[jj][v]) {
    138          counts[jj][v] = 1;
    139          ++numUniqueValues[jj];
    140        } else {
    141          ++counts[jj][v];
    142        }
    143      }
    144    }
    145    for (var ii = 0; ii < 4; ++ii) {
    146      assertMsg(numUniqueValues[ii] == info.counts[ii],
    147                "There should be " + info.counts[ii] +
    148                " unique values in channel " + ii + ". Found " +
    149                numUniqueValues[ii]);
    150    }
    151  }
    152 
    153  debug("");
    154  debug("Check that gamma settings don't effect 8bit pngs");
    155  wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);');
    156  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
    157                imgs['../../../resources/gray-ramp-default-gamma.png']);
    158  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
    159  wtu.clearAndDrawUnitQuad(gl);
    160  var ref = new Uint8Array(width * height * 4);
    161  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, ref);
    162 
    163  var gammaImages = [
    164    '../../../resources/gray-ramp-gamma0.1.png',
    165    '../../../resources/gray-ramp-gamma1.0.png',
    166    '../../../resources/gray-ramp-gamma2.0.png',
    167    '../../../resources/gray-ramp-gamma4.0.png',
    168    '../../../resources/gray-ramp-gamma9.0.png'];
    169  for (var ii = 0; ii < gammaImages.length; ++ii) {
    170    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
    171                  imgs[gammaImages[ii]]);
    172    wtu.clearAndDrawUnitQuad(gl);
    173    gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
    174    var same = true;
    175    for (var jj = 0; jj < width * height * 4; ++jj) {
    176      if (buf[jj] != ref[jj]) {
    177        same = false;
    178        break;
    179      }
    180    }
    181    assertMsg(same, "pixels should be same regardless of gamma settings.");
    182  }
    183 
    184  debug("");
    185  debug("check pixels are UN pre-multiplied");
    186  for (var ii = 0; ii < 2; ++ii) {
    187    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
    188    if (ii == 0) {
    189      var canvas2d = document.createElement("canvas");
    190      canvas2d.width = 256;
    191      canvas2d.height = 1;
    192      var ctx = canvas2d.getContext("2d");
    193      ctx.drawImage(imgs['../../../resources/gray-ramp-256-with-128-alpha.png'], 0, 0);
    194      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, canvas2d);
    195    } else {
    196      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
    197                    imgs['../../../resources/gray-ramp-256-with-128-alpha.png']);
    198    }
    199    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
    200    wtu.clearAndDrawUnitQuad(gl);
    201    var buf = new Uint8Array(width * height * 4);
    202    gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
    203    var lt128Count = [0, 0, 0];
    204    var ge128Count = [0, 0, 0];
    205    for (var jj = 0; jj < width; ++jj) {
    206      var off = jj * 4;
    207      for (var cc = 0; cc < 3; ++cc) {
    208        if (buf[off + cc] < 128) {
    209          ++lt128Count[cc];
    210        } else {
    211          ++ge128Count[cc];
    212        }
    213      }
    214    }
    215    // Not sure the exact count here because gamma does effect drawing into the
    216    // canvas but it should be close to 50% so I'll pass 45%
    217    for (var jj = 0; jj < 3; ++jj) {
    218      assertMsg(ge128Count[jj] > 256 * 0.45,
    219                "Half the pixels in channel " + jj +
    220                " should be >= 128,128,128. found " +
    221                ((ge128Count[jj] / 256) * 100).toFixed() + "%");
    222      assertMsg(lt128Count[jj] > 256 * 0.45,
    223                "Half the pixels in channel " + jj +
    224                " should be < 128,128,128. found " +
    225                ((lt128Count[jj] / 256) * 100).toFixed() + "%");
    226    }
    227  }
    228 
    229  debug("");
    230  debug("check canvas pixels are UN pre-multiplied");
    231  var canvas2d = document.createElement("canvas");
    232  canvas2d.width = 1;
    233  canvas2d.height = 1;
    234  var ctx = canvas2d.getContext("2d");
    235  ctx.fillStyle ="rgba(255,255,255,0.5)";
    236  ctx.fillRect(0, 0, 256, 1);
    237  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
    238  wtu.clearAndDrawUnitQuad(gl);
    239  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
    240  checkPixelRange(0, 0, [255, 255, 255, 127], 4);
    241 
    242  debug("");
    243  debug("check canvas pixels are pre-multiplied");
    244  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
    245  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
    246  wtu.clearAndDrawUnitQuad(gl);
    247  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
    248  checkPixelRange(0, 0, [127, 127, 127, 127], 4);
    249 
    250 
    251  debug("");
    252  debug("check pixels are pre-multiplied");
    253  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
    254  // TODO(gman): use different texture that won't pass on failure
    255  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
    256                imgs['../../../resources/zero-alpha.png']);
    257  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
    258  wtu.clearAndDrawUnitQuad(gl);
    259  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
    260 
    261  var same = true;
    262  for (var jj = 0; jj < width * height * 4; ++jj) {
    263    if (buf[jj] != 0) {
    264      same = false;
    265      break;
    266    }
    267  }
    268  assertMsg(same, "pixels should all be 0.");
    269 
    270  debug("");
    271  debug("check pixels are flipped");
    272  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
    273  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    274  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
    275                imgs['../../../resources/3x3.png']);
    276  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
    277  wtu.clearAndDrawUnitQuad(gl);
    278 
    279  checkPixel(left,   top,    [255,   0,   0, 255]);
    280  checkPixel(middle, top,    [255, 255,   0, 255]);
    281  checkPixel(right,  top,    [255,   0,   0, 255]);
    282  checkPixel(left,   center, [255,   0, 255, 255]);
    283  checkPixel(middle, center, [255,   0,   0, 255]);
    284  checkPixel(right,  center, [  0, 255,   0, 255]);
    285  checkPixel(left,   bottom, [  0,   0,   0, 255]);
    286  checkPixel(middle, bottom, [  0,   0, 255, 255]);
    287  checkPixel(right,  bottom, [255,   0,   0, 255]);
    288 
    289  debug("");
    290  debug("check uploading of images with no alpha channel works");
    291  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
    292  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
    293  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
    294                imgs['../../../resources/blue-1x1.jpg']);
    295  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
    296  wtu.clearAndDrawUnitQuad(gl);
    297  checkPixelRange(middle, center, [   0,   0, 255, 255], 10);
    298  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
    299 
    300  debug("");
    301  debug("check uploading of 16-bit images");
    302  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
    303  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
    304  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
    305                imgs['../../../resources/green-2x2-16bit.png']);
    306  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
    307  wtu.clearAndDrawUnitQuad(gl);
    308  checkPixelRange(middle, center, [   15, 121,   0, 255], 10);
    309  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
    310 
    311  debug("");
    312  debug("check uploading of images with ICC profiles");
    313  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
    314  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
    315  wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);');
    316 
    317  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
    318                imgs['../../../resources/small-square-with-colorspin-profile.jpg']);
    319  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
    320  wtu.clearAndDrawUnitQuad(gl);
    321  // The image is red.  However, if we ignore the color profile, it is blue.
    322  checkPixelRange(middle, center, [ 0, 0, 255, 255], 10);
    323 
    324  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
    325                imgs['../../../resources/small-square-with-colorspin-profile.png']);
    326  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
    327  wtu.clearAndDrawUnitQuad(gl);
    328  // The image is red.  However, if we ignore the color profile, it is blue.
    329  checkPixelRange(middle, center, [ 0, 0, 255, 255], 10);
    330 
    331  var iccPNGs = [
    332    '../../../resources/small-square-with-cie-rgb-profile.png',
    333    '../../../resources/small-square-with-colormatch-profile.png',
    334    '../../../resources/small-square-with-e-srgb-profile.png',
    335    '../../../resources/small-square-with-smpte-c-profile.png',
    336    '../../../resources/small-square-with-srgb-iec61966-2.1-profile.png'];
    337  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
    338  for (var ii = 0; ii < iccPNGs.length; ++ii) {
    339    var buf2 = new Uint8Array(width * height * 4);
    340    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
    341                  imgs[iccPNGs[ii]]);
    342    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
    343    wtu.clearAndDrawUnitQuad(gl);
    344    gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf2);
    345    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");
    346    var same = true;
    347    for (var jj = 0; jj < buf.length; ++jj) {
    348      if (buf[jj] != buf2[jj]) {
    349        same = false;
    350        break;
    351      }
    352    }
    353    assertMsg(same, "uploading PNGs with same data but various ICC profiles should generate the same results");
    354  }
    355 
    356  debug("");
    357  debug("check uploading of indexed PNG images");
    358  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
    359                imgs['../../../resources/red-indexed.png']);
    360  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
    361  wtu.clearAndDrawUnitQuad(gl);
    362  // The image should be red.
    363  checkPixelRange(middle, center, [ 255, 0, 0, 255 ], 10);
    364 
    365  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
    366  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
    367                imgs['../../../resources/transparent-on-left-indexed.png']);
    368  wtu.clearAndDrawUnitQuad(gl);
    369  wtu.checkCanvasRect(gl, 0, 0, 128, 16, [255, 0, 255, 0], "should be transparent purple");
    370  wtu.checkCanvasRect(gl, 128, 0,128, 16, [255, 255, 0, 255], "should be yellow");
    371 
    372  debug("");
    373  debug("check uploading of 1-channel JPG images");
    374  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
    375                imgs['../../../resources/1-channel.jpg']);
    376  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
    377  wtu.clearAndDrawUnitQuad(gl);
    378  // The image should be gray.
    379  checkPixelRange(middle, center, [ 128, 128, 128, 255 ], 28);
    380 
    381  debug("")
    382  debug("check calling texImage2D with NULL clears the texture");
    383  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB,
    384                imgs['../../../resources/red-indexed.png'].width,
    385                imgs['../../../resources/red-indexed.png'].height,
    386                0, gl.RGB, gl.UNSIGNED_BYTE, null);
    387  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
    388  wtu.clearAndDrawUnitQuad(gl);
    389  // The image should be white.
    390  checkPixelRange(middle, center, [ 0, 0, 0, 255 ], 10);
    391 
    392  debug("");
    393  debug("check zero size cases");
    394  gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, 2, 0, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, new Uint8Array());
    395  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from zero sized textures");
    396 
    397  debug("");
    398  successfullyParsed = true;
    399  shouldBeTrue("successfullyParsed");
    400  debug('<br /><span class="pass">TEST COMPLETE</span>');
    401  notifyFinishedToHarness();
    402 }
    403 </script>
    404 </body>
    405 </html>