Bug 1334735 - Part 2: Add separate flag to track need to flush throttled animations. r?bz,birtles draft
authorCameron McCormack <cam@mcc.id.au>
Tue, 07 Feb 2017 18:19:35 +0800
changeset 479821 5b542ee78cd33e581f5ca61bec0725886d1d0a40
parent 479820 cfc9317005af772987ffdc0e124331a9edbe17c7
child 479822 a4a0e566d5196c42260ae943ff0cfeb799e53236
push id44370
push userbmo:cam@mcc.id.au
push dateTue, 07 Feb 2017 10:20:07 +0000
reviewersbz, birtles
bugs1334735
milestone54.0a1
Bug 1334735 - Part 2: Add separate flag to track need to flush throttled animations. r?bz,birtles MozReview-Commit-ID: Fil3uTYYz3P
dom/animation/EffectCompositor.cpp
layout/base/PresShell.cpp
layout/base/nsIPresShell.h
layout/base/nsIPresShellInlines.h
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -259,17 +259,17 @@ EffectCompositor::RequestRestyle(dom::El
 
   auto& elementsToRestyle = mElementsToRestyle[aCascadeLevel];
   PseudoElementHashEntry::KeyType key = { aElement, aPseudoType };
 
   if (aRestyleType == RestyleType::Throttled) {
     if (!elementsToRestyle.Contains(key)) {
       elementsToRestyle.Put(key, false);
     }
-    mPresContext->PresShell()->SetNeedStyleFlush();
+    mPresContext->PresShell()->SetNeedThrottledAnimationFlush();
   } else {
     // Get() returns 0 if the element is not found. It will also return
     // false if the element is found but does not have a pending restyle.
     bool hasPendingRestyle = elementsToRestyle.Get(key);
     if (!hasPendingRestyle) {
       PostRestyleForAnimation(aElement, aPseudoType, aCascadeLevel);
     }
     elementsToRestyle.Put(key, true);
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -793,16 +793,17 @@ nsIPresShell::nsIPresShell()
     , mFrozen(false)
     , mIsFirstPaint(false)
     , mObservesMutationsForPrint(false)
     , mReflowScheduled(false)
     , mSuppressInterruptibleReflows(false)
     , mScrollPositionClampingScrollPortSizeSet(false)
     , mNeedLayoutFlush(true)
     , mNeedStyleFlush(true)
+    , mNeedThrottledAnimationFlush(true)
     , mPresShellId(0)
     , mFontSizeInflationEmPerLine(0)
     , mFontSizeInflationMinTwips(0)
     , mFontSizeInflationLineThreshold(0)
     , mFontSizeInflationForceEnabled(false)
     , mFontSizeInflationDisabledInMasterProcess(false)
     , mFontSizeInflationEnabled(false)
     , mPaintingIsFrozen(false)
@@ -4108,16 +4109,18 @@ PresShell::FlushPendingNotifications(moz
   // nsDocument::FlushPendingNotifications doesn't skip any re-entrant
   // calls to us.  Otherwise, we might miss some needed flushes, since
   // we clear mNeedStyleFlush / mNeedLayoutFlush here at the top of
   // the function but we might not have done the work yet.
   AutoRestore<bool> guard(mInFlush);
   mInFlush = true;
 
   mNeedStyleFlush = false;
+  mNeedThrottledAnimationFlush =
+    mNeedThrottledAnimationFlush && !aFlush.mFlushAnimations;
   mNeedLayoutFlush =
     mNeedLayoutFlush && (flushType < FlushType::InterruptibleLayout);
 
   bool isSafeToFlush = IsSafeToFlush();
 
   // If layout could possibly trigger scripts, then it's only safe to flush if
   // it's safe to run script.
   bool hasHadScriptObject;
@@ -4235,16 +4238,19 @@ PresShell::FlushPendingNotifications(moz
       if (!mIsDestroying) {
         viewManager->UpdateWidgetGeometry();
       }
     }
   }
 
   if (!didStyleFlush && flushType >= FlushType::Style && !mIsDestroying) {
     SetNeedStyleFlush();
+    if (aFlush.mFlushAnimations) {
+      SetNeedThrottledAnimationFlush();
+    }
   }
 
   if (!didLayoutFlush && !mIsDestroying &&
       (flushType >=
        (mSuppressInterruptibleReflows ? FlushType::Layout
                                       : FlushType::InterruptibleLayout))) {
     // We suppressed this flush due to mSuppressInterruptibleReflows or
     // !isSafeToFlush, but now we think we don't need to flush any more.
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -585,37 +585,40 @@ public:
   virtual void FlushPendingNotifications(mozilla::FlushType aType) = 0;
   virtual void FlushPendingNotifications(mozilla::ChangesToFlush aType) = 0;
 
   /**
    * Whether we might need a flush for the given flush type.  If this
    * function returns false, we definitely don't need to flush.
    *
    * @param aFlushType The flush type to check.  This must be
-   *   >= FlushType::Style.
+   *   >= FlushType::Style.  We assume that throttled animations are to be
+   *   flushed.
    */
   bool NeedFlush(mozilla::FlushType aType) const
   {
     // We check mInFlush to handle re-entrant calls to FlushPendingNotifications
     // by reporting that we always need a flush in that case.  Otherwise,
-    // we could end up missing needed flushes, since we clear mNeedStyleFlush
-    // and mNeedLayoutFlush at the top of FlushPendingNotifications.
+    // we could end up missing needed flushes, since we clear the mNeedXXXFlush
+    // flags at the top of FlushPendingNotifications.
     //
     // XXXheycam Could we just clear those flags after the work has been
     // done instead?
     MOZ_ASSERT(aType >= mozilla::FlushType::Style);
     return mNeedStyleFlush ||
            (mNeedLayoutFlush &&
             aType >= mozilla::FlushType::InterruptibleLayout) ||
            aType >= mozilla::FlushType::Display ||
+           mNeedThrottledAnimationFlush ||
            mInFlush;
   }
 
   inline void SetNeedStyleFlush();
   inline void SetNeedLayoutFlush();
+  inline void SetNeedThrottledAnimationFlush();
 
   /**
    * Callbacks will be called even if reflow itself fails for
    * some reason.
    */
   virtual nsresult PostReflowCallback(nsIReflowCallback* aCallback) = 0;
   virtual void CancelReflowCallback(nsIReflowCallback* aCallback) = 0;
 
@@ -1833,16 +1836,20 @@ protected:
   bool                      mScrollPositionClampingScrollPortSizeSet : 1;
 
   // True if a layout flush might not be a no-op
   bool mNeedLayoutFlush : 1;
 
   // True if a style flush might not be a no-op
   bool mNeedStyleFlush : 1;
 
+  // True if there are throttled animations that would be processed when
+  // performing a flush with mFlushAnimations == true.
+  bool mNeedThrottledAnimationFlush : 1;
+
   uint32_t                  mPresShellId;
 
   // List of subtrees rooted at style scope roots that need to be restyled.
   // When a change to a scoped style sheet is made, we add the style scope
   // root to this array rather than setting mStylesHaveChanged = true, since
   // we know we don't need to restyle the whole document.  However, if in the
   // same update block we have already had other changes that require
   // the whole document to be restyled (i.e., mStylesHaveChanged is already
--- a/layout/base/nsIPresShellInlines.h
+++ b/layout/base/nsIPresShellInlines.h
@@ -20,9 +20,20 @@ nsIPresShell::SetNeedStyleFlush()
   mNeedStyleFlush = true;
   if (nsIDocument* doc = mDocument->GetDisplayDocument()) {
     if (nsIPresShell* shell = doc->GetShell()) {
       shell->mNeedStyleFlush = true;
     }
   }
 }
 
+void
+nsIPresShell::SetNeedThrottledAnimationFlush()
+{
+  mNeedThrottledAnimationFlush = true;
+  if (nsIDocument* doc = mDocument->GetDisplayDocument()) {
+    if (nsIPresShell* shell = doc->GetShell()) {
+      shell->mNeedThrottledAnimationFlush = true;
+    }
+  }
+}
+
 #endif // nsIPresShellInlines_h