Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Errors
- This test gets skipped with pattern: os == 'android' && debug
- This test failed 4 times in the preceding 30 days. quicksearch this test
- Manifest: dom/canvas/test/mochitest.toml
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>WebGL in OffscreenCanvas</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
<body>
<canvas id="c1" width="64" height="64"></canvas>
<canvas id="c2" width="64" height="64"></canvas>
<canvas id="c_ref" width="64" height="64"></canvas>
<script>
function testWorker(onFinished) {
var worker = new Worker("offscreencanvas.js");
ok(worker, "Web worker successfully created");
worker.onmessage = function(evt) {
var msg = evt.data || {};
//console.log('onmessage', {evt}, msg.type, msg.result, msg.name);
if (msg.type == "test") {
ok(msg.result, msg.name);
}
if (msg.type == "imagebitmap") {
// testing toBlob
// Fill c_ref with green color.
var ctx = c_ref.getContext("2d");
ctx.rect(0, 0, 64, 64);
ctx.fillStyle = "#00FF00";
ctx.fill();
var bitmapRenderer = c1.getContext("bitmaprenderer");
bitmapRenderer.transferFromImageBitmap(msg.bitmap);
ok(c1.toDataURL() == c_ref.toDataURL(),
"c1.toDataURL MUST return a 64x64 green square");
// The ownership of msg.bitmap should be transferred to canvas c1 when
// we called transferFromImageBitmap, marking msg.bitmap as "detached".
// Ensure that transferFromImageBitmap again should throw.
var bitmapRenderer = c2.getContext("bitmaprenderer");
let didThrow = false;
try {
bitmapRenderer.transferFromImageBitmap(msg.bitmap)
} catch (e) {
didThrow = true;
}
ok(didThrow, 'transferFromImageBitmap(detached) must throw');
ok(c1.toDataURL() == c_ref.toDataURL(),
"c2.toDataURL MUST NOT return a 64x64 green square");
worker.terminate();
onFinished();
}
}
worker.postMessage({test: 'webgl_imagebitmap'});
}
function expectEq(name, expected, was, when) {
let msg = `${name} was ${was}`;
if (when) {
msg = `[${when}] ` + msg;
}
let eq = (was == expected);
if (!eq) {
if (typeof(expected) == 'number') {
eq = (Math.abs(was - expected) < 0.000001);
}
}
if (!eq) {
msg = msg + `, expected ${expected}`;
}
ok(eq, msg);
}
function expectMemberEq(obj, key, expected, when) {
const was = obj[key];
expectEq(`${obj}.${key}`, expected, was, when);
}
function expectEachMemberEq(obj, expectedByKeyMap, when) {
for (const [key,expected] of Object.entries(expectedByKeyMap)) {
expectMemberEq(obj, key, expected, when);
}
}
function note(text) {
console.log(text);
ok(true, text);
}
function invoke(fn) { return fn(); }
invoke(async () => {
SimpleTest.waitForExplicitFinish();
await new Promise(go =>
SpecialPowers.pushPrefEnv({'set': [
['webgl.force-enabled', true],
]}, go));
console.log('await testWorker...');
await new Promise(go => testWorker(go));
// -
const [W, H] = [5, 7];
note('Begin canvas2d transferToImageBitmap tests...');
{
const oc = new OffscreenCanvas(W, H);
const c2d = oc.getContext('2d');
c2d.fillStyle = '#00ff00';
c2d.fillRect(0, 0, W, H);
{
const idata = c2d.getImageData(0, 0, W, H);
expectEq('getImageData.data.slice(0, 4)', '[0,255,0,255]',
`[${idata.data.slice(0,4).join(',')}]`, 'after fillRect');
}
// -
const NON_DEFAULT_STATE_2D = {
direction: 'rtl',
fillStyle: '#aaaaaa',
font: '13px serif',
fontKerning: 'none',
globalAlpha: 0.42,
globalCompositeOperation: 'xor',
imageSmoothingEnabled: false,
imageSmoothingQuality: 'high',
lineCap: 'round',
lineDashOffset: 4.2,
lineJoin: 'round',
lineWidth: 3.14,
miterLimit: 1.0,
shadowBlur: 1,
shadowColor: '#bbbbbb',
shadowOffsetX: 2,
shadowOffsetY: 3,
strokeStyle: '#cccccc',
textAlign: 'right',
textBaseline: 'middle',
};
Object.assign(c2d, NON_DEFAULT_STATE_2D);
expectEachMemberEq(c2d, NON_DEFAULT_STATE_2D, 'before transferToImageBitmap');
const beforeTtibData = c2d.getImageData(0, 0, W, H);
const ib = oc.transferToImageBitmap();
const afterTtibData = c2d.getImageData(0, 0, W, H);
// Same state afterwards
expectEachMemberEq(oc, {width: W, height: H}, 'after transferToImageBitmap');
expectEachMemberEq(c2d, NON_DEFAULT_STATE_2D, 'after transferToImageBitmap');
// But bitmap cleared afterwards
let was = `[${afterTtibData.data.slice(0, 4).join(',')}]`;
expectEq('getImageData.data.slice(0, 4)', '[0,0,0,0]', was, 'after transferToImageBitmap');
}
note('Begin webgl transferToImageBitmap tests...');
{
const oc = new OffscreenCanvas(W, H);
const gl = oc.getContext('webgl', {preserveDrawingBuffer:true});
gl.clearColor(0, 1, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
const p = new Uint8Array(4);
gl.readPixels(0,0,1,1, gl.RGBA, gl.UNSIGNED_BYTE, p);
expectEq('gl.readPixels(0,0,1,1)', '[0,255,0,255]',
`[${p.slice(0,4).join(',')}]`, 'after gl.clear');
// -
const buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
expectEq(`ARRAY_BUFFER_BINDING`, buf,
gl.getParameter(gl.ARRAY_BUFFER_BINDING), 'before transferToImageBitmap');
const ib = oc.transferToImageBitmap();
// Same state afterwards
expectEachMemberEq(oc, {width: W, height: H}, 'after transferToImageBitmap');
expectEq(`ARRAY_BUFFER_BINDING`, buf,
gl.getParameter(gl.ARRAY_BUFFER_BINDING), 'after transferToImageBitmap');
// But bitmap cleared afterwards
gl.readPixels(0,0,1,1, gl.RGBA, gl.UNSIGNED_BYTE, p);
expectEq('gl.readPixels(0,0,1,1)', '[0,0,0,0]',
`[${p.slice(0,4).join(',')}]`, 'after transferToImageBitmap');
}
note('Tests complete.');
SimpleTest.finish();
});
</script>
</body>
</html>