test_accelerated_canvas_context_loss.html (3832B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Check for contextlost/restored events after GPU process restart</title> 6 <script src="/tests/SimpleTest/SimpleTest.js"></script> 7 <link rel="stylesheet" href="/tests/SimpleTest/test.css"> 8 </head> 9 <body> 10 <canvas id="c" width="512" height="512"></canvas> 11 12 <script type="application/javascript"> 13 14 function waitRAF() { 15 return new Promise((resolve, reject) => { 16 window.requestAnimationFrame(resolve); 17 }); 18 } 19 20 async function restartGPUProcess() { 21 return await SpecialPowers.spawnChrome([], async () => { 22 const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo); 23 24 if (gfxInfo.usingGPUProcess) { 25 const { TestUtils } = ChromeUtils.importESModule( 26 "resource://testing-common/TestUtils.sys.mjs" 27 ); 28 let promise = TestUtils.topicObserved("compositor-reinitialized"); 29 30 const acceleratedCanvas = gfxInfo.usingAcceleratedCanvas; 31 ok(true, "Restarting GPU process, accelerated canvas " + acceleratedCanvas); 32 33 gfxInfo.killGPUProcessForTests(); 34 await promise; 35 36 return acceleratedCanvas; 37 } 38 39 ok(true, "Not using GPU process"); 40 return false; 41 }); 42 } 43 44 const canvas = document.getElementById("c"); 45 const context = canvas.getContext("2d"); 46 47 let restoredPromiseResolve; 48 let restoredPromiseReject; 49 50 const restoredPromise = new Promise((resolve, reject) => { 51 restoredPromiseResolve = resolve; 52 restoredPromiseReject = reject; 53 }); 54 55 let countLostEvents = 0; 56 let countRestoredEvents = 0; 57 58 function onContextLost() { 59 ok(context.isContextLost(), "Canvas context should be lost during contextlost event"); 60 61 try { 62 let transform = context.getTransform(); 63 ok(transform.isIdentity, "Canvas context should return identity transform while context lost"); 64 } catch (e) {} 65 66 countLostEvents += 1; 67 } 68 69 function onContextRestored() { 70 ok(!context.isContextLost(), "Canvas context should not be lost during contextrestored event"); 71 countRestoredEvents += 1; 72 73 restoredPromiseResolve(true); 74 } 75 76 function waitContextRestored() { 77 let timeoutId = window.setTimeout(restoredPromiseReject, 5000); 78 return restoredPromise.then(() => { 79 window.clearTimeout(timeoutId); 80 }); 81 } 82 83 async function start() { 84 try { 85 canvas.addEventListener("contextlost", onContextLost); 86 canvas.addEventListener("contextrestored", onContextRestored); 87 88 ok(!context.isContextLost(), "Canvas context should not be lost before initial fill"); 89 90 context.fillStyle = 'red'; 91 context.fill(); 92 await waitRAF(); 93 94 ok(!context.isContextLost(), "Canvas context should not be lost after initial fill"); 95 96 let transform = context.getTransform(); 97 ok(transform.isIdentity, "Canvas context should default to identity transform"); 98 context.setTransform(2.0, 3.0, 4.0, 5.0, 6.0, 7.0); 99 transform = context.getTransform(); 100 ok(!transform.isIdentity, "Canvas context should have non-identity transform"); 101 102 const restarted = await restartGPUProcess(); 103 const expectedEvents = restarted ? 1 : 0; 104 105 if (expectedEvents) { 106 await waitContextRestored(); 107 } 108 await waitRAF(); 109 110 is(countLostEvents, expectedEvents, "Should have fired " + expectedEvents + " contextlost events"); 111 is(countRestoredEvents, expectedEvents, "Should have fired " + expectedEvents + " contextrestored events"); 112 ok(!context.isContextLost(), "Canvas context should not be lost after restoration"); 113 114 context.fillStyle = 'green'; 115 context.fill(); 116 await waitRAF(); 117 118 ok(!context.isContextLost(), "Canvas context should not be lost at completion"); 119 } catch (err) { 120 ok(false, "Caught exception " + err); 121 } finally { 122 SimpleTest.finish(); 123 } 124 } 125 126 SimpleTest.waitForExplicitFinish(); 127 SimpleTest.requestFlakyTimeout("Wait for failure condition"); 128 start(); 129 130 </script> 131 </body> 132 </html>