257 lines
7.1 KiB
HTML
257 lines
7.1 KiB
HTML
<!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."
|
|
);
|
|
|
|
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>
|