Bug 1232577 part 9 - Remove AnimationCollection::mStyleRuleRefreshTime; r=heycam
authorBrian Birtles <birtles@gmail.com>
Wed, 13 Jan 2016 07:54:54 +0900
changeset 314804 35725757afce1a57cac0d7ab89f049ba3eb0b602
parent 314803 e3aa66edbd85d7ab9fe63c61f1e65ce314ce9f46
child 314805 f6fcc3f908c05e1dc5029e82c7ab5463c943633d
push id5703
push userraliiev@mozilla.com
push dateMon, 07 Mar 2016 14:18:41 +0000
treeherdermozilla-beta@31e373ad5b5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1232577
milestone46.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 1232577 part 9 - Remove AnimationCollection::mStyleRuleRefreshTime; r=heycam Now that we track whether or not animations are up to date using the hashset in EffectCompositor, we can remove the mStyleRuleRefreshTime flag that is, as of part 5 of this patch series, now only used for detecting whether or not animations are up to date. In order to preserve the existing behavior of FlushAnimations, however, this patch temporarily introduces a method to indicate if there are throttled animations or not. It might not be obvious that FlushAnimations is only concerned with throttled animations due to its name. FlushAnimations is simply intended to post animation restyles for out-of-date animations. Any animations that are *not* throttled will either be up to date, or we will have already posted an animation restyle so we only need to consider throttled animations in this case.
dom/animation/EffectCompositor.cpp
dom/animation/EffectCompositor.h
layout/style/AnimationCommon.cpp
layout/style/AnimationCommon.h
layout/style/nsAnimationManager.cpp
layout/style/nsTransitionManager.cpp
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -222,16 +222,29 @@ EffectCompositor::GetElementToRestyle(do
     return nullptr;
   }
   if (!pseudoFrame) {
     return nullptr;
   }
   return pseudoFrame->GetContent()->AsElement();
 }
 
+bool
+EffectCompositor::HasThrottledAnimations(Element* aElement,
+                                         nsCSSPseudoElements::Type aPseudoType,
+                                         CascadeLevel aCascadeLevel) const
+{
+  auto& elementsToRestyle = mElementsToRestyle[aCascadeLevel];
+  PseudoElementHashKey key = { aElement, aPseudoType };
+
+  bool hasPendingRestyle = false;
+  return elementsToRestyle.Get(key, &hasPendingRestyle) &&
+         !hasPendingRestyle;
+}
+
 /* static */ bool
 EffectCompositor::HasAnimationsForCompositor(const nsIFrame* aFrame,
                                              nsCSSProperty aProperty)
 {
   return FindAnimationsForCompositor(aFrame, aProperty, nullptr);
 }
 
 /* static */ nsTArray<RefPtr<dom::Animation>>
--- a/dom/animation/EffectCompositor.h
+++ b/dom/animation/EffectCompositor.h
@@ -100,16 +100,21 @@ public:
   // specified (pseudo-)element for cascade level |aLevel|.
   // If the animation rule is not marked as needing an update,
   // no work is done.
   void MaybeUpdateAnimationRule(dom::Element* aElement,
                                 nsCSSPseudoElements::Type aPseudoType,
                                 CascadeLevel aCascadeLevel,
                                 bool& aStyleChanging);
 
+  // FIXME: Temporary method until we move FlushAnimations here.
+  bool HasThrottledAnimations(dom::Element* aElement,
+                              nsCSSPseudoElements::Type aPseudoType,
+                              CascadeLevel aCascadeLevel) const;
+
   static bool HasAnimationsForCompositor(const nsIFrame* aFrame,
                                          nsCSSProperty aProperty);
 
   static nsTArray<RefPtr<dom::Animation>>
   GetAnimationsForCompositor(const nsIFrame* aFrame,
                              nsCSSProperty aProperty);
 
 
