diff options
Diffstat (limited to 'gfx/layers/apz/test/mochitest/test_layerization.html')
-rw-r--r-- | gfx/layers/apz/test/mochitest/test_layerization.html | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/gfx/layers/apz/test/mochitest/test_layerization.html b/gfx/layers/apz/test/mochitest/test_layerization.html new file mode 100644 index 000000000..c74b181bd --- /dev/null +++ b/gfx/layers/apz/test/mochitest/test_layerization.html @@ -0,0 +1,214 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1173580 +--> +<head> + <title>Test for layerization</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script> + <script type="application/javascript" src="apz_test_native_event_utils.js"></script> + <script type="application/javascript" src="apz_test_utils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <link rel="stylesheet" type="text/css" href="helper_subframe_style.css"/> + <style> + #container { + display: flex; + overflow: scroll; + height: 500px; + } + .outer-frame { + height: 500px; + overflow: scroll; + flex-basis: 100%; + background: repeating-linear-gradient(#CCC, #CCC 100px, #BBB 100px, #BBB 200px); + } + #container-content { + height: 200%; + } + </style> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1173580">APZ layerization tests</a> +<p id="display"></p> +<div id="container"> + <div id="outer1" class="outer-frame"> + <div id="inner1" class="inner-frame"> + <div class="inner-content"></div> + </div> + </div> + <div id="outer2" class="outer-frame"> + <div id="inner2" class="inner-frame"> + <div class="inner-content"></div> + </div> + </div> + <iframe id="outer3" class="outer-frame" src="helper_iframe1.html"></iframe> + <iframe id="outer4" class="outer-frame" src="helper_iframe2.html"></iframe> +<!-- The container-content div ensures 'container' is scrollable, so the + optimization that layerizes the primary async-scrollable frame on page + load layerizes it rather than its child subframes. --> + <div id="container-content"></div> +</div> +<pre id="test"> +<script type="application/javascript;version=1.7"> + +// Scroll the mouse wheel over |element|. +function scrollWheelOver(element, waitForScroll, testDriver) { + moveMouseAndScrollWheelOver(element, 10, 10, testDriver, waitForScroll); +} + +const DISPLAYPORT_EXPIRY = 100; + +// This helper function produces another helper function, which, when invoked, +// invokes the provided testDriver argument in a setTimeout 0. This is really +// just useful in cases when there are no paints pending, because then +// waitForAllPaints will invoke its callback synchronously. If we did +// waitForAllPaints(testDriver) that might cause reentrancy into the testDriver +// which is bad. This function works around that. +function asyncWrapper(testDriver) { + return function() { + setTimeout(testDriver, 0); + }; +} + +function* test(testDriver) { + // Initially, nothing should be layerized. + ok(!isLayerized('outer1'), "initially 'outer1' should not be layerized"); + ok(!isLayerized('inner1'), "initially 'inner1' should not be layerized"); + ok(!isLayerized('outer2'), "initially 'outer2' should not be layerized"); + ok(!isLayerized('inner2'), "initially 'inner2' should not be layerized"); + ok(!isLayerized('outer3'), "initially 'outer3' should not be layerized"); + ok(!isLayerized('inner3'), "initially 'inner3' should not be layerized"); + ok(!isLayerized('outer4'), "initially 'outer4' should not be layerized"); + ok(!isLayerized('inner4'), "initially 'inner4' should not be layerized"); + + // Scrolling over outer1 should layerize outer1, but not inner1. + yield scrollWheelOver(document.getElementById('outer1'), true, testDriver); + ok(isLayerized('outer1'), "scrolling 'outer1' should cause it to be layerized"); + ok(!isLayerized('inner1'), "scrolling 'outer1' should not cause 'inner1' to be layerized"); + + // Scrolling over inner2 should layerize both outer2 and inner2. + yield scrollWheelOver(document.getElementById('inner2'), true, testDriver); + ok(isLayerized('inner2'), "scrolling 'inner2' should cause it to be layerized"); + ok(isLayerized('outer2'), "scrolling 'inner2' should also cause 'outer2' to be layerized"); + + // The second half of the test repeats the same checks as the first half, + // but with an iframe as the outer scrollable frame. + + // Scrolling over outer3 should layerize outer3, but not inner3. + yield scrollWheelOver(document.getElementById('outer3').contentDocument.documentElement, true, testDriver); + ok(isLayerized('outer3'), "scrolling 'outer3' should cause it to be layerized"); + ok(!isLayerized('inner3'), "scrolling 'outer3' should not cause 'inner3' to be layerized"); + + // Scrolling over outer4 should layerize both outer4 and inner4. + yield scrollWheelOver(document.getElementById('outer4').contentDocument.getElementById('inner4'), true, testDriver); + ok(isLayerized('inner4'), "scrolling 'inner4' should cause it to be layerized"); + ok(isLayerized('outer4'), "scrolling 'inner4' should also cause 'outer4' to be layerized"); + + // Now we enable displayport expiry, and verify that things are still + // layerized as they were before. + yield SpecialPowers.pushPrefEnv({"set": [["apz.displayport_expiry_ms", DISPLAYPORT_EXPIRY]]}, testDriver); + ok(isLayerized('outer1'), "outer1 is still layerized after enabling expiry"); + ok(!isLayerized('inner1'), "inner1 is still not layerized after enabling expiry"); + ok(isLayerized('outer2'), "outer2 is still layerized after enabling expiry"); + ok(isLayerized('inner2'), "inner2 is still layerized after enabling expiry"); + ok(isLayerized('outer3'), "outer3 is still layerized after enabling expiry"); + ok(!isLayerized('inner3'), "inner3 is still not layerized after enabling expiry"); + ok(isLayerized('outer4'), "outer4 is still layerized after enabling expiry"); + ok(isLayerized('inner4'), "inner4 is still layerized after enabling expiry"); + + // Now we trigger a scroll on some of the things still layerized, so that + // the displayport expiry gets triggered. + + // Expire displayport with scrolling on outer1 + yield scrollWheelOver(document.getElementById('outer1'), true, testDriver); + yield waitForAllPaints(function() { + flushApzRepaints(testDriver); + }); + yield setTimeout(testDriver, DISPLAYPORT_EXPIRY); + yield waitForAllPaints(asyncWrapper(testDriver)); + ok(!isLayerized('outer1'), "outer1 is no longer layerized after displayport expiry"); + ok(!isLayerized('inner1'), "inner1 is still not layerized after displayport expiry"); + + // Expire displayport with scrolling on inner2 + yield scrollWheelOver(document.getElementById('inner2'), true, testDriver); + yield waitForAllPaints(function() { + flushApzRepaints(testDriver); + }); + // Once the expiry elapses, it will trigger expiry on outer2, so we check + // both, one at a time. + yield setTimeout(testDriver, DISPLAYPORT_EXPIRY); + yield waitForAllPaints(asyncWrapper(testDriver)); + ok(!isLayerized('inner2'), "inner2 is no longer layerized after displayport expiry"); + yield setTimeout(testDriver, DISPLAYPORT_EXPIRY); + yield waitForAllPaints(asyncWrapper(testDriver)); + ok(!isLayerized('outer2'), "outer2 got de-layerized with inner2"); + + // Scroll on inner3. inner3 isn't layerized, and this will cause it to + // get layerized, but it will also trigger displayport expiration for inner3 + // which will eventually trigger displayport expiration on inner3 and outer3. + // Note that the displayport expiration might actually happen before the wheel + // input is processed in the compositor (see bug 1246480 comment 3), and so + // we make sure not to wait for a scroll event here, since it may never fire. + // However, if we do get a scroll event while waiting for the expiry, we need + // to restart the expiry timer because the displayport expiry got reset. There's + // no good way that I can think of to deterministically avoid doing this. + let inner3 = document.getElementById('outer3').contentDocument.getElementById('inner3'); + yield scrollWheelOver(inner3, false, testDriver); + yield waitForAllPaints(function() { + flushApzRepaints(testDriver); + }); + var timerId = setTimeout(testDriver, DISPLAYPORT_EXPIRY); + var timeoutResetter = function() { + ok(true, "Got a scroll event; resetting timer..."); + clearTimeout(timerId); + setTimeout(testDriver, DISPLAYPORT_EXPIRY); + // by not updating timerId we ensure that this listener resets the timeout + // at most once. + }; + inner3.addEventListener('scroll', timeoutResetter, false); + yield; // wait for the setTimeout to elapse + inner3.removeEventListener('scroll', timeoutResetter, false); + + yield waitForAllPaints(asyncWrapper(testDriver)); + ok(!isLayerized('inner3'), "inner3 becomes unlayerized after expiry"); + yield setTimeout(testDriver, DISPLAYPORT_EXPIRY); + yield waitForAllPaints(asyncWrapper(testDriver)); + ok(!isLayerized('outer3'), "outer3 is no longer layerized after inner3 triggered expiry"); + + // Scroll outer4 and wait for the expiry. It should NOT get expired because + // inner4 is still layerized + yield scrollWheelOver(document.getElementById('outer4').contentDocument.documentElement, true, testDriver); + yield waitForAllPaints(function() { + flushApzRepaints(testDriver); + }); + // Wait for the expiry to elapse + yield setTimeout(testDriver, DISPLAYPORT_EXPIRY); + yield waitForAllPaints(asyncWrapper(testDriver)); + ok(isLayerized('inner4'), "inner4 is still layerized because it never expired"); + ok(isLayerized('outer4'), "outer4 is still layerized because inner4 is still layerized"); +} + +if (isApzEnabled()) { + SimpleTest.waitForExplicitFinish(); + SimpleTest.requestFlakyTimeout("we are testing code that measures an actual timeout"); + SimpleTest.expectAssertions(0, 8); // we get a bunch of "ASSERTION: Bounds computation mismatch" sometimes (bug 1232856) + + // Disable smooth scrolling, because it results in long-running scroll + // animations that can result in a 'scroll' event triggered by an earlier + // wheel event as corresponding to a later wheel event. + // Also enable APZ test logging, since we use that data to determine whether + // a scroll frame was layerized. + pushPrefs([["general.smoothScroll", false], + ["apz.displayport_expiry_ms", 0], + ["apz.test.logging_enabled", true]]) + .then(waitUntilApzStable) + .then(runContinuation(test)) + .then(SimpleTest.finish); +} + +</script> +</pre> +</body> +</html> |