tor-browser

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

drawingbuffer-storage-test.js (8105B)


      1 /*
      2 Copyright (c) 2023 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 "use strict";
      8 
      9 let gl;
     10 let oldViewport;
     11 let width;
     12 let height;
     13 let format;
     14 let hasDrawingBufferStorage;
     15 let maxRenderbufferSize;
     16 
     17 function runTest(contextVersion) {
     18  description();
     19  debug("");
     20 
     21  function initialize() {
     22    let canvas = document.createElement("canvas");
     23    gl = wtu.create3DContext(canvas, {antialias: false});
     24    if (!gl) {
     25      testFailed("context does not exist");
     26      return [0, 0];
     27    }
     28 
     29    hasDrawingBufferStorage = `drawingBufferStorage` in gl;
     30    if (!hasDrawingBufferStorage) {
     31      testPassed("drawingBufferStorage not present -- skipping test");
     32      return;
     33    }
     34 
     35    maxRenderbufferSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);
     36  }
     37 
     38  function testPixel(expected, actual, tol) {
     39    let str = 'approx equal: expected: ' + expected + ', actual: ' + actual + ', tolerance: ' + tol;
     40    for (let i = 0; i < 4; ++i) {
     41      if (Math.abs(expected[i] - actual[i]) > tol) {
     42        testFailed(str);
     43        return;
     44      }
     45    }
     46    testPassed(str);
     47  }
     48 
     49  function srgbToLinear(x) {
     50    if (x < 0.0)
     51      return 0.0;
     52    if (x < 0.04045)
     53      return x / 12.92;
     54    if (x < 1.0) {
     55      return Math.pow((x + 0.055)/1.044, 2.4);
     56    }
     57    return 1.0;
     58  }
     59 
     60  function testClearColor() {
     61    // Make a fresh canvas.
     62    let canvas = document.createElement("canvas");
     63    canvas.width = 16;
     64    canvas.height = 16;
     65 
     66    gl = wtu.create3DContext(canvas, {antialias: false});
     67    if (!gl) {
     68      testFailed("context does not exist");
     69      return;
     70    }
     71    testPassed("context exists");
     72    shouldBe('gl.drawingBufferFormat', 'gl.RGBA8');
     73 
     74    let testCase = function(f, size, clearColor, expectedPixel, tolerance) {
     75      format = f;
     76      width = size[0];
     77      height = size[1];
     78 
     79      gl.drawingBufferStorage(format, width, height);
     80      shouldBe('gl.getError()', 'gl.NO_ERROR');
     81 
     82      shouldBe('gl.drawingBufferFormat', 'format');
     83      shouldBe('gl.drawingBufferWidth', 'width');
     84      shouldBe('gl.drawingBufferHeight', 'height');
     85 
     86      gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
     87      gl.clear(gl.COLOR_BUFFER_BIT);
     88 
     89      let buf;
     90      if (format == 0x881A /*RGBA16F*/) {
     91        buf = new Float32Array(4);
     92        gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, buf);
     93      } else {
     94        buf = new Uint8Array(4);
     95        gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
     96      }
     97      testPixel(expectedPixel, buf, tolerance);
     98    }
     99 
    100    debug('Testing RGBA8');
    101    testCase(gl.RGBA8, [16, 32],
    102             [16 / 255, 32 / 255, 64 / 255, 128 / 255],
    103             [16, 32, 64, 128],
    104             0);
    105 
    106    // WebGL 1 must use EXT_sRGB for SRGB8_ALPHA8.
    107    let srgb8_alpha8 = gl.SRGB8_ALPHA8;
    108    if (!srgb8_alpha8) {
    109      let ext = gl.getExtension('EXT_sRGB');
    110      if (ext) {
    111        srgb8_alpha8 = ext.SRGB8_ALPHA8_EXT;
    112      }
    113    }
    114    if (srgb8_alpha8) {
    115      debug('Testing SRGB8_ALPHA8');
    116      testCase(srgb8_alpha8, [16, 32],
    117               [srgbToLinear(64/255), srgbToLinear(16/255), srgbToLinear(32/255), 128 / 255],
    118               [64, 16, 32, 128],
    119               1);
    120    }
    121 
    122    if (gl.getExtension('EXT_color_buffer_float')) {
    123      // WebGL 1 must use EXT_color_buffer_half_float for RGBA16F.
    124      let rgba16f = gl.RGBA16F;
    125      if (!rgba16f) {
    126        let ext = gl.getExtension('EXT_color_buffer_half_float');
    127        if (ext) {
    128          rgba16f = ext.RGBA16F_EXT;
    129        }
    130      }
    131 
    132      debug('Testing RGBA16F');
    133      testCase(rgba16f, [18, 28],
    134               [0.25, 0.5, 0.75, 0.125],
    135               [0.25, 0.5, 0.75, 0.125],
    136               0.00001);
    137    } else {
    138      debug('Skipping RGBA16F');
    139    }
    140 
    141    shouldBe('gl.getError()', 'gl.NO_ERROR');
    142  }
    143 
    144  function testNoAlpha() {
    145    let canvas = document.createElement("canvas");
    146    canvas.width = 16;
    147    canvas.height = 16;
    148    gl = wtu.create3DContext(canvas, {alpha:false});
    149    if (!gl) {
    150      testFailed("context does not exist");
    151      return;
    152    }
    153    debug('Testing alpha:false');
    154 
    155    // Report RGB8 for the format.
    156    shouldBe('gl.drawingBufferFormat', 'gl.RGB8');
    157 
    158    // If WebGLContextAttributes.alpha is false, generate INVALID_OPERATION.
    159    gl.drawingBufferStorage(gl.RGBA8, 16, 16);
    160    shouldBe('gl.getError()', 'gl.INVALID_OPERATION');
    161  }
    162 
    163  function testMissingExtension() {
    164    let canvas = document.createElement("canvas");
    165    canvas.width = 16;
    166    canvas.height = 16;
    167    gl = wtu.create3DContext(canvas);
    168    if (!gl) {
    169      testFailed("context does not exist");
    170      return;
    171    }
    172 
    173    debug('Testing use of RGBA16F without enabling EXT_color_buffer_float');
    174    gl.drawingBufferStorage(gl.RGBA16F, 16, 16);
    175    shouldBe('gl.getError()', 'gl.INVALID_ENUM');
    176  }
    177 
    178  function testMaxSize() {
    179    let canvas = document.createElement("canvas");
    180    canvas.width = 16;
    181    canvas.height = 16;
    182    gl = wtu.create3DContext(canvas);
    183    if (!gl) {
    184      testFailed("context does not exist");
    185      return;
    186    }
    187 
    188    debug('Testing maximum size');
    189    gl.drawingBufferStorage(gl.RGBA8, maxRenderbufferSize, maxRenderbufferSize);
    190    shouldBe('gl.getError()', 'gl.NONE');
    191    shouldBe('gl.drawingBufferWidth', 'maxRenderbufferSize');
    192    shouldBe('gl.drawingBufferHeight', 'maxRenderbufferSize');
    193 
    194    debug('Testing over-maximum width and ehgith');
    195    gl.drawingBufferStorage(gl.RGBA8, maxRenderbufferSize+1, 16);
    196    shouldBe('gl.getError()', 'gl.INVALID_VALUE');
    197    gl.drawingBufferStorage(gl.RGBA8, 16, maxRenderbufferSize+1);
    198    shouldBe('gl.getError()', 'gl.INVALID_VALUE');
    199    shouldBe('gl.drawingBufferWidth', 'maxRenderbufferSize');
    200    shouldBe('gl.drawingBufferHeight', 'maxRenderbufferSize');
    201  }
    202 
    203  function testDrawToCanvas() {
    204    let canvasGL = document.createElement("canvas");
    205    canvasGL.width = 16;
    206    canvasGL.height = 16;
    207    gl = wtu.create3DContext(canvasGL);
    208    if (!gl) {
    209      testFailed("context does not exist");
    210      return;
    211    }
    212 
    213    let canvas2D = document.createElement("canvas");
    214    canvas2D.width = 16;
    215    canvas2D.height = 16;
    216    let ctx = canvas2D.getContext('2d');
    217    let imageData = new ImageData(16, 16);
    218 
    219    let testCase = function(f, clearColor, canvasColor, tolerance) {
    220      gl.drawingBufferStorage(f, 16, 16);
    221      gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
    222      gl.clear(gl.COLOR_BUFFER_BIT);
    223 
    224      ctx.putImageData(imageData, 0, 0);
    225      ctx.drawImage(canvasGL, 0, 0);
    226      testPixel(canvasColor, ctx.getImageData(8, 8, 1, 1).data, tolerance);
    227    }
    228 
    229    debug('Drawing RGBA to canvas');
    230    testCase(gl.RGBA8, [16/255, 32/255, 64/255, 64/255], [64, 128, 255, 64], 0);
    231 
    232    // WebGL 1 must use EXT_sRGB for SRGB8_ALPHA8.
    233    let srgb8_alpha8 = gl.SRGB8_ALPHA8;
    234    if (!srgb8_alpha8) {
    235      let ext = gl.getExtension('EXT_sRGB');
    236      if (ext) {
    237        srgb8_alpha8 = ext.SRGB8_ALPHA8_EXT;
    238      }
    239    }
    240    if (srgb8_alpha8) {
    241      debug('Drawing opaque SRGB8_ALPHA8 to canvas');
    242      testCase(srgb8_alpha8,
    243               [srgbToLinear(64/255), srgbToLinear(32/255), srgbToLinear(16/255), 1.0],
    244               [64, 32, 16, 255],
    245               1);
    246 
    247      debug('Drawing transparent SRGB8_ALPHA8 to canvas');
    248      // We set the tolerance to 5 because of compounding error. The backbuffer
    249      // may be off by 1, and then un-premultiplying alpha of 64/55 will multiply
    250      // that error by 4. Then add one to be safe.
    251      testCase(srgb8_alpha8,
    252               [srgbToLinear(32/255), srgbToLinear(64/255), srgbToLinear(16/255), 64/255],
    253               [128, 255, 64, 64],
    254               5);
    255    }
    256 
    257    if (gl.getExtension('EXT_color_buffer_float')) {
    258      debug('Drawing transparent RGBA16F to canvas');
    259      testCase(gl.RGBA16F,
    260               [32/255, 64/255, 16/255, 64/255],
    261               [128, 255, 64, 64],
    262               1);
    263    }
    264  }
    265 
    266  let wtu = WebGLTestUtils;
    267  initialize();
    268  if (hasDrawingBufferStorage) {
    269    testClearColor();
    270    testNoAlpha();
    271    testMissingExtension();
    272    testMaxSize();
    273    testDrawToCanvas();
    274  }
    275 }