4 <title>WebGL in OffscreenCanvas
</title>
5 <script src=
"/tests/SimpleTest/SimpleTest.js"></script>
6 <script src=
"/tests/SimpleTest/WindowSnapshot.js"></script>
7 <link rel=
"stylesheet" href=
"/tests/SimpleTest/test.css">
10 <script type=
"text/js-worker">
11 function ok(expect, msg) {
12 postMessage({
"type":
"status", status: !!expect, msg: msg});
15 onmessage = function(event) {
16 var bitmap = event.data.bitmap;
17 ok(!!bitmap,
"Get the ImageBitmap from the main script.");
19 var offscreenCanvas = new OffscreenCanvas(
64,
64);
20 var ctx = offscreenCanvas.getContext('bitmaprenderer');
21 ok(!!ctx,
"Get bitmaprenderer context on worker.");
23 ctx.transferFromImageBitmap(bitmap);
24 var resultBitmap = offscreenCanvas.transferToImageBitmap();
25 postMessage({
"type":
"bitmap", bitmap: resultBitmap}, [resultBitmap]);
30 SimpleTest
.waitForExplicitFinish();
32 function createCanvas(width
, height
) {
33 var htmlCanvas
= document
.createElement('canvas');
34 htmlCanvas
.width
= width
;
35 htmlCanvas
.height
= height
;
36 document
.body
.appendChild(htmlCanvas
);
40 function runTest(canvasWidth
, canvasHeight
, nextTest
) {
41 var canvas1
= createCanvas(canvasWidth
, canvasHeight
);
42 var ctx
= canvas1
.getContext("2d");
43 ctx
.fillStyle
= "#00FF00";
44 ctx
.fillRect(0, 0, canvasWidth
, canvasHeight
);
46 var canvasRef
= createCanvas(canvasWidth
, canvasHeight
);
47 var ctx
= canvasRef
.getContext("2d");
48 // Clear with black transparent first
49 ctx
.fillStyle
= "rgba(0, 0, 0, 0)";
50 ctx
.fillRect(0, 0, canvasWidth
, canvasHeight
);
52 ctx
.fillStyle
= "#00FF00";
53 ctx
.fillRect(0, 0, canvasWidth
, canvasHeight
);
55 createImageBitmap(canvas1
).then(async
function(bmp
) {
56 document
.body
.removeChild(canvas1
);
58 var canvas2
= createCanvas(90, 90);
59 var ctx2
= canvas2
.getContext("bitmaprenderer");
60 ctx2
.transferFromImageBitmap(bmp
);
62 ok(canvasRef
.toDataURL() == canvas2
.toDataURL(), "toDataURL should return same result.");
65 canvasRef
.style
.display
= "none";
66 canvas2
.style
.display
= "block";
67 var snapshot
= await
snapshotWindow(window
);
69 canvasRef
.style
.display
= "block";
70 canvas2
.style
.display
= "none";
71 var snapshotRef
= await
snapshotWindow(window
);
73 // bitmaprenderers use an ImageLayer whereas a normal 2d canvas uses a canvas layer. This
74 // can result in some anti-aliasing differences on the edge. We consider slight AA differences
75 // to be reasonable when using different codepaths so fuzz a little bit.
76 var fuzz
= { numDifferentPixels
: 0,
78 if (SpecialPowers
.Services
.appinfo
.widgetToolkit
== "android") {
79 fuzz
.maxDifference
= 2;
80 fuzz
.numDifferentPixels
= 131;
82 var results
= compareSnapshots(snapshot
, snapshotRef
, true, fuzz
);
83 ok(results
[0], "Screenshots should be the same");
85 document
.body
.removeChild(canvasRef
);
86 document
.body
.removeChild(canvas2
);
92 function createSolidGreenBitmap(width
, height
) {
93 const canvas
= createCanvas(width
, height
);
94 const ctx
= canvas
.getContext("2d");
95 ctx
.fillStyle
= "#00FF00";
96 ctx
.fillRect(0, 0, width
, height
);
97 const bitmap
= createImageBitmap(canvas
);
98 document
.body
.removeChild(canvas
);
102 async
function scaleTestCase(name
, refWidth
, refHeight
, testWidth
, testHeight
, canvasWidth
, canvasHeight
) {
103 const refBitmap
= await
createSolidGreenBitmap(refWidth
, refHeight
);
104 const refCanvas
= createCanvas(refWidth
, refHeight
);
105 const refCtx
= refCanvas
.getContext("bitmaprenderer");
106 refCtx
.transferFromImageBitmap(refBitmap
);
107 is(refCanvas
.width
, refWidth
, name
+ ": refCanvas width " + refCanvas
.width
+ " is ref " + refWidth
);
108 is(refCanvas
.height
, refHeight
, name
+ ": refCanvas height " + refCanvas
.height
+ " is ref " + refHeight
);
109 const refSnapshot
= await
snapshotWindow(window
);
110 document
.body
.removeChild(refCanvas
);
112 const bitmap
= await
createSolidGreenBitmap(testWidth
, testHeight
);
113 const canvas
= createCanvas(canvasWidth
, canvasHeight
);
114 const ctx
= canvas
.getContext("bitmaprenderer");
115 ctx
.transferFromImageBitmap(bitmap
);
116 is(canvas
.width
, testWidth
, name
+ ": canvas width " + canvas
.width
+ " is bitmap " + testWidth
);
117 is(canvas
.height
, testHeight
, name
+ ": canvas height " + canvas
.height
+ " is bitmap " + testHeight
);
118 if (refWidth
!== testWidth
) {
119 canvas
.width
= refWidth
;
120 is(canvas
.width
, refWidth
, name
+ ": canvas width " + canvas
.width
+ " is ref " + refWidth
);
122 if (refHeight
!== testHeight
) {
123 canvas
.height
= refHeight
;
124 is(canvas
.height
, refHeight
, name
+ ": canvas height " + canvas
.height
+ " is ref " + refHeight
);
126 const snapshot
= await
snapshotWindow(window
);
127 document
.body
.removeChild(canvas
);
129 const results
= compareSnapshots(snapshot
, refSnapshot
, true);
130 ok(results
[0], name
+ ": screenshots should be the same");
131 return Promise
.resolve();
134 async
function scaleTest() {
135 await
scaleTestCase("grow_unscaled", 64, 64, 64, 64, 32, 32); // Canvas grows, no scaling.
136 await
scaleTestCase("grow_downscaled", 64, 64, 128, 128, 32, 32); // Canvas grows, scales down.
137 await
scaleTestCase("grow_upscaled", 64, 64, 32, 32, 16, 16); // Canvas grows, scales up.
138 await
scaleTestCase("same_downscaled", 64, 64, 128, 128, 128, 128); // Canvas unchanged, scales down.
139 await
scaleTestCase("same_upscaled", 64, 64, 32, 32, 32, 32); // Canvas unchanged, scales up.
140 await
scaleTestCase("shrink_unscaled", 64, 64, 64, 64, 128, 128); // Canvas shrinks, no scaling.
141 await
scaleTestCase("shrink_downscaled", 64, 64, 128, 128, 256, 256); // Canvas shrinks, scales down.
142 await
scaleTestCase("shrink_upscaled", 64, 64, 32, 32, 256, 256); // Canvas shrinks, scales up.
146 function runTestOnWorker() {
147 var canvas1
= createCanvas(64, 64);
148 var ctx
= canvas1
.getContext("2d");
149 ctx
.fillStyle
= "#00FF00";
150 ctx
.fillRect(0, 0, 64, 64);
152 var blob
= new Blob(Array
.prototype.map
.call(document
.querySelectorAll("script[type=\"text\/js-worker\"]"), function (oScript
) { return oScript
.textContent
; }),{type
: "text/javascript"});
154 var worker
= new Worker(window
.URL
.createObjectURL(blob
));
156 createImageBitmap(canvas1
).then(function(bmp
) {
157 worker
.postMessage({bitmap
: bmp
}, [bmp
]);
158 worker
.onmessage = function(event
) {
159 if (event
.data
.type
== "status") {
160 ok(event
.data
.status
, event
.data
.msg
);
161 } else if (event
.data
.type
== "bitmap") {
162 var canvas2
= createCanvas(64, 64);
163 var ctx2
= canvas2
.getContext('bitmaprenderer');
164 ctx2
.transferFromImageBitmap(event
.data
.bitmap
);
165 ok(canvas1
.toDataURL() == canvas2
.toDataURL(), 'toDataURL should be the same');
173 runTest(64, 64, runTest
.bind(this, 128, 128, scaleTest
));