1*c8dee2aaSAndroid Build Coastguard Worker<!DOCTYPE html> 2*c8dee2aaSAndroid Build Coastguard Worker<html> 3*c8dee2aaSAndroid Build Coastguard Worker<head> 4*c8dee2aaSAndroid Build Coastguard Worker <title>Skottie-WASM Perf</title> 5*c8dee2aaSAndroid Build Coastguard Worker <meta charset="utf-8" /> 6*c8dee2aaSAndroid Build Coastguard Worker <meta http-equiv="X-UA-Compatible" content="IE=edge"> 7*c8dee2aaSAndroid Build Coastguard Worker <meta name="viewport" content="width=device-width, initial-scale=1.0"> 8*c8dee2aaSAndroid Build Coastguard Worker <script src="res/canvaskit.js" type="text/javascript" charset="utf-8"></script> 9*c8dee2aaSAndroid Build Coastguard Worker <style type="text/css" media="screen"> 10*c8dee2aaSAndroid Build Coastguard Worker body { 11*c8dee2aaSAndroid Build Coastguard Worker margin: 0; 12*c8dee2aaSAndroid Build Coastguard Worker padding: 0; 13*c8dee2aaSAndroid Build Coastguard Worker } 14*c8dee2aaSAndroid Build Coastguard Worker </style> 15*c8dee2aaSAndroid Build Coastguard Worker</head> 16*c8dee2aaSAndroid Build Coastguard Worker<body> 17*c8dee2aaSAndroid Build Coastguard Worker <main> 18*c8dee2aaSAndroid Build Coastguard Worker <canvas id=anim width=1000 height=1000 style="height: 1000px; width: 1000px;"></canvas> 19*c8dee2aaSAndroid Build Coastguard Worker </main> 20*c8dee2aaSAndroid Build Coastguard Worker <script type="text/javascript" charset="utf-8"> 21*c8dee2aaSAndroid Build Coastguard Worker const WIDTH = 1000; 22*c8dee2aaSAndroid Build Coastguard Worker const HEIGHT = 1000; 23*c8dee2aaSAndroid Build Coastguard Worker const LOTTIE_JSON_PATH = '/res/lottie.json'; 24*c8dee2aaSAndroid Build Coastguard Worker const MAX_FRAMES = 25; 25*c8dee2aaSAndroid Build Coastguard Worker const MAX_LOOPS = 25; 26*c8dee2aaSAndroid Build Coastguard Worker const MAX_SAMPLE_MS = 60*1000; // in case something takes a while, stop after 60 seconds. 27*c8dee2aaSAndroid Build Coastguard Worker (function() { 28*c8dee2aaSAndroid Build Coastguard Worker const loadKit = CanvasKitInit({ 29*c8dee2aaSAndroid Build Coastguard Worker locateFile: (file) => '/res/' + file, 30*c8dee2aaSAndroid Build Coastguard Worker }); 31*c8dee2aaSAndroid Build Coastguard Worker 32*c8dee2aaSAndroid Build Coastguard Worker const loadLottie = fetch(LOTTIE_JSON_PATH).then((resp) => { 33*c8dee2aaSAndroid Build Coastguard Worker return resp.text(); 34*c8dee2aaSAndroid Build Coastguard Worker }); 35*c8dee2aaSAndroid Build Coastguard Worker 36*c8dee2aaSAndroid Build Coastguard Worker Promise.all([loadKit, loadLottie]).then((values) => { 37*c8dee2aaSAndroid Build Coastguard Worker const [CanvasKit, json] = values; 38*c8dee2aaSAndroid Build Coastguard Worker 39*c8dee2aaSAndroid Build Coastguard Worker const animation = CanvasKit.MakeManagedAnimation(json, null); 40*c8dee2aaSAndroid Build Coastguard Worker if (!animation) { 41*c8dee2aaSAndroid Build Coastguard Worker window._error = 'Could not process JSON'; 42*c8dee2aaSAndroid Build Coastguard Worker return 43*c8dee2aaSAndroid Build Coastguard Worker } 44*c8dee2aaSAndroid Build Coastguard Worker 45*c8dee2aaSAndroid Build Coastguard Worker let surface = null; 46*c8dee2aaSAndroid Build Coastguard Worker if (window.location.hash.indexOf('gpu') !== -1) { 47*c8dee2aaSAndroid Build Coastguard Worker surface = CanvasKit.MakeWebGLCanvasSurface('anim'); 48*c8dee2aaSAndroid Build Coastguard Worker if (!surface) { 49*c8dee2aaSAndroid Build Coastguard Worker window._error = 'Could not make GPU surface'; 50*c8dee2aaSAndroid Build Coastguard Worker return; 51*c8dee2aaSAndroid Build Coastguard Worker } 52*c8dee2aaSAndroid Build Coastguard Worker let c = document.getElementById('anim'); 53*c8dee2aaSAndroid Build Coastguard Worker // If CanvasKit was unable to instantiate a WebGL context, it will fallback 54*c8dee2aaSAndroid Build Coastguard Worker // to CPU and add a ck-replaced class to the canvas element. 55*c8dee2aaSAndroid Build Coastguard Worker if (c.classList.contains('ck-replaced')) { 56*c8dee2aaSAndroid Build Coastguard Worker window._error = 'fell back to CPU'; 57*c8dee2aaSAndroid Build Coastguard Worker return; 58*c8dee2aaSAndroid Build Coastguard Worker } 59*c8dee2aaSAndroid Build Coastguard Worker } else { 60*c8dee2aaSAndroid Build Coastguard Worker surface = CanvasKit.MakeSWCanvasSurface('anim'); 61*c8dee2aaSAndroid Build Coastguard Worker if (!surface) { 62*c8dee2aaSAndroid Build Coastguard Worker window._error = 'Could not make CPU surface'; 63*c8dee2aaSAndroid Build Coastguard Worker return; 64*c8dee2aaSAndroid Build Coastguard Worker } 65*c8dee2aaSAndroid Build Coastguard Worker } 66*c8dee2aaSAndroid Build Coastguard Worker const canvas = surface.getCanvas(); 67*c8dee2aaSAndroid Build Coastguard Worker 68*c8dee2aaSAndroid Build Coastguard Worker const t_rate = 1.0 / (MAX_FRAMES-1); 69*c8dee2aaSAndroid Build Coastguard Worker let seek = 0; 70*c8dee2aaSAndroid Build Coastguard Worker let frame = 0; 71*c8dee2aaSAndroid Build Coastguard Worker let loop = 0; 72*c8dee2aaSAndroid Build Coastguard Worker const damageRect = Float32Array.of(0, 0, 0, 0); 73*c8dee2aaSAndroid Build Coastguard Worker const bounds = CanvasKit.LTRBRect(0, 0, WIDTH, HEIGHT); 74*c8dee2aaSAndroid Build Coastguard Worker const start = performance.now(); 75*c8dee2aaSAndroid Build Coastguard Worker 76*c8dee2aaSAndroid Build Coastguard Worker const drawFrame = () => { 77*c8dee2aaSAndroid Build Coastguard Worker if ((performance.now() - start) > MAX_SAMPLE_MS) { 78*c8dee2aaSAndroid Build Coastguard Worker // This global variable signals we are done. 79*c8dee2aaSAndroid Build Coastguard Worker window._skottieDone = true; 80*c8dee2aaSAndroid Build Coastguard Worker return; 81*c8dee2aaSAndroid Build Coastguard Worker } 82*c8dee2aaSAndroid Build Coastguard Worker if (frame >= MAX_FRAMES) { 83*c8dee2aaSAndroid Build Coastguard Worker // Reached the end of one loop. 84*c8dee2aaSAndroid Build Coastguard Worker loop++; 85*c8dee2aaSAndroid Build Coastguard Worker if (loop == MAX_LOOPS) { 86*c8dee2aaSAndroid Build Coastguard Worker // This global variable signals we are done. 87*c8dee2aaSAndroid Build Coastguard Worker window._skottieDone = true; 88*c8dee2aaSAndroid Build Coastguard Worker return; 89*c8dee2aaSAndroid Build Coastguard Worker } 90*c8dee2aaSAndroid Build Coastguard Worker // Reset frame and seek to restart the loop. 91*c8dee2aaSAndroid Build Coastguard Worker frame = 0; 92*c8dee2aaSAndroid Build Coastguard Worker seek = 0; 93*c8dee2aaSAndroid Build Coastguard Worker } 94*c8dee2aaSAndroid Build Coastguard Worker 95*c8dee2aaSAndroid Build Coastguard Worker let damage = animation.seek(seek, damageRect); 96*c8dee2aaSAndroid Build Coastguard Worker if (damage[2] > damage[0] && damage[3] > damage[1]) { 97*c8dee2aaSAndroid Build Coastguard Worker animation.render(canvas, bounds); 98*c8dee2aaSAndroid Build Coastguard Worker surface.flush(); 99*c8dee2aaSAndroid Build Coastguard Worker } 100*c8dee2aaSAndroid Build Coastguard Worker console.log(`Used seek: ${seek}`); 101*c8dee2aaSAndroid Build Coastguard Worker seek += t_rate; 102*c8dee2aaSAndroid Build Coastguard Worker frame++; 103*c8dee2aaSAndroid Build Coastguard Worker window.requestAnimationFrame(drawFrame); 104*c8dee2aaSAndroid Build Coastguard Worker }; 105*c8dee2aaSAndroid Build Coastguard Worker window.requestAnimationFrame(drawFrame); 106*c8dee2aaSAndroid Build Coastguard Worker }); 107*c8dee2aaSAndroid Build Coastguard Worker })(); 108*c8dee2aaSAndroid Build Coastguard Worker </script> 109*c8dee2aaSAndroid Build Coastguard Worker</body> 110*c8dee2aaSAndroid Build Coastguard Worker</html> 111