summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/mochitest/test_queue_copyExternalImageToTexture.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/webgpu/mochitest/test_queue_copyExternalImageToTexture.html')
-rw-r--r--dom/webgpu/mochitest/test_queue_copyExternalImageToTexture.html261
1 files changed, 261 insertions, 0 deletions
diff --git a/dom/webgpu/mochitest/test_queue_copyExternalImageToTexture.html b/dom/webgpu/mochitest/test_queue_copyExternalImageToTexture.html
new file mode 100644
index 0000000000..279b4a52b4
--- /dev/null
+++ b/dom/webgpu/mochitest/test_queue_copyExternalImageToTexture.html
@@ -0,0 +1,261 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css" />
+ </head>
+
+ <body>
+ <script type="text/javascript">
+ "use strict";
+
+ ok(
+ SpecialPowers.getBoolPref("dom.webgpu.enabled"),
+ "WebGPU pref should be enabled."
+ );
+ ok(
+ SpecialPowers.getBoolPref("gfx.offscreencanvas.enabled"),
+ "OffscreenCanvas pref should be enabled."
+ );
+
+ SimpleTest.waitForExplicitFinish();
+
+ function requestAnimationFramePromise() {
+ return new Promise(requestAnimationFrame);
+ }
+
+ function createSourceCanvasWebgl() {
+ const offscreenCanvas = new OffscreenCanvas(200, 200);
+ const gl = offscreenCanvas.getContext("webgl");
+
+ const COLOR_VALUE = 127.0 / 255.0;
+ const ALPHA_VALUE = 127.0 / 255.0;
+
+ gl.enable(gl.SCISSOR_TEST);
+
+ gl.scissor(0, 0, 100, 100);
+ gl.clearColor(COLOR_VALUE, 0.0, 0.0, ALPHA_VALUE);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.scissor(100, 0, 100, 100);
+ gl.clearColor(0.0, COLOR_VALUE, 0.0, ALPHA_VALUE);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.scissor(0, 100, 100, 100);
+ gl.clearColor(0.0, 0.0, COLOR_VALUE, ALPHA_VALUE);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ gl.scissor(100, 100, 100, 100);
+ gl.clearColor(0.0, 0.0, 0.0, ALPHA_VALUE);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+
+ return {
+ source: offscreenCanvas,
+ origin: { x: 0, y: 0 },
+ flipY: true,
+ };
+ }
+
+ function createSourceCanvas2d() {
+ const offscreenCanvas = new OffscreenCanvas(200, 200);
+ const context = offscreenCanvas.getContext("2d");
+
+ context.fillStyle = "rgba(255,0,0,0.498)";
+ context.fillRect(0, 0, 100, 100);
+
+ context.fillStyle = "rgba(0,255,0,0.498)";
+ context.fillRect(100, 0, 100, 100);
+
+ context.fillStyle = "rgba(0,0,255,0.498)";
+ context.fillRect(0, 100, 100, 100);
+
+ context.fillStyle = "rgba(0,0,0,0.498)";
+ context.fillRect(100, 100, 100, 100);
+
+ return {
+ source: offscreenCanvas,
+ origin: { x: 0, y: 0 },
+ flipY: false,
+ };
+ }
+
+ function createSourceImageBitmap() {
+ const sourceCanvas = createSourceCanvas2d();
+ return {
+ source: sourceCanvas.source.transferToImageBitmap(),
+ origin: { x: 0, y: 0 },
+ flipY: false,
+ };
+ }
+
+ async function mapDestTexture(
+ device,
+ source,
+ destFormat,
+ premultiply,
+ copySize
+ ) {
+ const bytesPerRow = 256 * 4; // 256 aligned for 200 pixels
+ const texture = device.createTexture({
+ format: destFormat,
+ size: copySize,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ });
+
+ device.queue.copyExternalImageToTexture(
+ source,
+ { texture, premultipliedAlpha: premultiply },
+ copySize
+ );
+
+ const buffer = device.createBuffer({
+ size: 1024 * 200,
+ usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
+ });
+
+ const encoder = device.createCommandEncoder();
+ encoder.copyTextureToBuffer(
+ { texture },
+ { buffer, bytesPerRow },
+ copySize
+ );
+ device.queue.submit([encoder.finish()]);
+
+ await buffer.mapAsync(GPUMapMode.READ);
+ return buffer;
+ }
+
+ async function verifyBuffer(
+ test,
+ device,
+ source,
+ format,
+ premultiply,
+ copyDim,
+ topLeftPixelData
+ ) {
+ try {
+ const buffer = await mapDestTexture(
+ device,
+ source,
+ format,
+ premultiply,
+ copyDim
+ );
+ const arrayBuffer = buffer.getMappedRange();
+ const view = new Uint8Array(arrayBuffer);
+ for (let i = 0; i < topLeftPixelData.length; ++i) {
+ is(
+ view[i],
+ topLeftPixelData[i],
+ test +
+ " " +
+ format +
+ " (" +
+ source.origin.x +
+ "," +
+ source.origin.y +
+ ") channel " +
+ i
+ );
+ }
+ } catch (e) {
+ ok(false, "WebGPU exception: " + e);
+ }
+ }
+
+ async function verifySourceCanvas(test, device, source) {
+ await verifyBuffer(
+ test,
+ device,
+ source,
+ "rgba8unorm",
+ /* premultiply */ true,
+ { width: 200, height: 200 },
+ [127, 0, 0, 127]
+ );
+ await verifyBuffer(
+ test,
+ device,
+ source,
+ "bgra8unorm",
+ /* premultiply */ true,
+ { width: 200, height: 200 },
+ [0, 0, 127, 127]
+ );
+ await verifyBuffer(
+ test,
+ device,
+ source,
+ "rgba8unorm",
+ /* premultiply */ false,
+ { width: 200, height: 200 },
+ [255, 0, 0, 127]
+ );
+ await verifyBuffer(
+ test,
+ device,
+ source,
+ "bgra8unorm",
+ /* premultiply */ false,
+ { width: 200, height: 200 },
+ [0, 0, 255, 127]
+ );
+
+ // The copy is flipped but the origin is relative to the original source data,
+ // so we need to invert for WebGL.
+ const topRightPixelData =
+ test === "webgl" ? [0, 0, 0, 127] : [0, 127, 0, 127];
+ const topRightOrigin = { origin: { x: 100, y: 0 } };
+ await verifyBuffer(
+ test,
+ device,
+ { ...source, ...topRightOrigin },
+ "bgra8unorm",
+ /* premultiply */ true,
+ { width: 100, height: 100 },
+ topRightPixelData
+ );
+
+ const bottomLeftPixelData =
+ test === "webgl" ? [0, 0, 127, 127] : [127, 0, 0, 127];
+ const bottomLeftOrigin = { origin: { x: 0, y: 100 } };
+ await verifyBuffer(
+ test,
+ device,
+ { ...source, ...bottomLeftOrigin },
+ "bgra8unorm",
+ /* premultiply */ true,
+ { width: 100, height: 100 },
+ bottomLeftPixelData
+ );
+ }
+
+ async function writeDestCanvas(source2d, sourceWebgl, sourceImageBitmap) {
+ const adapter = await navigator.gpu.requestAdapter();
+ const device = await adapter.requestDevice();
+ await verifySourceCanvas("2d", device, source2d);
+ await verifySourceCanvas("imageBitmap", device, sourceImageBitmap);
+ await verifySourceCanvas("webgl", device, sourceWebgl);
+ }
+
+ async function runTest() {
+ try {
+ const source2d = createSourceCanvas2d();
+ const sourceWebgl = createSourceCanvasWebgl();
+ const sourceImageBitmap = createSourceImageBitmap();
+ await requestAnimationFramePromise();
+ await requestAnimationFramePromise();
+ await writeDestCanvas(source2d, sourceWebgl, sourceImageBitmap);
+ } catch (e) {
+ ok(false, "Uncaught exception: " + e);
+ } finally {
+ SimpleTest.finish();
+ }
+ }
+
+ runTest();
+ </script>
+ </body>
+</html>