helper_checkerboard_scrollinfo.html (3522B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <title>Scrolling a scrollinfo layer and making sure it doesn't checkerboard</title> 5 <script type="application/javascript" src="apz_test_utils.js"></script> 6 <script type="application/javascript" src="apz_test_native_event_utils.js"></script> 7 <script src="/tests/SimpleTest/paint_listener.js"></script> 8 <meta name="viewport" content="width=device-width"/> 9 <style> 10 #withfilter { 11 filter: url(#menushadow); 12 } 13 14 #scroller { 15 width: 300px; 16 height: 1038px; 17 overflow: scroll; 18 } 19 20 .spacer { 21 height: 1878px; 22 background-image: linear-gradient(red, blue); 23 } 24 </style> 25 </head> 26 <body> 27 <div id="withfilter"> 28 <div id="scroller"> 29 <div class="spacer"></div> 30 </div> 31 </div> 32 <!-- the SVG below copied directly from the Gecko Profiler code that 33 demonstrated the original bug. It basically generates a bit of a "drop 34 shadow" effect on the div it's applied to. Original SVG can be found at 35 https://github.com/firefox-devtools/profiler/blame/624f71bce5469cf4f8b2be720e929ba69fa6bfdc/res/img/svg/shadowfilter.svg --> 36 <svg xmlns="http://www.w3.org/2000/svg"> 37 <defs> 38 <filter id="menushadow" color-interpolation-filters="sRGB" x="-10" y="-10" width="30" height="30"> 39 <feComponentTransfer in="SourceAlpha"> 40 <feFuncA type="linear" slope="0.3"/> 41 </feComponentTransfer> 42 <feGaussianBlur stdDeviation="5"/> 43 <feOffset dy="10" result="shadow"/> 44 <feComponentTransfer in="SourceAlpha"> 45 <feFuncA type="linear" slope="0.1"/> 46 </feComponentTransfer> 47 <feMorphology operator="dilate" radius="0.5" result="rim"/> 48 <feMerge><feMergeNode in="shadow"/><feMergeNode in="rim"/></feMerge> 49 <feComposite operator="arithmetic" in2="SourceAlpha" k2="1" k3="-0.1"/> 50 <feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge> 51 </filter> 52 </defs> 53 </svg> 54 </body> 55 <script type="application/javascript"> 56 async function test() { 57 var scroller = document.querySelector("#scroller"); 58 var utils = SpecialPowers.getDOMWindowUtils(window); 59 var scrollerId = utils.getViewId(scroller); 60 61 // Scroll to the bottom of the page, so that the bottom of #scroller is 62 // visible; that's where the checkerboarding happens. 63 document.scrollingElement.scrollTop = document.scrollingElement.scrollTopMax; 64 65 // After the first call to promiseApzFlushedRepaints, the scroller will have 66 // zero displayport margins (because it's inside an SVG filter, and so takes 67 // the "scroll info layer" codepath in APZ's CalculatePendingDisplayPort 68 // function. The main-thread then computes a displayport using those zero 69 // margins and alignment heuristics. If those heuristics are buggy, then the 70 // scroller may end up checkerboarding. That's what we check for on each 71 // scroll increment. 72 73 // The scroll values here just need to be "thorough" enough to exercise the 74 // code at different alignments, so using a non-power-of-two or prime number 75 // for the increment seems like a good idea. The smaller the increment, the 76 // longer the test takes to run (because more iterations) so we don't want it 77 // too small either. 78 for (var y = 3; y <= scroller.scrollTopMax; y += 17) { 79 dump(`Scrolling scroller to ${y}\n`); 80 scroller.scrollTo(0, y); 81 await promiseApzFlushedRepaints(); 82 assertNotCheckerboarded(utils, scrollerId, `At y=${y}`); 83 } 84 } 85 86 waitUntilApzStable() 87 .then(test) 88 .then(subtestDone, subtestFailed); 89 90 </script> 91 </html>