Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<title>JPEG XL integration: canvas WebGPU decode path</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
async function loadImage(src) {
const image = new Image();
await new Promise((resolve, reject) => {
image.onload = resolve;
image.onerror = () => reject(new Error(`image load failed: ${src}`));
image.src = src;
});
return image;
}
function sampleCenterPixelWith2d(image) {
const canvas = document.createElement('canvas');
canvas.width = 3;
canvas.height = 3;
const ctx = canvas.getContext('2d');
assert_true(!!ctx, '2D context available');
ctx.drawImage(image, 0, 0);
return ctx.getImageData(1, 1, 1, 1).data;
}
function assertPixelsApproxEqual(actual, expected, tolerance, messagePrefix) {
for (let i = 0; i < 4; ++i) {
assert_approx_equals(
actual[i], expected[i], tolerance, `${messagePrefix} channel ${i}`);
}
}
async function sampleCenterPixelWithWebGPU(image) {
if (!('gpu' in navigator)) {
return null;
}
const adapter = await navigator.gpu.requestAdapter();
if (!adapter) {
return null;
}
const device = await adapter.requestDevice();
const width = image.naturalWidth || image.width;
const height = image.naturalHeight || image.height;
assert_greater_than(width, 0);
assert_greater_than(height, 0);
const texture = device.createTexture({
size: {width, height, depthOrArrayLayers: 1},
format: 'rgba8unorm',
usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC,
});
device.queue.copyExternalImageToTexture(
{source: image},
{texture},
{width, height, depthOrArrayLayers: 1});
const buffer = device.createBuffer({
size: 4,
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
});
const encoder = device.createCommandEncoder();
encoder.copyTextureToBuffer(
{texture, origin: {x: 1, y: 1, z: 0}},
{buffer},
{width: 1, height: 1, depthOrArrayLayers: 1});
device.queue.submit([encoder.finish()]);
await buffer.mapAsync(GPUMapMode.READ);
const pixel = new Uint8Array(buffer.getMappedRange()).slice(0, 4);
buffer.unmap();
buffer.destroy();
texture.destroy();
return pixel;
}
promise_test(async () => {
const [jxlImage, pngImage] = await Promise.all([
loadImage('resources/3x3_srgb_lossless.jxl'),
loadImage('resources/3x3_srgb_lossless.png'),
]);
const actual = await sampleCenterPixelWithWebGPU(jxlImage);
if (!actual) {
return;
}
const expected = sampleCenterPixelWith2d(pngImage);
assertPixelsApproxEqual(actual, expected, 1, 'WebGPU copyExternalImageToTexture');
}, 'WebGPU copyExternalImageToTexture path with JPEG XL image.');
</script>