1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
<!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': [
['gfx.offscreencanvas.enabled', true],
['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>
|