tor-browser

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

test_queue_copyExternalImageToTexture.html (7222B)


      1 <!doctype html>
      2 <html>
      3  <head>
      4    <meta charset="utf-8" />
      5    <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6    <link rel="stylesheet" href="/tests/SimpleTest/test.css" />
      7  </head>
      8 
      9  <body>
     10    <script type="text/javascript">
     11      "use strict";
     12 
     13      ok(
     14        SpecialPowers.getBoolPref("dom.webgpu.enabled"),
     15        "WebGPU pref should be enabled."
     16      );
     17 
     18      SimpleTest.waitForExplicitFinish();
     19 
     20      function requestAnimationFramePromise() {
     21        return new Promise(requestAnimationFrame);
     22      }
     23 
     24      function createSourceCanvasWebgl() {
     25        const offscreenCanvas = new OffscreenCanvas(200, 200);
     26        const gl = offscreenCanvas.getContext("webgl");
     27 
     28        const COLOR_VALUE = 127.0 / 255.0;
     29        const ALPHA_VALUE = 127.0 / 255.0;
     30 
     31        gl.enable(gl.SCISSOR_TEST);
     32 
     33        gl.scissor(0, 0, 100, 100);
     34        gl.clearColor(COLOR_VALUE, 0.0, 0.0, ALPHA_VALUE);
     35        gl.clear(gl.COLOR_BUFFER_BIT);
     36 
     37        gl.scissor(100, 0, 100, 100);
     38        gl.clearColor(0.0, COLOR_VALUE, 0.0, ALPHA_VALUE);
     39        gl.clear(gl.COLOR_BUFFER_BIT);
     40 
     41        gl.scissor(0, 100, 100, 100);
     42        gl.clearColor(0.0, 0.0, COLOR_VALUE, ALPHA_VALUE);
     43        gl.clear(gl.COLOR_BUFFER_BIT);
     44 
     45        gl.scissor(100, 100, 100, 100);
     46        gl.clearColor(0.0, 0.0, 0.0, ALPHA_VALUE);
     47        gl.clear(gl.COLOR_BUFFER_BIT);
     48 
     49        return {
     50          source: offscreenCanvas,
     51          origin: { x: 0, y: 0 },
     52          flipY: true,
     53        };
     54      }
     55 
     56      function createSourceCanvas2d() {
     57        const offscreenCanvas = new OffscreenCanvas(200, 200);
     58        const context = offscreenCanvas.getContext("2d");
     59 
     60        context.fillStyle = "rgba(255,0,0,0.498)";
     61        context.fillRect(0, 0, 100, 100);
     62 
     63        context.fillStyle = "rgba(0,255,0,0.498)";
     64        context.fillRect(100, 0, 100, 100);
     65 
     66        context.fillStyle = "rgba(0,0,255,0.498)";
     67        context.fillRect(0, 100, 100, 100);
     68 
     69        context.fillStyle = "rgba(0,0,0,0.498)";
     70        context.fillRect(100, 100, 100, 100);
     71 
     72        return {
     73          source: offscreenCanvas,
     74          origin: { x: 0, y: 0 },
     75          flipY: false,
     76        };
     77      }
     78 
     79      function createSourceImageBitmap() {
     80        const sourceCanvas = createSourceCanvas2d();
     81        return {
     82          source: sourceCanvas.source.transferToImageBitmap(),
     83          origin: { x: 0, y: 0 },
     84          flipY: false,
     85        };
     86      }
     87 
     88      async function mapDestTexture(
     89        device,
     90        source,
     91        destFormat,
     92        premultiply,
     93        copySize
     94      ) {
     95        const bytesPerRow = 256 * 4; // 256 aligned for 200 pixels
     96        const texture = device.createTexture({
     97          format: destFormat,
     98          size: copySize,
     99          usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
    100        });
    101 
    102        device.queue.copyExternalImageToTexture(
    103          source,
    104          { texture, premultipliedAlpha: premultiply },
    105          copySize
    106        );
    107 
    108        const buffer = device.createBuffer({
    109          size: 1024 * 200,
    110          usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
    111        });
    112 
    113        const encoder = device.createCommandEncoder();
    114        encoder.copyTextureToBuffer(
    115          { texture },
    116          { buffer, bytesPerRow },
    117          copySize
    118        );
    119        device.queue.submit([encoder.finish()]);
    120 
    121        await buffer.mapAsync(GPUMapMode.READ);
    122        return buffer;
    123      }
    124 
    125      async function verifyBuffer(
    126        test,
    127        device,
    128        source,
    129        format,
    130        premultiply,
    131        copyDim,
    132        topLeftPixelData
    133      ) {
    134        try {
    135          const buffer = await mapDestTexture(
    136            device,
    137            source,
    138            format,
    139            premultiply,
    140            copyDim
    141          );
    142          const arrayBuffer = buffer.getMappedRange();
    143          const view = new Uint8Array(arrayBuffer);
    144          for (let i = 0; i < topLeftPixelData.length; ++i) {
    145            is(
    146              view[i],
    147              topLeftPixelData[i],
    148              test +
    149                " " +
    150                format +
    151                " (" +
    152                source.origin.x +
    153                "," +
    154                source.origin.y +
    155                ") channel " +
    156                i
    157            );
    158          }
    159        } catch (e) {
    160          ok(false, "WebGPU exception: " + e);
    161        }
    162      }
    163 
    164      async function verifySourceCanvas(test, device, source) {
    165        await verifyBuffer(
    166          test,
    167          device,
    168          source,
    169          "rgba8unorm",
    170          /* premultiply */ true,
    171          { width: 200, height: 200 },
    172          [127, 0, 0, 127]
    173        );
    174        await verifyBuffer(
    175          test,
    176          device,
    177          source,
    178          "bgra8unorm",
    179          /* premultiply */ true,
    180          { width: 200, height: 200 },
    181          [0, 0, 127, 127]
    182        );
    183        await verifyBuffer(
    184          test,
    185          device,
    186          source,
    187          "rgba8unorm",
    188          /* premultiply */ false,
    189          { width: 200, height: 200 },
    190          [255, 0, 0, 127]
    191        );
    192        await verifyBuffer(
    193          test,
    194          device,
    195          source,
    196          "bgra8unorm",
    197          /* premultiply */ false,
    198          { width: 200, height: 200 },
    199          [0, 0, 255, 127]
    200        );
    201 
    202        // The copy is flipped but the origin is relative to the original source data,
    203        // so we need to invert for WebGL.
    204        const topRightPixelData =
    205          test === "webgl" ? [0, 0, 0, 127] : [0, 127, 0, 127];
    206        const topRightOrigin = { origin: { x: 100, y: 0 } };
    207        await verifyBuffer(
    208          test,
    209          device,
    210          { ...source, ...topRightOrigin },
    211          "bgra8unorm",
    212          /* premultiply */ true,
    213          { width: 100, height: 100 },
    214          topRightPixelData
    215        );
    216 
    217        const bottomLeftPixelData =
    218          test === "webgl" ? [0, 0, 127, 127] : [127, 0, 0, 127];
    219        const bottomLeftOrigin = { origin: { x: 0, y: 100 } };
    220        await verifyBuffer(
    221          test,
    222          device,
    223          { ...source, ...bottomLeftOrigin },
    224          "bgra8unorm",
    225          /* premultiply */ true,
    226          { width: 100, height: 100 },
    227          bottomLeftPixelData
    228        );
    229      }
    230 
    231      async function writeDestCanvas(source2d, sourceWebgl, sourceImageBitmap) {
    232        const adapter = await navigator.gpu.requestAdapter();
    233        const device = await adapter.requestDevice();
    234        await verifySourceCanvas("2d", device, source2d);
    235        await verifySourceCanvas("imageBitmap", device, sourceImageBitmap);
    236        await verifySourceCanvas("webgl", device, sourceWebgl);
    237      }
    238 
    239      async function runTest() {
    240        try {
    241          const source2d = createSourceCanvas2d();
    242          const sourceWebgl = createSourceCanvasWebgl();
    243          const sourceImageBitmap = createSourceImageBitmap();
    244          await requestAnimationFramePromise();
    245          await requestAnimationFramePromise();
    246          await writeDestCanvas(source2d, sourceWebgl, sourceImageBitmap);
    247        } catch (e) {
    248          ok(false, "Uncaught exception: " + e);
    249        } finally {
    250          SimpleTest.finish();
    251        }
    252      }
    253 
    254      runTest();
    255    </script>
    256  </body>
    257 </html>