--- a/layout/style/AnimationCommon.cpp
+++ b/layout/style/AnimationCommon.cpp
@@ -230,21 +230,19 @@ CommonAnimationManager::SizeOfExcludingT
 CommonAnimationManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
 }
 
 void
 CommonAnimationManager::AddStyleUpdatesTo(RestyleTracker& aTracker)
 {
-  TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh();
-
   for (AnimationCollection* collection = mElementCollections.getFirst();
        collection; collection = collection->getNext()) {
-    collection->EnsureStyleRuleFor(now);
+    collection->EnsureStyleRuleFor();
 
     dom::Element* elementToRestyle = collection->GetElementToRestyle();
     if (elementToRestyle) {
       nsRestyleHint rshint = collection->IsForTransitions()
         ? eRestyle_CSSTransitions : eRestyle_CSSAnimations;
       aTracker.AddPendingRestyle(elementToRestyle, rshint, nsChangeHint(0));
     }
   }
@@ -267,20 +265,29 @@ CommonAnimationManager::ExtractComputedV
                                StyleAnimationValue::eUnit_Visibility);
   }
   return result;
 }
 
 void
 CommonAnimationManager::FlushAnimations()
 {
-  TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh();
   for (AnimationCollection* collection = mElementCollections.getFirst();
        collection; collection = collection->getNext()) {
-    if (collection->mStyleRuleRefreshTime == now) {
+
+    EffectCompositor::CascadeLevel cascadeLevel =
+      collection->IsForAnimations() ?
+      EffectCompositor::CascadeLevel::Animations :
+      EffectCompositor::CascadeLevel::Transitions;
+    bool hasThrottledAnimations =
+      mPresContext->EffectCompositor()->HasThrottledAnimations(
+        collection->mElement,
+        collection->PseudoElementType(),
+        cascadeLevel);
+    if (!hasThrottledAnimations) {
       continue;
     }
 
     MOZ_ASSERT(collection->mElement->GetComposedDoc() ==
                  mPresContext->Document(),
                "Should not have a transition/animation collection for an "
                "element that is not part of the document tree");
 
@@ -309,18 +316,17 @@ CommonAnimationManager::GetAnimationRule
     return nullptr;
   }
 
   RestyleManager* restyleManager = mPresContext->RestyleManager();
   if (restyleManager->SkipAnimationRules()) {
     return nullptr;
   }
 
-  collection->EnsureStyleRuleFor(
-    mPresContext->RefreshDriver()->MostRecentRefresh());
+  collection->EnsureStyleRuleFor();
 
   EffectSet* effectSet = EffectSet::GetEffectSet(aElement, aPseudoType);
   if (!effectSet) {
     return nullptr;
   }
 
   return IsAnimationManager() ?
          effectSet->AnimationRule(EffectCompositor::CascadeLevel::Animations) :
@@ -407,35 +413,27 @@ AnimationCollection::Tick()
 {
   for (size_t animIdx = 0, animEnd = mAnimations.Length();
        animIdx != animEnd; animIdx++) {
     mAnimations[animIdx]->Tick();
   }
 }
 
 void
-AnimationCollection::EnsureStyleRuleFor(TimeStamp aRefreshTime)
+AnimationCollection::EnsureStyleRuleFor()
 {
   mHasPendingAnimationRestyle = false;
 
   nsPresContext* presContext = mManager->PresContext();
   if (!presContext) {
     // Pres context will be null after the manager is disconnected.
     return;
   }
 
   if (!mStyleChanging) {
-    mStyleRuleRefreshTime = aRefreshTime;
-    return;
-  }
-
-  if (!mStyleRuleRefreshTime.IsNull() &&
-      mStyleRuleRefreshTime == aRefreshTime) {
-    // The style rule on the EffectSet may be null and valid, if we have no
-    // style to apply.
     return;
   }
 
   // Update cascade results before updating the style rule, since the
   // cascade results can influence the style rule.
   nsStyleContext* styleContext = nullptr;
   {
     dom::Element* elementToRestyle = GetElementToRestyle();
@@ -445,18 +443,16 @@ AnimationCollection::EnsureStyleRuleFor(
         styleContext = frame->StyleContext();
       }
     }
   }
   EffectCompositor::MaybeUpdateCascadeResults(mElement,
                                               PseudoElementType(),
                                               styleContext);
 
-  mStyleRuleRefreshTime = aRefreshTime;
-
   EffectCompositor::CascadeLevel cascadeLevel =
     IsForAnimations() ?
     EffectCompositor::CascadeLevel::Animations :
     EffectCompositor::CascadeLevel::Transitions;
   presContext->EffectCompositor()->MaybeUpdateAnimationRule(mElement,
                                                             PseudoElementType(),
                                                             cascadeLevel,
                                                             mStyleChanging);
@@ -481,17 +477,16 @@ AnimationCollection::RequestRestyle(Effe
   presContext->EffectCompositor()->RequestRestyle(mElement,
                                                   PseudoElementType(),
                                                   aRestyleType,
                                                   cascadeLevel);
 
   // Steps for RestyleType::Layer:
 
   if (aRestyleType == EffectCompositor::RestyleType::Layer) {
-    mStyleRuleRefreshTime = TimeStamp();
     mStyleChanging = true;
 
     // Prompt layers to re-sync their animations.
     presContext->ClearLastStyleUpdateForAllAnimations();
     presContext->RestyleManager()->IncrementAnimationGeneration();
     EffectSet* effectSet =
       EffectSet::GetEffectSet(mElement, PseudoElementType());
     if (effectSet) {
--- a/layout/style/AnimationCommon.h
+++ b/layout/style/AnimationCommon.h
@@ -81,17 +81,17 @@ public:
         return true;
       }
     } while ((aContent = aContent->GetParent()));
 
     return false;
   }
 
   // Requests a standard restyle on each managed AnimationCollection that has
-  // an out-of-date mStyleRuleRefreshTime.
+  // an out-of-date animation rule.
   void FlushAnimations();
 
   nsIStyleRule* GetAnimationRule(dom::Element* aElement,
                                  nsCSSPseudoElements::Type aPseudoType);
 
   static bool ExtractComputedValueForTransition(
                   nsCSSProperty aProperty,
                   nsStyleContext* aStyleContext,
@@ -166,17 +166,17 @@ struct AnimationCollection : public Link
     mElement->DeleteProperty(mElementProperty);
   }
 
   static void PropertyDtor(void *aObject, nsIAtom *aPropertyName,
                            void *aPropertyValue, void *aData);
 
   void Tick();
 
-  void EnsureStyleRuleFor(TimeStamp aRefreshTime);
+  void EnsureStyleRuleFor();
 
   void RequestRestyle(EffectCompositor::RestyleType aRestyleType);
 
 public:
   // True if this animation can be performed on the compositor thread.
   //
   // Returns whether the state of this element's animations at the current
   // refresh driver time contains animation data that can be done on the
@@ -248,19 +248,16 @@ public:
   // for which we've done the transition update, so that we avoid doing
   // it more than once per style change.
   // (Note that we also store an animation generation on each EffectSet in
   // order to track when we need to update animations on layers.)
   uint64_t mCheckGeneration;
   // Update mCheckGeneration to RestyleManager's count
   void UpdateCheckGeneration(nsPresContext* aPresContext);
 
-  // The refresh time associated with the animation rule on the EffectSet.
-  TimeStamp mStyleRuleRefreshTime;
-
   // False when we know that our current animation rule is valid
   // indefinitely into the future (because all of our animations are
   // either completed or paused).  May be invalidated by a style change.
   bool mStyleChanging;
 
 private:
   // Whether or not we have already posted for animation restyle.
   // This is used to avoid making redundant requests and is reset each time
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -410,17 +410,16 @@ nsAnimationManager::CheckAnimationRule(n
   if (newAnimations.IsEmpty()) {
     if (collection) {
       collection->Destroy();
     }
     return nullptr;
   }
 
   if (collection) {
-    collection->mStyleRuleRefreshTime = TimeStamp();
     EffectSet* effectSet =
       EffectSet::GetEffectSet(aElement, aStyleContext->GetPseudoType());
     if (effectSet) {
       effectSet->UpdateAnimationGeneration(mPresContext);
     }
 
     // Copy over the start times and (if still paused) pause starts
     // for each animation (matching on name only) that was also in the
@@ -545,18 +544,17 @@ nsAnimationManager::CheckAnimationRule(n
   for (size_t newAnimIdx = newAnimations.Length(); newAnimIdx-- != 0; ) {
     newAnimations[newAnimIdx]->CancelFromStyle();
   }
 
   EffectCompositor::UpdateCascadeResults(aElement,
                                          aStyleContext->GetPseudoType(),
                                          aStyleContext);
 
-  TimeStamp refreshTime = mPresContext->RefreshDriver()->MostRecentRefresh();
-  collection->EnsureStyleRuleFor(refreshTime);
+  collection->EnsureStyleRuleFor();
   // We don't actually dispatch the pending events now.  We'll either
   // dispatch them the next time we get a refresh driver notification
   // or the next time somebody calls
   // nsPresShell::FlushPendingNotifications.
   if (mEventDispatcher.HasQueuedEvents()) {
     mPresContext->Document()->SetNeedStyleFlush();
   }
 
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -483,23 +483,19 @@ nsTransitionManager::StyleContextChanged
 
   MOZ_ASSERT(!startedAny || collection,
              "must have element transitions if we started any transitions");
 
   if (collection) {
     EffectCompositor::UpdateCascadeResults(aElement, pseudoType,
                                            newStyleContext);
 
-    // Set the style rule refresh time to null so that EnsureStyleRuleFor
-    // creates a new style rule if we started *or* stopped transitions.
-    collection->mStyleRuleRefreshTime = TimeStamp();
     collection->UpdateCheckGeneration(mPresContext);
     collection->mStyleChanging = true;
-    TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh();
-    collection->EnsureStyleRuleFor(now);
+    collection->EnsureStyleRuleFor();
   }
 
   // We want to replace the new style context with the after-change style.
   *aNewStyleContext = afterChangeStyle;
   if (collection) {
     // Since we have transition styles, we have to undo this replacement.
     // The check of collection->mCheckGeneration against the restyle
     // manager's GetAnimationGeneration() will ensure that we don't go