Bug 1169690 - Gtests. r=kats
authorBotond Ballo <botond@mozilla.com>
Wed, 03 Jun 2015 19:38:50 -0400
changeset 247423 3b1edd0ae65ea24ae91b8ecfca0c5cbeffbedd22
parent 247422 2fffb8a2de13ce9280bc13f73393693db83ed2a3
child 247424 ca22d030c7d7085b2295873344143a3f877e06a3
push id28864
push userkwierso@gmail.com
push dateFri, 05 Jun 2015 21:49:37 +0000
treeherdermozilla-central@97a39c939c51 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1169690
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1169690 - Gtests. r=kats
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/tests/gtest/TestAsyncPanZoomController.cpp
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -540,16 +540,17 @@ public:
       // that this is not noticeable. The target APZC is chosen by seeing if
       // there is an APZC further in the handoff chain which is pannable; if
       // there isn't, we take the new fling ourselves, entering an overscrolled
       // state.
       // Note: APZC is holding mMonitor, so directly calling
       // HandleFlingOverscroll() (which acquires the tree lock) would violate
       // the lock ordering. Instead we schedule HandleFlingOverscroll() to be
       // called after mMonitor is released.
+      APZC_LOG("%p fling went into overscroll, handing off with velocity %s\n", &mApzc, Stringify(velocity).c_str());
       mDeferredTasks.append(NewRunnableMethod(&mApzc,
                                               &AsyncPanZoomController::HandleFlingOverscroll,
                                               velocity,
                                               mOverscrollHandoffChain));
 
       // If there is a remaining velocity on this APZC, continue this fling
       // as well. (This fling and the handed-off fling will run concurrently.)
       // Note that AdjustDisplacement() will have zeroed out the velocity
@@ -2126,16 +2127,17 @@ nsRefPtr<const OverscrollHandoffChain> A
   return result;
 }
 
 void AsyncPanZoomController::AcceptFling(const ParentLayerPoint& aVelocity,
                                          const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
                                          bool aHandoff) {
   // We may have a pre-existing velocity for whatever reason (for example,
   // a previously handed off fling). We don't want to clobber that.
+  APZC_LOG("%p accepting fling with velocity %s\n", this, Stringify(aVelocity).c_str());
   mX.SetVelocity(mX.GetVelocity() + aVelocity.x);
   mY.SetVelocity(mY.GetVelocity() + aVelocity.y);
   SetState(FLING);
   FlingAnimation *fling = new FlingAnimation(*this,
       aOverscrollHandoffChain,
       !aHandoff);  // only apply acceleration if this is an initial fling
 
   float friction = gfxPrefs::APZFlingFriction();
--- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp
+++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp
@@ -201,16 +201,18 @@ public:
     return mFrameMetrics;
   }
 
   const FrameMetrics& GetFrameMetrics() const {
     ReentrantMonitorAutoEnter lock(mMonitor);
     return mFrameMetrics;
   }
 
+  using AsyncPanZoomController::GetVelocityVector;
+
   void AssertStateIsReset() const {
     ReentrantMonitorAutoEnter lock(mMonitor);
     EXPECT_EQ(NOTHING, mState);
   }
 
   void AssertStateIsFling() const {
     ReentrantMonitorAutoEnter lock(mMonitor);
     EXPECT_EQ(FLING, mState);
@@ -1852,16 +1854,32 @@ protected:
     manager = new TestAPZCTreeManager();
   }
 
   virtual void TearDown() {
     while (mcc->RunThroughDelayedTasks());
     manager->ClearTree();
   }
 
+  /**
+   * Sample animations once for all APZCs, 1 ms later than the last sample.
+   */
+  void SampleAnimationsOnce() {
+    const TimeDuration increment = TimeDuration::FromMilliseconds(1);
+    ParentLayerPoint pointOut;
+    ViewTransform viewTransformOut;
+    mcc->AdvanceBy(increment);
+
+    for (const nsRefPtr<Layer>& layer : layers) {
+      if (TestAsyncPanZoomController* apzc = ApzcOf(layer)) {
+        apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
+      }
+    }
+  }
+
   nsRefPtr<MockContentControllerDelayed> mcc;
 
   nsTArray<nsRefPtr<Layer> > layers;
   nsRefPtr<LayerManager> lm;
   nsRefPtr<Layer> root;
 
   nsRefPtr<TestAPZCTreeManager> manager;
 
