LCOV - code coverage report
Current view: top level - gfx/layers/apz/src - GenericFlingAnimation.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 60 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set sw=2 ts=8 et tw=80 : */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef mozilla_layers_GenericFlingAnimation_h_
       8             : #define mozilla_layers_GenericFlingAnimation_h_
       9             : 
      10             : #include "APZUtils.h"
      11             : #include "AsyncPanZoomAnimation.h"
      12             : #include "AsyncPanZoomController.h"
      13             : #include "FrameMetrics.h"
      14             : #include "Layers.h"
      15             : #include "Units.h"
      16             : #include "OverscrollHandoffState.h"
      17             : #include "gfxPrefs.h"
      18             : #include "mozilla/Assertions.h"
      19             : #include "mozilla/Monitor.h"
      20             : #include "mozilla/RefPtr.h"
      21             : #include "mozilla/TimeStamp.h"
      22             : #include "nsThreadUtils.h"
      23             : 
      24             : #define FLING_LOG(...)
      25             : // #define FLING_LOG(...) printf_stderr("FLING: " __VA_ARGS__)
      26             : 
      27             : namespace mozilla {
      28             : namespace layers {
      29             : 
      30           0 : class GenericFlingAnimation: public AsyncPanZoomAnimation {
      31             : public:
      32           0 :   GenericFlingAnimation(AsyncPanZoomController& aApzc,
      33             :                         PlatformSpecificStateBase* aPlatformSpecificState,
      34             :                         const RefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
      35             :                         bool aFlingIsHandedOff,
      36             :                         const RefPtr<const AsyncPanZoomController>& aScrolledApzc)
      37           0 :     : mApzc(aApzc)
      38             :     , mOverscrollHandoffChain(aOverscrollHandoffChain)
      39           0 :     , mScrolledApzc(aScrolledApzc)
      40             :   {
      41           0 :     MOZ_ASSERT(mOverscrollHandoffChain);
      42           0 :     TimeStamp now = aApzc.GetFrameTime();
      43             : 
      44             :     // Drop any velocity on axes where we don't have room to scroll anyways
      45             :     // (in this APZC, or an APZC further in the handoff chain).
      46             :     // This ensures that we don't take the 'overscroll' path in Sample()
      47             :     // on account of one axis which can't scroll having a velocity.
      48           0 :     if (!mOverscrollHandoffChain->CanScrollInDirection(&mApzc, ScrollDirection::HORIZONTAL)) {
      49           0 :       ReentrantMonitorAutoEnter lock(mApzc.mMonitor);
      50           0 :       mApzc.mX.SetVelocity(0);
      51             :     }
      52           0 :     if (!mOverscrollHandoffChain->CanScrollInDirection(&mApzc, ScrollDirection::VERTICAL)) {
      53           0 :       ReentrantMonitorAutoEnter lock(mApzc.mMonitor);
      54           0 :       mApzc.mY.SetVelocity(0);
      55             :     }
      56             : 
      57           0 :     ParentLayerPoint velocity = mApzc.GetVelocityVector();
      58             : 
      59             :     // If the last fling was very recent and in the same direction as this one,
      60             :     // boost the velocity to be the sum of the two. Check separate axes separately
      61             :     // because we could have two vertical flings with small horizontal components
      62             :     // on the opposite side of zero, and we still want the y-fling to get accelerated.
      63             :     // Note that the acceleration code is only applied on the APZC that initiates
      64             :     // the fling; the accelerated velocities are then handed off using the
      65             :     // normal DispatchFling codepath.
      66             :     // Acceleration is only applied in the APZC that originated the fling,
      67             :     // not in APZCs further down the handoff chain during handoff.
      68           0 :     bool applyAcceleration = !aFlingIsHandedOff;
      69           0 :     if (applyAcceleration && !mApzc.mLastFlingTime.IsNull()
      70           0 :         && (now - mApzc.mLastFlingTime).ToMilliseconds() < gfxPrefs::APZFlingAccelInterval()
      71           0 :         && velocity.Length() >= gfxPrefs::APZFlingAccelMinVelocity()) {
      72           0 :       if (SameDirection(velocity.x, mApzc.mLastFlingVelocity.x)) {
      73           0 :         velocity.x = Accelerate(velocity.x, mApzc.mLastFlingVelocity.x);
      74             :         FLING_LOG("%p Applying fling x-acceleration from %f to %f (delta %f)\n",
      75             :                   &mApzc, mApzc.mX.GetVelocity(), velocity.x, mApzc.mLastFlingVelocity.x);
      76           0 :         mApzc.mX.SetVelocity(velocity.x);
      77             :       }
      78           0 :       if (SameDirection(velocity.y, mApzc.mLastFlingVelocity.y)) {
      79           0 :         velocity.y = Accelerate(velocity.y, mApzc.mLastFlingVelocity.y);
      80             :         FLING_LOG("%p Applying fling y-acceleration from %f to %f (delta %f)\n",
      81             :                   &mApzc, mApzc.mY.GetVelocity(), velocity.y, mApzc.mLastFlingVelocity.y);
      82           0 :         mApzc.mY.SetVelocity(velocity.y);
      83             :       }
      84             :     }
      85             : 
      86           0 :     mApzc.mLastFlingTime = now;
      87           0 :     mApzc.mLastFlingVelocity = velocity;
      88           0 :   }
      89             : 
      90             :   /**
      91             :    * Advances a fling by an interpolated amount based on the passed in |aDelta|.
      92             :    * This should be called whenever sampling the content transform for this
      93             :    * frame. Returns true if the fling animation should be advanced by one frame,
      94             :    * or false if there is no fling or the fling has ended.
      95             :    */
      96           0 :   virtual bool DoSample(FrameMetrics& aFrameMetrics,
      97             :                         const TimeDuration& aDelta) override
      98             :   {
      99           0 :     float friction = gfxPrefs::APZFlingFriction();
     100           0 :     float threshold = gfxPrefs::APZFlingStoppedThreshold();
     101             : 
     102           0 :     bool shouldContinueFlingX = mApzc.mX.FlingApplyFrictionOrCancel(aDelta, friction, threshold),
     103           0 :          shouldContinueFlingY = mApzc.mY.FlingApplyFrictionOrCancel(aDelta, friction, threshold);
     104             :     // If we shouldn't continue the fling, let's just stop and repaint.
     105           0 :     if (!shouldContinueFlingX && !shouldContinueFlingY) {
     106             :       FLING_LOG("%p ending fling animation. overscrolled=%d\n", &mApzc, mApzc.IsOverscrolled());
     107             :       // This APZC or an APZC further down the handoff chain may be be overscrolled.
     108             :       // Start a snap-back animation on the overscrolled APZC.
     109             :       // Note:
     110             :       //   This needs to be a deferred task even though it can safely run
     111             :       //   while holding mMonitor, because otherwise, if the overscrolled APZC
     112             :       //   is this one, then the SetState(NOTHING) in UpdateAnimation will
     113             :       //   stomp on the SetState(SNAP_BACK) it does.
     114           0 :       mDeferredTasks.AppendElement(NewRunnableMethod<AsyncPanZoomController*>(
     115             :         "layers::OverscrollHandoffChain::SnapBackOverscrolledApzc",
     116           0 :         mOverscrollHandoffChain.get(),
     117             :         &OverscrollHandoffChain::SnapBackOverscrolledApzc,
     118           0 :         &mApzc));
     119           0 :       return false;
     120             :     }
     121             : 
     122             :     // AdjustDisplacement() zeroes out the Axis velocity if we're in overscroll.
     123             :     // Since we need to hand off the velocity to the tree manager in such a case,
     124             :     // we save it here. Would be ParentLayerVector instead of ParentLayerPoint
     125             :     // if we had vector classes.
     126           0 :     ParentLayerPoint velocity = mApzc.GetVelocityVector();
     127             : 
     128           0 :     ParentLayerPoint offset = velocity * aDelta.ToMilliseconds();
     129             : 
     130             :     // Ordinarily we might need to do a ScheduleComposite if either of
     131             :     // the following AdjustDisplacement calls returns true, but this
     132             :     // is already running as part of a FlingAnimation, so we'll be compositing
     133             :     // per frame of animation anyway.
     134           0 :     ParentLayerPoint overscroll;
     135           0 :     ParentLayerPoint adjustedOffset;
     136           0 :     mApzc.mX.AdjustDisplacement(offset.x, adjustedOffset.x, overscroll.x);
     137           0 :     mApzc.mY.AdjustDisplacement(offset.y, adjustedOffset.y, overscroll.y);
     138             : 
     139           0 :     aFrameMetrics.ScrollBy(adjustedOffset / aFrameMetrics.GetZoom());
     140             : 
     141             :     // The fling may have caused us to reach the end of our scroll range.
     142           0 :     if (!IsZero(overscroll)) {
     143             :       // Hand off the fling to the next APZC in the overscroll handoff chain.
     144             : 
     145             :       // We may have reached the end of the scroll range along one axis but
     146             :       // not the other. In such a case we only want to hand off the relevant
     147             :       // component of the fling.
     148           0 :       if (FuzzyEqualsAdditive(overscroll.x, 0.0f, COORDINATE_EPSILON)) {
     149           0 :         velocity.x = 0;
     150           0 :       } else if (FuzzyEqualsAdditive(overscroll.y, 0.0f, COORDINATE_EPSILON)) {
     151           0 :         velocity.y = 0;
     152             :       }
     153             : 
     154             :       // To hand off the fling, we attempt to find a target APZC and start a new
     155             :       // fling with the same velocity on that APZC. For simplicity, the actual
     156             :       // overscroll of the current sample is discarded rather than being handed
     157             :       // off. The compositor should sample animations sufficiently frequently
     158             :       // that this is not noticeable. The target APZC is chosen by seeing if
     159             :       // there is an APZC further in the handoff chain which is pannable; if
     160             :       // there isn't, we take the new fling ourselves, entering an overscrolled
     161             :       // state.
     162             :       // Note: APZC is holding mMonitor, so directly calling
     163             :       // HandleFlingOverscroll() (which acquires the tree lock) would violate
     164             :       // the lock ordering. Instead we schedule HandleFlingOverscroll() to be
     165             :       // called after mMonitor is released.
     166             :       FLING_LOG("%p fling went into overscroll, handing off with velocity %s\n", &mApzc, Stringify(velocity).c_str());
     167           0 :       mDeferredTasks.AppendElement(
     168             :         NewRunnableMethod<ParentLayerPoint,
     169             :                           RefPtr<const OverscrollHandoffChain>,
     170           0 :                           RefPtr<const AsyncPanZoomController>>(
     171             :           "layers::AsyncPanZoomController::HandleFlingOverscroll",
     172           0 :           &mApzc,
     173             :           &AsyncPanZoomController::HandleFlingOverscroll,
     174             :           velocity,
     175             :           mOverscrollHandoffChain,
     176           0 :           mScrolledApzc));
     177             : 
     178             :       // If there is a remaining velocity on this APZC, continue this fling
     179             :       // as well. (This fling and the handed-off fling will run concurrently.)
     180             :       // Note that AdjustDisplacement() will have zeroed out the velocity
     181             :       // along the axes where we're overscrolled.
     182           0 :       return !IsZero(mApzc.GetVelocityVector());
     183             :     }
     184             : 
     185           0 :     return true;
     186             :   }
     187             : 
     188             : private:
     189           0 :   static bool SameDirection(float aVelocity1, float aVelocity2)
     190             :   {
     191             :     return (aVelocity1 == 0.0f)
     192           0 :         || (aVelocity2 == 0.0f)
     193           0 :         || (IsNegative(aVelocity1) == IsNegative(aVelocity2));
     194             :   }
     195             : 
     196           0 :   static float Accelerate(float aBase, float aSupplemental)
     197             :   {
     198           0 :     return (aBase * gfxPrefs::APZFlingAccelBaseMultiplier())
     199           0 :          + (aSupplemental * gfxPrefs::APZFlingAccelSupplementalMultiplier());
     200             :   }
     201             : 
     202             :   AsyncPanZoomController& mApzc;
     203             :   RefPtr<const OverscrollHandoffChain> mOverscrollHandoffChain;
     204             :   RefPtr<const AsyncPanZoomController> mScrolledApzc;
     205             : };
     206             : 
     207             : } // namespace layers
     208             : } // namespace mozilla
     209             : 
     210             : #endif // mozilla_layers_GenericFlingAnimation_h_

Generated by: LCOV version 1.13