Bug 1109390 part 10 - Add an enum to AnimationPlayer to represent if we are pause-pending or play-pending; r=jwatt
authorBrian Birtles <birtles@gmail.com>
Fri, 27 Mar 2015 15:56:45 +0900
changeset 264934 e443000da039963b2e566b63db74a99f34ebe691
parent 264933 de1b1fbecf37fac6e4682bd00c2a424f8538d832
child 264935 7d0f03b20dbe4a34b5e0b50bc6114478459c3473
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt
bugs1109390
milestone39.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 1109390 part 10 - Add an enum to AnimationPlayer to represent if we are pause-pending or play-pending; r=jwatt
dom/animation/AnimationPlayer.cpp
dom/animation/AnimationPlayer.h
--- a/dom/animation/AnimationPlayer.cpp
+++ b/dom/animation/AnimationPlayer.cpp
@@ -155,17 +155,17 @@ AnimationPlayer::SilentlySetPlaybackRate
     SilentlySetCurrentTime(previousTime.Value());
     MOZ_ASSERT(!rv.Failed(), "Should not assert for non-null time");
   }
 }
 
 AnimationPlayState
 AnimationPlayer::PlayState() const
 {
-  if (mIsPending) {
+  if (mPendingState != PendingState::NotPending) {
     return AnimationPlayState::Pending;
   }
 
   Nullable<TimeDuration> currentTime = GetCurrentTime();
   if (currentTime.IsNull()) {
     return AnimationPlayState::Idle;
   }
 
@@ -262,17 +262,17 @@ AnimationPlayer::SetSource(Animation* aS
 
 void
 AnimationPlayer::Tick()
 {
   // Since we are not guaranteed to get only one call per refresh driver tick,
   // it's possible that mPendingReadyTime is set to a time in the future.
   // In that case, we should wait until the next refresh driver tick before
   // resuming.
-  if (mIsPending &&
+  if (mPendingState != PendingState::NotPending &&
       !mPendingReadyTime.IsNull() &&
       mPendingReadyTime.Value() <= mTimeline->GetCurrentTime().Value()) {
     ResumeAt(mPendingReadyTime.Value());
     mPendingReadyTime.SetNull();
   }
 
   if (IsPossiblyOrphanedPendingPlayer()) {
     MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(),
@@ -328,17 +328,17 @@ AnimationPlayer::GetCurrentOrPendingStar
   // need to incorporate the playbackRate when implemented (bug 1127380).
   result.SetValue(mPendingReadyTime.Value() - mHoldTime.Value());
   return result;
 }
 
 void
 AnimationPlayer::Cancel()
 {
-  if (mIsPending) {
+  if (mPendingState != PendingState::NotPending) {
     CancelPendingPlay();
     if (mReady) {
       mReady->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
     }
   }
 
   mHoldTime.SetNull();
   mStartTime.SetNull();
@@ -439,17 +439,17 @@ AnimationPlayer::DoPlay()
   }
 
   // Clear ready promise. We'll create a new one lazily.
   mReady = nullptr;
 
   // Clear the start time until we resolve a new one
   mStartTime.SetNull();
 
-  mIsPending = true;
+  mPendingState = PendingState::PlayPending;
 
   nsIDocument* doc = GetRenderedDocument();
   if (!doc) {
     TriggerOnNextTick(Nullable<TimeDuration>());
     return;
   }
 
   PendingPlayerTracker* tracker = doc->GetOrCreatePendingPlayerTracker();
@@ -458,17 +458,17 @@ AnimationPlayer::DoPlay()
   // We may have updated the current time when we set the hold time above
   // so notify source content.
   UpdateSourceContent();
 }
 
 void
 AnimationPlayer::DoPause()
 {
-  if (mIsPending) {
+  if (mPendingState == PendingState::PlayPending) {
     CancelPendingPlay();
     // Resolve the ready promise since we currently only use it for
     // players that are waiting to play. Later (in bug 1109390), we will
     // use this for players waiting to pause as well and then we won't
     // want to resolve it just yet.
     if (mReady) {
       mReady->MaybeResolve(this);
     }
@@ -485,28 +485,29 @@ AnimationPlayer::DoPause()
 }
 
 void
 AnimationPlayer::ResumeAt(const TimeDuration& aResumeTime)
 {
   // This method is only expected to be called for a player that is
   // waiting to play. We can easily adapt it to handle other states
   // but it's currently not necessary.
-  MOZ_ASSERT(PlayState() == AnimationPlayState::Pending,
-             "Expected to resume a pending player");
+  MOZ_ASSERT(mPendingState == PendingState::PlayPending,
+             "Expected to resume a play-pending player");
   MOZ_ASSERT(!mHoldTime.IsNull(),
-             "A player in the pending state should have a resolved hold time");
+             "A player in the play-pending state should have a resolved"
+             " hold time");
 
   if (mPlaybackRate != 0) {
     mStartTime.SetValue(aResumeTime - (mHoldTime.Value() / mPlaybackRate));
     mHoldTime.SetNull();
   } else {
     mStartTime.SetValue(aResumeTime);
   }
-  mIsPending = false;
+  mPendingState = PendingState::NotPending;
 
   UpdateSourceContent();
 
   if (mReady) {
     mReady->MaybeResolve(this);
   }
 }
 
@@ -535,29 +536,29 @@ AnimationPlayer::PostUpdate()
   if (collection) {
     collection->NotifyPlayerUpdated();
   }
 }
 
 void
 AnimationPlayer::CancelPendingPlay()
 {
-  if (!mIsPending) {
+  if (mPendingState == PendingState::NotPending) {
     return;
   }
 
   nsIDocument* doc = GetRenderedDocument();
   if (doc) {
     PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
     if (tracker) {
       tracker->RemovePlayPending(*this);
     }
   }
 
-  mIsPending = false;
+  mPendingState = PendingState::NotPending;
   mPendingReadyTime.SetNull();
 }
 
 bool
 AnimationPlayer::IsPossiblyOrphanedPendingPlayer() const
 {
   // Check if we are pending but might never start because we are not being
   // tracked.
@@ -568,21 +569,21 @@ AnimationPlayer::IsPossiblyOrphanedPendi
   //   or bound to a different document.
   //   (note that for the case of our source content changing we should handle
   //   that in SetSource)
   // * We started playing but our timeline became inactive.
   //   In this case the pending player tracker will drop us from its hashmap
   //   when we have been painted.
   // * When we started playing we couldn't find a PendingPlayerTracker to
   //   register with (perhaps the source content had no document) so we simply
-  //   set mIsPending in DoPlay and relied on this method to catch us on the
+  //   set mPendingState in DoPlay and relied on this method to catch us on the
   //   next tick.
 
   // If we're not pending we're ok.
-  if (!mIsPending) {
+  if (mPendingState == PendingState::NotPending) {
     return false;
   }
 
   // If we have a pending ready time then we will be started on the next
   // tick.
   if (!mPendingReadyTime.IsNull()) {
     return false;
   }
--- a/dom/animation/AnimationPlayer.h
+++ b/dom/animation/AnimationPlayer.h
@@ -49,17 +49,17 @@ class AnimationPlayer : public nsISuppor
 {
 protected:
   virtual ~AnimationPlayer() {}
 
 public:
   explicit AnimationPlayer(AnimationTimeline* aTimeline)
     : mTimeline(aTimeline)
     , mPlaybackRate(1.0)
-    , mIsPending(false)
+    , mPendingState(PendingState::NotPending)
     , mIsRunningOnCompositor(false)
     , mIsPreviousStateFinished(false)
     , mIsRelevant(false)
   {
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AnimationPlayer)
@@ -230,19 +230,19 @@ public:
 protected:
   void DoPlay();
   void DoPause();
   void ResumeAt(const TimeDuration& aResumeTime);
 
   void UpdateSourceContent();
   void FlushStyle() const;
   void PostUpdate();
-  // Remove this player from the pending player tracker and resets mIsPending
-  // as necessary. The caller is responsible for resolving or aborting the
-  // mReady promise as necessary.
+  // Remove this player from the pending player tracker and reset
+  // mPendingState as necessary. The caller is responsible for resolving or
+  // aborting the mReady promise as necessary.
   void CancelPendingPlay();
 
   bool IsPossiblyOrphanedPendingPlayer() const;
   StickyTimeDuration SourceContentEnd() const;
 
   nsIDocument* GetRenderedDocument() const;
   nsPresContext* GetPresContext() const;
   virtual css::CommonAnimationManager* GetAnimationManager() const = 0;
@@ -256,22 +256,25 @@ protected:
   Nullable<TimeDuration> mPendingReadyTime; // Timeline timescale
   double mPlaybackRate;
 
   // A Promise that is replaced on each call to Play() (and in future Pause())
   // and fulfilled when Play() is successfully completed.
   // This object is lazily created by GetReady.
   nsRefPtr<Promise> mReady;
 
-  // Indicates if the player is in the pending state. We use this rather
-  // than checking if this player is tracked by a PendingPlayerTracker.
-  // This is because the PendingPlayerTracker is associated with the source
-  // content's document but we need to know if we're pending even if the
-  // source content loses association with its document.
-  bool mIsPending;
+  // Indicates if the player is in the pending state (and what state it is
+  // waiting to enter when it finished pending). We use this rather than
+  // checking if this player is tracked by a PendingPlayerTracker because the
+  // player will continue to be pending even after it has been removed from the
+  // PendingPlayerTracker while it is waiting for the next tick
+  // (see TriggerOnNextTick for details).
+  enum class PendingState { NotPending, PlayPending, PausePending };
+  PendingState mPendingState;
+
   bool mIsRunningOnCompositor;
   // Indicates whether we were in the finished state during our
   // most recent unthrottled sample (our last ComposeStyle call).
   // FIXME: When we implement the finished promise (bug 1074630) we can
   // probably remove this and check if the promise has been settled yet
   // or not instead.
   bool mIsPreviousStateFinished; // Spec calls this "previous finished state"
   // Indicates that the player should be exposed in an element's