Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test OffscreenCanvas.transferToImageBitmap compositing steps (#3612) #3643

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,14 @@
<body>
<div id="description"></div>
<div id="console"></div>
<script id='myWorker' type='text/worker'>
self.onmessage = function(e) {
var canvas = new OffscreenCanvas(128, 128);
var gl = canvas.getContext("webgl");
gl.clearColor(1.0, 1.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
var image = canvas.transferToImageBitmap();

self.postMessage({ bitmap: image },
[ image ]);
};
</script>
<script>
"use strict";
description("This test ensures that the transferToImageBitmap function of OffscreenCanvas webgl context is functional.");
if (!window.OffscreenCanvas) {
testPassed("No OffscreenCanvas support");
finishTest();
} else {
var blob = new Blob([document.getElementById('myWorker').textContent]);
var worker = new Worker(URL.createObjectURL(blob));

worker.onmessage = function(msg) {
testTransferToImageBitmap("webgl", msg.data.bitmap);
finishTest();
}
worker.postMessage("Start Worker");
runTest();
}
</script>
</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,14 @@
<body>
<div id="description"></div>
<div id="console"></div>
<script id='myWorker' type='text/worker'>
self.onmessage = function(e) {
var canvas = new OffscreenCanvas(128, 128);
var gl = canvas.getContext("webgl2");
gl.clearColor(1.0, 1.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
var image = canvas.transferToImageBitmap();

self.postMessage({ bitmap: image },
[ image ]);
};
</script>
<script>
"use strict";
description("This test ensures that the transferToImageBitmap function of OffscreenCanvas webgl2 context is functional.");
if (!window.OffscreenCanvas) {
testPassed("No OffscreenCanvas support");
finishTest();
} else {
var blob = new Blob([document.getElementById('myWorker').textContent]);
var worker = new Worker(URL.createObjectURL(blob));

worker.onmessage = function(msg) {
testTransferToImageBitmap("webgl2", msg.data.bitmap);
finishTest();
}
worker.postMessage("Start Worker");
runTest();
}
</script>
</body>
Expand Down
178 changes: 178 additions & 0 deletions sdk/tests/js/tests/offscreencanvas-transfer-image-bitmap.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,181 @@
let wtu = WebGLTestUtils;
function draw(gl) {
let vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, "attribute vec2 a_pos; void main() { gl_Position = vec4(a_pos, 0.0, 1.0); }");
gl.compileShader(vs);
let fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, "precision mediump float; void main() { gl_FragColor = vec4(1., 1., 1., 1.); }");
gl.compileShader(fs);
let p = gl.createProgram();
gl.attachShader(p, vs);
gl.attachShader(p, fs);
gl.bindAttribLocation(p, 0, "a_pos");
gl.linkProgram(p);
gl.useProgram(p);
gl.viewport(0, 0, 128, 128);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
gl.viewport(0, 0, 128, 128);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's nice to hardcode fewer things.

let verts = [
1.0, 1.0,
-1.0, 1.0,
-1.0, -1.0,
-1.0, -1.0,
1.0, -1.0,
1.0, 1.0
];
let vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 6);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.useProgram(null);
}

function testContent({contextType, depth, stencil, antialias, preserveDrawingBuffer}) {
var canvas = new OffscreenCanvas(128, 128);
var gl = canvas.getContext(contextType, {depth, stencil, antialias, preserveDrawingBuffer});
if (!gl)
return `Skipped, could not create ${contextType} context`;

// Draw the yellow contents and modify the depth and stencil buffers.
gl.clearColor(1.0, 1.0, 0.0, 1.0);
gl.clearDepth(0.0);
gl.clearStencil(255);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
let bitmap = canvas.transferToImageBitmap();

// Test that color buffer was cleared.
var buf = new Uint8Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
let colorClear = buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0;
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT);

// Test that depth buffer was cleared to 1.0.
let depthClear = true;
if (gl.getContextAttributes().depth) {
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.GREATER);
draw(gl);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
depthClear = buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0;
gl.disable(gl.DEPTH_TEST);
gl.clear(gl.COLOR_BUFFER_BIT);
}

