helper_checkerboard_apzforcedisabled.html (3927B)
1 <!DOCTYPE HTML> 2 <html id="root-element"> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width; initial-scale=1.0"> 6 <title>Checkerboarding while root scrollframe async-scrolls and a 7 subframe has APZ force disabled</title> 8 <script type="application/javascript" src="apz_test_utils.js"></script> 9 <script type="application/javascript" src="apz_test_native_event_utils.js"></script> 10 <script src="/tests/SimpleTest/paint_listener.js"></script> 11 <script type="application/javascript"> 12 13 async function test() { 14 var utils = SpecialPowers.getDOMWindowUtils(window); 15 var subframe = document.getElementById('subframe'); 16 17 // layerize subframe 18 await promiseNativeMouseEventWithAPZAndWaitForEvent({ 19 type: "click", 20 target: subframe, 21 offsetX: 10, 22 offsetY: 10, 23 }); 24 25 // verify layerization 26 await promiseAllPaintsDone(); 27 ok(isLayerized("subframe"), "subframe should be layerized at this point"); 28 var subframeScrollId = utils.getViewId(subframe); 29 ok(subframeScrollId > 0, "subframe should have a scroll id"); 30 31 // then disable APZ for it 32 utils.disableApzForElement(subframe); 33 34 // wait for the dust to settle 35 await promiseAllPaintsDone(); 36 37 // Check that the root element's displayport has at least 500px of vertical 38 // displayport margin on either side. This will ensure that we can scroll 39 // by 500px without causing the displayport to move, which in turn means that 40 // the scroll will not trigger repaints (due to paint-skipping). 41 var rootElem = document.documentElement; 42 var rootDisplayport = getLastContentDisplayportFor(rootElem.id); 43 ok(rootDisplayport != null, "root element should have a displayport"); 44 dump("root dp: " + JSON.stringify(rootDisplayport) + 45 ", height: " + rootElem.clientHeight); 46 var rootDpVerticalMargin = (rootDisplayport.height - rootElem.clientHeight) / 2; 47 ok(rootDpVerticalMargin > 500, 48 "root element should have at least 500px of vertical displayport margin"); 49 50 // Scroll enough that we reveal new parts of the subframe, but not so much 51 // that the root displayport starts moving. If the root displayport moves, 52 // the main-thread will trigger a repaint of the subframe, but if the root 53 // displayport doesn't move, we get a paint-skipped scroll which is where the 54 // bug manifests. (The bug being that the subframe ends in a visual perma- 55 // checkerboarding state). Note that we do an 'auto' behavior scroll so 56 // that it's "instant" rather than an animation. Animations would demonstrate 57 // the bug too but are more complicated to wait for. 58 window.scrollBy({top: 500, left: 0, behavior: 'auto'}); 59 is(window.scrollY, 500, "document got scrolled instantly"); 60 61 // Note that at this point we must NOT call promiseOnlyApzControllerFlushed, because 62 // otherwise APZCCallbackHelper::NotifyFlushComplete will trigger a repaint 63 // (for unrelated reasons), and the repaint will clear the checkerboard 64 // state. We do, however, want to wait for a "steady state" here that 65 // includes all pending paints from the main thread and a composite that 66 // samples the APZ state. In order to accomplish this we wait for all the main 67 // thread paints, and then force a composite via advanceTimeAndRefresh. The 68 // advanceTimeAndRefresh has the additional advantage of freezing the refresh 69 // driver which avoids any additional externally-triggered repaints from 70 // erasing the symptoms of the bug. 71 await promiseAllPaintsDone(); 72 assertNotCheckerboarded(utils, subframeScrollId, "subframe"); 73 } 74 75 waitUntilApzStable() 76 .then(test) 77 .then(subtestDone, subtestFailed); 78 79 </script> 80 <style> 81 #subframe { 82 overflow-x: auto; 83 margin-left: 100px; /* makes APZ minimap easier to see */ 84 } 85 </style> 86 </head> 87 <body> 88 <div id="subframe"> 89 <div style="width: 10000px; height: 10000px; background-image: linear-gradient(green, red)"> 90 </div> 91 </div> 92 </body> 93 </html>