@@ -2523,31 +2541,69 @@ protected:
     SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID + 2, CSSRect(0, 50, 100, 100));
     SetScrollableFrameMetrics(layers[4], FrameMetrics::START_SCROLL_ID + 3, CSSRect(0, 50, 100, 100));
     SetScrollHandoff(layers[2], layers[1]);
     SetScrollHandoff(layers[4], layers[3]);
     registration = MakeUnique<ScopedLayerTreeRegistration>(0, root, mcc);
     manager->UpdateHitTestingTree(nullptr, root, false, 0, 0);
   }
 
-  void CreateScrollgrabLayerTree() {
+  void CreateScrollgrabLayerTree(bool makeParentScrollable = true) {
     const char* layerTreeSyntax = "c(t)";
     nsIntRegion layerVisibleRegion[] = {
       nsIntRegion(IntRect(0, 0, 100, 100)),  // scroll-grabbing parent
       nsIntRegion(IntRect(0, 20, 100, 80))   // child
     };
     root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, nullptr, lm, layers);
-    SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID, CSSRect(0, 0, 100, 120));
+    float parentHeight = makeParentScrollable ? 120 : 100;
+    SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID, CSSRect(0, 0, 100, parentHeight));
     SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID + 1, CSSRect(0, 0, 100, 200));
     SetScrollHandoff(layers[1], root);
     registration = MakeUnique<ScopedLayerTreeRegistration>(0, root, mcc);
     manager->UpdateHitTestingTree(nullptr, root, false, 0, 0);
     rootApzc = ApzcOf(root);
     rootApzc->GetFrameMetrics().SetHasScrollgrab(true);
   }
+
+  void TestFlingAcceleration() {
+    // Jack up the fling acceleration multiplier so we can easily determine
+    // whether acceleration occured.
+    const float kAcceleration = 100.0f;
+    SCOPED_GFX_PREF(APZFlingAccelBaseMultiplier, float, kAcceleration);
+
+    nsRefPtr<TestAsyncPanZoomController> childApzc = ApzcOf(layers[1]);
+
+    // Pan once, enough to fully scroll the scrollgrab parent and then scroll
+    // and fling the child.
+    Pan(manager, mcc, 70, 40);
+
+    // Give the fling animation a chance to start.
+    SampleAnimationsOnce();
+
+    float childVelocityAfterFling1 = childApzc->GetVelocityVector().y;
+
+    // Pan again.
+    Pan(manager, mcc, 70, 40);
+
+    // Give the fling animation a chance to start.
+    // This time it should be accelerated.
+    SampleAnimationsOnce();
+
+    float childVelocityAfterFling2 = childApzc->GetVelocityVector().y;
+
+    // We should have accelerated once.
+    // The division by 2 is to account for friction.
+    EXPECT_GT(childVelocityAfterFling2,
+              childVelocityAfterFling1 * kAcceleration / 2);
+
+    // We should not have accelerated twice.
+    // The division by 4 is to account for friction.
+    EXPECT_LE(childVelocityAfterFling2,
+              childVelocityAfterFling1 * kAcceleration * kAcceleration / 4);
+  }
 };
 
 // Here we test that if the processing of a touch block is deferred while we
 // wait for content to send a prevent-default message, overscroll is still
 // handed off correctly when the block is processed.
 TEST_F(APZOverscrollHandoffTester, DeferredInputEventProcessing) {
   // Set up the APZC tree.
   CreateOverscrollHandoffLayerTree1();
@@ -2739,16 +2795,26 @@ TEST_F(APZOverscrollHandoffTester, Scrol
   // Pan on the child, not enough to fully scroll the scrollgrab parent.
   Pan(childApzc, mcc, 80, 70);
 
   // Check that it is the scrollgrab parent that's in a fling, not the child.
   rootApzc->AssertStateIsFling();
   childApzc->AssertStateIsReset();
 }
 
+TEST_F(APZOverscrollHandoffTester, ScrollgrabFlingAcceleration1) {
+  CreateScrollgrabLayerTree(true /* make parent scrollable */);
+  TestFlingAcceleration();
+}
+
+TEST_F(APZOverscrollHandoffTester, ScrollgrabFlingAcceleration2) {
+  CreateScrollgrabLayerTree(false /* do not make parent scrollable */);
+  TestFlingAcceleration();
+}
+
 class APZEventRegionsTester : public APZCTreeManagerTester {
 protected:
   UniquePtr<ScopedLayerTreeRegistration> registration;
   TestAsyncPanZoomController* rootApzc;
 
   void CreateEventRegionsLayerTree1() {
     const char* layerTreeSyntax = "c(tt)";
     nsIntRegion layerVisibleRegions[] = {