// Test that stencil buffer was cleared to 0.
let stencilClear = true;
if (gl.getContextAttributes().stencil) {
gl.enable(gl.STENCIL_TEST);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
gl.stencilFunc(gl.NOTEQUAL, 0, 0xffffffff);
draw(gl);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
stencilClear = buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0;
}
// Test that the context does not flip preserveDrawingBuffer.
let preserveDrawingBufferPreserved = preserveDrawingBuffer == gl.getContextAttributes().preserveDrawingBuffer;
return { bitmap, colorClear, depthClear, stencilClear, preserveDrawingBufferPreserved };
}

function workerScript(subcase) {
return `
${draw}
${testContent}
let result = testContent({contextType: "${subcase.contextType}", depth: ${subcase.depth}, stencil: ${subcase.stencil}, antialias: ${subcase.antialias}, preserveDrawingBuffer: ${subcase.preserveDrawingBuffer}});
self.postMessage(result, [ result.bitmap ]);
`;
}

function nestedWorkerScript(subcase) {
return `
${draw}
${testContent}
${workerScript}
try {
let subcase = { contextType: "${subcase.contextType}", depth: ${subcase.depth}, stencil: ${subcase.stencil}, antialias: ${subcase.antialias}, preserveDrawingBuffer: ${subcase.preserveDrawingBuffer} };
let worker = new Worker(URL.createObjectURL(new Blob([workerScript(subcase)])));
worker.onmessage = function(msg) {
self.postMessage(msg.data, [msg.data.bitmap]);
};
} catch (e) {
self.postMessage("Failed, got exception: " + e);
}
`;
}

function testMain(subcase) {
return testContent(subcase);
}

function testWorker(subcase) {
return new Promise((resolve) => {
let worker = new Worker(URL.createObjectURL(new Blob([workerScript(subcase)])));
worker.onmessage = function(msg) {
resolve(msg.data);
};
});
}

function testNestedWorker(subcase) {
return new Promise((resolve) => {
let worker = new Worker(URL.createObjectURL(new Blob([nestedWorkerScript(subcase)])));
worker.onmessage = function(msg) {
resolve(msg.data);
};
});
}

let tests = [
testMain,
testWorker,
testNestedWorker,
];

let contextType = wtu.getDefault3DContextVersion() == 2 ? "webgl2" : "webgl";
let subcases = [];
for (let test of tests) {
for (let preserveDrawingBuffer of [true, false]) {
for (let antialias of [true, false]) {
for (let depth of [true, false]) {
for (let stencil of [true, false])
subcases.push({test, contextType, preserveDrawingBuffer, antialias, depth, stencil});
}
}
}
}
// To debug one case:
// subcases = [{preserveDrawingBuffer: false, antialias: false, depth: true, stencil: false, contextType, test: testMain}];

let colorClear;
let depthClear;
let stencilClear;
let preserveDrawingBufferPreserved;

async function runTest() {
for (let subcase of subcases) {
debug(`test ${subcase.test.name}, contextType: ${subcase.contextType}, depth: ${subcase.depth}, stencil: ${subcase.stencil}, antialias: ${subcase.antialias}, preserveDrawingBuffer:${subcase.preserveDrawingBuffer}`);
let result = await subcase.test(subcase);
if (typeof result === "string") {
if (result.startsWith("Skipped"))
debug(result);
else
testFailed(result);
continue;
}
testTransferToImageBitmap("webgl", result.bitmap);
colorClear = result.colorClear;
shouldBeTrue("colorClear");
depthClear = result.depthClear;
shouldBeTrue("depthClear");
stencilClear = result.stencilClear;
shouldBeTrue("stencilClear");
preserveDrawingBufferPreserved = result.preserveDrawingBufferPreserved;
shouldBeTrue("preserveDrawingBufferPreserved");
}
finishTest();
}

function testTransferToImageBitmap(webglContextVersion, bitmap) {
var internalFormat = "RGBA";
var pixelFormat = "RGBA";
Expand Down
Loading