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