Bug 1257641 - Add a test for APZ paint-skipping and event transformations after a skipped paint. r?botond draft
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 11 Apr 2016 18:58:13 -0400
changeset 349556 6cb0baf71f1b4ba259c0e00c8dac64aee799683c
parent 349555 1e73a8c1582988d01d35522fba212879da78fd09
child 518139 5d3e7da17b90e61a586d9d068d959925ffc16572
push id15128
push userkgupta@mozilla.com
push dateMon, 11 Apr 2016 22:58:31 +0000
reviewersbotond
bugs1257641
milestone48.0a1
Bug 1257641 - Add a test for APZ paint-skipping and event transformations after a skipped paint. r?botond MozReview-Commit-ID: KnKSmueS87J
gfx/layers/apz/test/mochitest/apz_test_utils.js
gfx/layers/apz/test/mochitest/helper_scrollto_tap.html
gfx/layers/apz/test/mochitest/mochitest.ini
gfx/layers/apz/test/mochitest/test_tap.html
--- a/gfx/layers/apz/test/mochitest/apz_test_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_utils.js
@@ -92,8 +92,22 @@ function flushApzRepaints(aCallback, aWi
   SpecialPowers.Services.obs.addObserver(repaintDone, "apz-repaints-flushed", false);
   if (SpecialPowers.getDOMWindowUtils(aWindow).flushApzRepaints()) {
     dump("Flushed APZ repaints, waiting for callback...\n");
   } else {
     dump("Flushing APZ repaints was a no-op, triggering callback directly...\n");
     repaintDone();
   }
 }
+
+function waitForApzFlushedRepaints(aCallback) {
+  // First flush the main-thread paints and send transactions to the APZ
+  waitForAllPaints(function() {
+    // Then flush the APZ to make sure any repaint requests have been sent
+    // back to the main thread
+    flushApzRepaints(function() {
+      // Then flush the main-thread again to process the repaint requests.
+      // Once this is done, we should be in a stable state with nothing
+      // pending, so we can trigger the callback.
+      waitForAllPaints(aCallback);
+    });
+  });
+}
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/test/mochitest/helper_scrollto_tap.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <meta name="viewport" content="width=device-width; initial-scale=1.0">
+  <title>Sanity touch-tapping test</title>
+  <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
+  <script type="application/javascript" src="apz_test_utils.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
+  <script type="application/javascript">
+
+function startTest() {
+  if (window.scrollY == 0) {
+    // the scrollframe is not yet marked as APZ-scrollable. Mark it so and
+    // start over.
+    window.scrollTo(0, 1);
+    waitForApzFlushedRepaints(startTest);
+    return;
+  }
+
+  // This is a scroll by 20px that should use paint-skipping if possible.
+  // If paint-skipping is enabled, this should not trigger a paint, but go
+  // directly to the compositor using an empty transaction. We check for this
+  // by ensuring the document element did not get painted.
+  var utils = window.opener.SpecialPowers.getDOMWindowUtils(window);
+  var elem = document.documentElement;
+  var skipping = location.search == '?true';
+  utils.checkAndClearPaintedState(elem);
+  window.scrollTo(0, 20);
+  waitForAllPaints(function() {
+    window.opener.is(utils.checkAndClearPaintedState(elem), !skipping, "Document element didn't get painted");
+    // After that's done, we click on the button to make sure the
+    // skipped-paint codepath still has working APZ event transformations.
+    clickButton();
+  });
+}
+
+function clickButton() {
+  if (!window.TouchEvent) {
+    window.opener.ok(true, "Touch events are not supported on this platform, sorry!\n");
+    window.opener.testDone();
+    return;
+  }
+
+  document.addEventListener('click', clicked, false);
+
+  synthesizeNativeTap(document.getElementById('b'), 5, 5, function() {
+    dump("Finished synthesizing tap, waiting for button to be clicked...\n");
+  });
+}
+
+function clicked(e) {
+  window.opener.is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
+  window.opener.testDone();
+}
+
+window.onload = function() {
+  waitForAllPaints(function() {
+    flushApzRepaints(startTest);
+  });
+}
+  </script>
+</head>
+<body style="height: 5000px">
+ <div style="height: 50px">spacer</div>
+ <button id="b" style="width: 10px; height: 10px"></button>
+</body>
+</html>
--- a/gfx/layers/apz/test/mochitest/mochitest.ini
+++ b/gfx/layers/apz/test/mochitest/mochitest.ini
@@ -5,16 +5,17 @@ support-files =
   helper_bug982141.html
   helper_bug1151663.html
   helper_iframe1.html
   helper_iframe2.html
   helper_subframe_style.css
   helper_basic_pan.html
   helper_div_pan.html
   helper_iframe_pan.html
+  helper_scrollto_tap.html
   helper_tap.html
 tags = apz
 [test_bug982141.html]
 [test_bug1151663.html]
 [test_wheel_scroll.html]
 skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
 [test_wheel_transactions.html]
 skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
--- a/gfx/layers/apz/test/mochitest/test_tap.html
+++ b/gfx/layers/apz/test/mochitest/test_tap.html
@@ -7,31 +7,69 @@
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <script type="application/javascript">
 
 SimpleTest.waitForExplicitFinish();
 
 // this page just serially loads each one of the following test helper pages in
 // a new window and waits for it to call testDone()
 var tests = [
-  'helper_tap.html',
+  {'file': 'helper_tap.html'},
+  // For the following two tests, disable displayport suppression 10 times to
+  // make sure displayport suppression doesn't interfere with the test.
+  {'file': 'helper_scrollto_tap.html?true', 'prefs': [["apz.paint_skipping.enabled", true]], 'dp_suppression': false},
+  {'file': 'helper_scrollto_tap.html?false', 'prefs': [["apz.paint_skipping.enabled", false]], 'dp_suppression': false}
 ];
 
 var testIndex = -1;
 var w = null;
 
 function testDone() {
+  var test = tests[testIndex];
   if (w) {
+    if (typeof test.dp_suppression != 'undefined') {
+      // We modified the suppression when starting the test, so now undo that.
+      SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(!test.dp_suppression);
+    }
+    if (!!test.prefs) {
+      // We pushed some prefs for this test, pop them, and re-invoke
+      // testDone() after that's been processed
+      SpecialPowers.popPrefEnv(function() {
+        w.close();
+        w = null;
+        testDone();
+      });
+      return;
+    }
+
     w.close();
   }
+
   testIndex++;
-  if (testIndex < tests.length) {
-    w = window.open(tests[testIndex], "_blank");
+  if (testIndex >= tests.length) {
+    SimpleTest.finish();
+    return;
+  }
+
+  test = tests[testIndex];
+  if (typeof test.dp_suppression != 'undefined') {
+    // Normally during a test, the displayport will get suppressed during page
+    // load, and unsuppressed at a non-deterministic time during the test. The
+    // unsuppression can trigger a repaint which interferes with the test, so
+    // to avoid that we can force the displayport to be unsuppressed for the
+    // entire test which is more deterministic.
+    SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(test.dp_suppression);
+  }
+  if (!!test.prefs) {
+    // Got some prefs for this subtest, push them
+    SpecialPowers.pushPrefEnv({"set": test.prefs}, function() {
+      w = window.open(test.file, "_blank");
+    });
   } else {
-    SimpleTest.finish();
+    w = window.open(test.file, "_blank");
   }
 }
 
 window.onload = function() {
   if (!SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled) {
     ok(true, "APZ is not enabled, this test is not relevant, sorry!\n");
     SimpleTest.finish();
     return;