Modify CanvasKit to work in a Web Worker and add a demo of it in action.
In this CL: - Modify modules/canvaskit/gpu.js to support the use of OffscreenCanvas. - Add a CanvasKit demos.skia.org demo for CanvasKit in a Web Worker. Change-Id: I8c26bd94f2aa5b3c09cf149b056b910b0e4cd602 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/304320 Reviewed-by: Elliot Evans <elliotevans@google.com> Reviewed-by: Kevin Lubick <kjlubick@google.com> Reviewed-by: Nathaniel Nifong <nifong@google.com> Commit-Queue: Elliot Evans <elliotevans@google.com>
This commit is contained in:
parent
2e66ade997
commit
683bbe01ff
38
demos.skia.org/demos/web_worker/index.html
Normal file
38
demos.skia.org/demos/web_worker/index.html
Normal file
@ -0,0 +1,38 @@
|
||||
<!DOCTYPE html>
|
||||
<title>CanvasKit Web Worker Demo</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<style>
|
||||
canvas {
|
||||
border: 1px dashed grey;
|
||||
}
|
||||
|
||||
.canvas-container {
|
||||
float: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<h1>CanvasKit in a Web Worker demo</h1>
|
||||
<p>NOTE: this demo currently only works in chromium-based browsers, where
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas#Browser_compatibility">
|
||||
Offscreen Canvas
|
||||
</a>
|
||||
is supported.
|
||||
</p>
|
||||
|
||||
<div class="canvas-container">
|
||||
<h2>Normal Canvas</h2>
|
||||
<canvas id="onscreen-canvas" width=500 height=500></canvas>
|
||||
<button id="busy-button">Make main thread busy</button>
|
||||
</div>
|
||||
<div class="canvas-container">
|
||||
<h2>Web Worker Canvas</h2>
|
||||
<canvas id="offscreen-canvas" width=500 height=500></canvas>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript" src="https://particles.skia.org/static/canvaskit.js"></script>
|
||||
<script type="text/javascript" src="shared.js"></script>
|
||||
<script type="text/javascript" src="main.js"></script>
|
34
demos.skia.org/demos/web_worker/main.js
Normal file
34
demos.skia.org/demos/web_worker/main.js
Normal file
@ -0,0 +1,34 @@
|
||||
// Set up worker and send it a message with the canvas to draw to.
|
||||
const offscreenCanvas = document.getElementById('offscreen-canvas').transferControlToOffscreen();
|
||||
const worker = new Worker('worker.js');
|
||||
worker.postMessage({ offscreenCanvas }, [offscreenCanvas]);
|
||||
|
||||
const canvasKitInitPromise =
|
||||
CanvasKitInit({locateFile: (file) => 'https://particles.skia.org/static/'+file});
|
||||
const skottieJsonPromise =
|
||||
fetch('https://storage.googleapis.com/skia-cdn/misc/lego_loader.json')
|
||||
.then((response) => response.text());
|
||||
|
||||
Promise.all([
|
||||
canvasKitInitPromise,
|
||||
skottieJsonPromise
|
||||
]).then(([
|
||||
CanvasKit,
|
||||
jsonStr
|
||||
]) => {
|
||||
const onscreenCanvas = document.getElementById('onscreen-canvas');
|
||||
const surface = CanvasKit.MakeWebGLCanvasSurface(onscreenCanvas, null);
|
||||
if (!surface) {
|
||||
throw 'Could not make canvas surface';
|
||||
}
|
||||
|
||||
SkottieExample(CanvasKit, surface, jsonStr);
|
||||
});
|
||||
|
||||
document.getElementById('busy-button').addEventListener('click', () => {
|
||||
const startTime = performance.now();
|
||||
// This loop runs for 1300ms, emulating computation.
|
||||
// 1300ms was chosen because it causes a visually obvious lag in the lego loader animation.
|
||||
while (performance.now() - startTime < 1300) {
|
||||
}
|
||||
});
|
21
demos.skia.org/demos/web_worker/shared.js
Normal file
21
demos.skia.org/demos/web_worker/shared.js
Normal file
@ -0,0 +1,21 @@
|
||||
function SkottieExample(CanvasKit, surface, jsonStr, bounds) {
|
||||
if (!CanvasKit || !jsonStr) {
|
||||
return;
|
||||
}
|
||||
const animation = CanvasKit.MakeAnimation(jsonStr);
|
||||
const duration = animation.duration() * 1000;
|
||||
bounds = {fLeft: 0, fTop: 0, fRight: 500, fBottom: 500};
|
||||
|
||||
const firstFrame = performance.now();
|
||||
|
||||
function drawFrame(skcanvas) {
|
||||
const now = performance.now();
|
||||
const seek = ((now - firstFrame) / duration) % 1.0;
|
||||
|
||||
animation.seek(seek);
|
||||
animation.render(skcanvas, bounds);
|
||||
|
||||
surface.requestAnimationFrame(drawFrame);
|
||||
}
|
||||
surface.requestAnimationFrame(drawFrame);
|
||||
}
|
27
demos.skia.org/demos/web_worker/worker.js
Normal file
27
demos.skia.org/demos/web_worker/worker.js
Normal file
@ -0,0 +1,27 @@
|
||||
importScripts('https://particles.skia.org/static/canvaskit.js');
|
||||
importScripts('shared.js');
|
||||
|
||||
const transferCanvasToOffscreenPromise =
|
||||
new Promise((resolve) => addEventListener('message', resolve));
|
||||
const canvasKitInitPromise =
|
||||
CanvasKitInit({locateFile: (file) => 'https://particles.skia.org/static/'+file});
|
||||
const skottieJsonPromise =
|
||||
fetch('https://storage.googleapis.com/skia-cdn/misc/lego_loader.json')
|
||||
.then((response) => response.text());
|
||||
|
||||
Promise.all([
|
||||
transferCanvasToOffscreenPromise,
|
||||
canvasKitInitPromise,
|
||||
skottieJsonPromise
|
||||
]).then(([
|
||||
{ data: { offscreenCanvas } },
|
||||
CanvasKit,
|
||||
jsonStr
|
||||
]) => {
|
||||
const surface = CanvasKit.MakeWebGLCanvasSurface(offscreenCanvas, null);
|
||||
if (!surface) {
|
||||
throw 'Could not make canvas surface';
|
||||
}
|
||||
|
||||
SkottieExample(CanvasKit, surface, jsonStr);
|
||||
});
|
@ -58,7 +58,9 @@
|
||||
CanvasKit.MakeWebGLCanvasSurface = function(idOrElement, colorSpace, attrs) {
|
||||
colorSpace = colorSpace || null;
|
||||
var canvas = idOrElement;
|
||||
if (canvas.tagName !== 'CANVAS') {
|
||||
var isHTMLCanvas = typeof HTMLCanvasElement !== 'undefined' && canvas instanceof HTMLCanvasElement;
|
||||
var isOffscreenCanvas = canvas instanceof OffscreenCanvas;
|
||||
if (!isHTMLCanvas && !isOffscreenCanvas) {
|
||||
canvas = document.getElementById(idOrElement);
|
||||
if (!canvas) {
|
||||
throw 'Canvas with id ' + idOrElement + ' was not found';
|
||||
|
Loading…
Reference in New Issue
Block a user