summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js')
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js155
1 files changed, 116 insertions, 39 deletions
diff --git a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js
index 05b422f8ea..e88d9d807a 100644
--- a/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js
+++ b/testing/web-platform/mozilla/tests/webgpu/webgpu/web_platform/canvas/readbackFromWebGPUCanvas.spec.js
@@ -14,7 +14,12 @@ The contents of A and B should match.
TODO: implement all canvas types, see TODO on kCanvasTypes.
`;import { makeTestGroup } from '../../../common/framework/test_group.js';
-import { assert, raceWithRejectOnTimeout, unreachable } from '../../../common/util/util.js';
+import {
+ ErrorWithExtra,
+ assert,
+ raceWithRejectOnTimeout,
+ unreachable } from
+'../../../common/util/util.js';
import {
kCanvasAlphaModes,
kCanvasColorSpaces,
@@ -26,8 +31,11 @@ import {
kAllCanvasTypes,
createCanvas,
- createOnscreenCanvas } from
+ createOnscreenCanvas,
+ createOffscreenCanvas } from
'../../util/create_elements.js';
+import { TexelView } from '../../util/texture/texel_view.js';
+import { findFailedPixels } from '../../util/texture/texture_ok.js';
export const g = makeTestGroup(GPUTest);
@@ -61,6 +69,26 @@ const expect = {
])
};
+/**
+ * Given 4 pixels in rgba8unorm format, puts them into an ImageData
+ * of the specified color space and then puts them into an srgb color space
+ * canvas (the default). If the color space is different there will be a
+ * conversion. Returns the resulting 4 pixels in rgba8unorm format.
+ */
+function convertRGBA8UnormBytesToColorSpace(
+expected,
+srcColorSpace,
+dstColorSpace)
+{
+ const srcImgData = new ImageData(2, 2, { colorSpace: srcColorSpace });
+ srcImgData.data.set(expected);
+ const dstCanvas = new OffscreenCanvas(2, 2);
+ const dstCtx = dstCanvas.getContext('2d', { colorSpace: dstColorSpace });
+ assert(dstCtx !== null);
+ dstCtx.putImageData(srcImgData, 0, 0);
+ return dstCtx.getImageData(0, 0, 2, 2).data;
+}
+
function initWebGPUCanvasContent(
t,
format,
@@ -119,7 +147,7 @@ t,
image,
colorSpace)
{
- const canvas = createOnscreenCanvas(t, 2, 2);
+ const canvas = createOffscreenCanvas(t, 2, 2);
const ctx = canvas.getContext('2d', { colorSpace });
assert(ctx !== null);
ctx.drawImage(image, 0, 0);
@@ -147,22 +175,13 @@ sourceData)
// draw the WebGPU derived data into a canvas
const fromWebGPUCtx = drawImageSourceIntoCanvas(t, image, destinationColorSpace);
- // create a 2D canvas with the same source data in the same color space as the WebGPU
- // canvas
- const source2DCanvas = createOnscreenCanvas(t, 2, 2);
- const source2DCtx = source2DCanvas.getContext('2d', { colorSpace: sourceColorSpace });
- assert(source2DCtx !== null);
- const imgData = source2DCtx.getImageData(0, 0, 2, 2);
- imgData.data.set(sourceData);
- source2DCtx.putImageData(imgData, 0, 0);
-
- // draw the source 2D canvas into another 2D canvas with the destination color space and
- // then pull out the data. This result should be the same as the WebGPU derived data
- // written to a 2D canvas of the same destination color space.
- const from2DCtx = drawImageSourceIntoCanvas(t, source2DCanvas, destinationColorSpace);
- const expect = from2DCtx.getImageData(0, 0, 2, 2).data;
-
- readPixelsFrom2DCanvasAndCompare(t, fromWebGPUCtx, expect);
+ const expect = convertRGBA8UnormBytesToColorSpace(
+ sourceData,
+ sourceColorSpace,
+ destinationColorSpace
+ );
+
+ readPixelsFrom2DCanvasAndCompare(t, fromWebGPUCtx, expect, 2);
}
function checkImageResult(
@@ -171,18 +190,55 @@ image,
sourceColorSpace,
expect)
{
+ // canvas(colorSpace)->img(colorSpace)->canvas(colorSpace).drawImage->canvas(colorSpace).getImageData->actual
+ // hard coded data->expected
checkImageResultWithSameColorSpaceCanvas(t, image, sourceColorSpace, expect);
+
+ // canvas(colorSpace)->img(colorSpace)->canvas(diffColorSpace).drawImage->canvas(diffColorSpace).getImageData->actual
+ // hard coded data->ImageData(colorSpace)->canvas(diffColorSpace).putImageData->canvas(diffColorSpace).getImageData->expected
checkImageResultWithDifferentColorSpaceCanvas(t, image, sourceColorSpace, expect);
}
function readPixelsFrom2DCanvasAndCompare(
t,
ctx,
-expect)
+expect,
+maxDiffULPsForNormFormat = 0)
{
- const actual = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height).data;
+ const { width, height } = ctx.canvas;
+ const actual = ctx.getImageData(0, 0, width, height).data;
+
+ const subrectOrigin = [0, 0, 0];
+ const subrectSize = [width, height, 1];
+
+ const areaDesc = {
+ bytesPerRow: width * 4,
+ rowsPerImage: height,
+ subrectOrigin,
+ subrectSize
+ };
+
+ const format = 'rgba8unorm';
+ const actTexelView = TexelView.fromTextureDataByReference(format, actual, areaDesc);
+ const expTexelView = TexelView.fromTextureDataByReference(format, expect, areaDesc);
+
+ const failedPixelsMessage = findFailedPixels(
+ format,
+ { x: 0, y: 0, z: 0 },
+ { width, height, depthOrArrayLayers: 1 },
+ { actTexelView, expTexelView },
+ { maxDiffULPsForNormFormat }
+ );
- t.expectOK(checkElementsEqual(actual, expect));
+ if (failedPixelsMessage !== undefined) {
+ const msg = 'Canvas had unexpected contents:\n' + failedPixelsMessage;
+ t.expectOK(
+ new ErrorWithExtra(msg, () => ({
+ expTexelView,
+ actTexelView
+ }))
+ );
+ }
}
g.test('onscreenCanvas,snapshot').
@@ -284,11 +340,7 @@ fn(async (t) => {
return;
}
const blob = await offscreenCanvas.convertToBlob();
- const url = URL.createObjectURL(blob);
- const img = new Image(offscreenCanvas.width, offscreenCanvas.height);
- img.src = url;
- await raceWithRejectOnTimeout(img.decode(), 5000, 'load image timeout');
- snapshot = img;
+ snapshot = await createImageBitmap(blob);
break;
}
case 'transferToImageBitmap':{
@@ -383,6 +435,19 @@ desc(
- colorSpace = {"srgb", "display-p3"}
- WebGPU canvas type = {"onscreen", "offscreen"}
- 2d canvas type = {"onscreen", "offscreen"}
+
+
+ * makes a webgpu canvas with the given colorSpace and puts data in via copy convoluted
+ copy process
+ * makes a 2d canvas with 'srgb' colorSpace (the default)
+ * draws the webgpu canvas into the 2d canvas so if the color spaces do not match
+ there will be a conversion.
+ * gets the pixels from the 2d canvas via getImageData
+ * compares them to hard coded values that are converted to expected values by copying
+ to an ImageData of the given color space, and then using putImageData into an srgb canvas.
+
+ canvas(colorSpace) -> canvas(srgb).drawImage -> canvas(srgb).getImageData -> actual
+ ImageData(colorSpace) -> canvas(srgb).putImageData -> canvas(srgb).getImageData -> expected
`
).
params((u) =>
@@ -396,35 +461,47 @@ combine('canvas2DType', kAllCanvasTypes)
fn((t) => {
const { format, webgpuCanvasType, alphaMode, colorSpace, canvas2DType } = t.params;
- const canvas = initWebGPUCanvasContent(t, format, alphaMode, colorSpace, webgpuCanvasType);
+ const webgpuCanvas = initWebGPUCanvasContent(
+ t,
+ format,
+ alphaMode,
+ colorSpace,
+ webgpuCanvasType
+ );
- const expectCanvas = createCanvas(t, canvas2DType, canvas.width, canvas.height);
- const ctx = expectCanvas.getContext('2d');
+ const actualCanvas = createCanvas(t, canvas2DType, webgpuCanvas.width, webgpuCanvas.height);
+ const ctx = actualCanvas.getContext('2d');
if (ctx === null) {
t.skip(canvas2DType + ' canvas cannot get 2d context');
return;
}
- ctx.drawImage(canvas, 0, 0);
- readPixelsFrom2DCanvasAndCompare(t, ctx, expect[t.params.alphaMode]);
+ ctx.drawImage(webgpuCanvas, 0, 0);
+
+ readPixelsFrom2DCanvasAndCompare(
+ t,
+ ctx,
+ convertRGBA8UnormBytesToColorSpace(expect[t.params.alphaMode], colorSpace, 'srgb')
+ );
});
g.test('transferToImageBitmap_unconfigured_nonzero_size').
desc(
`Regression test for a crash when calling transferImageBitmap on an unconfigured. Case where the canvas is not empty`
).
+params((u) => u.combine('readbackCanvasType', ['onscreen', 'offscreen'])).
fn((t) => {
- const canvas = createCanvas(t, 'offscreen', 2, 3);
+ const kWidth = 2;
+ const kHeight = 3;
+ const canvas = createCanvas(t, 'offscreen', kWidth, kHeight);
canvas.getContext('webgpu');
// Transferring gives an ImageBitmap of the correct size filled with transparent black.
const ib = canvas.transferToImageBitmap();
- t.expect(ib.width === canvas.width);
- t.expect(ib.height === canvas.height);
+ t.expect(ib.width === kWidth);
+ t.expect(ib.height === kHeight);
- const readbackCanvas = document.createElement('canvas');
- readbackCanvas.width = canvas.width;
- readbackCanvas.height = canvas.height;
+ const readbackCanvas = createCanvas(t, t.params.readbackCanvasType, kWidth, kHeight);
const readbackContext = readbackCanvas.getContext('2d', {
alpha: true
});
@@ -434,7 +511,7 @@ fn((t) => {
}
// Since there isn't a configuration we expect the ImageBitmap to have the default alphaMode of "opaque".
- const expected = new Uint8ClampedArray(canvas.width * canvas.height * 4);
+ const expected = new Uint8ClampedArray(kWidth * kHeight * 4);
for (let i = 0; i < expected.byteLength; i += 4) {
expected[i + 0] = 0;
expected[i + 1] = 0;