Bug 927349 part 16 - Do a full reflow when we have pending animations; r=jwatt
authorBrian Birtles <birtles@gmail.com>
Mon, 22 Dec 2014 09:35:41 +0900
changeset 220811 6710df16f1e85a1ad1d3f7b1a858667920b54798
parent 220810 da5d7b9bff8f11a62427a9a4507a131ea4a9e058
child 220812 7d4ffa8d49ca3452d158e900f4efba1b6b1bf399
push id28000
push usercbook@mozilla.com
push dateMon, 22 Dec 2014 12:13:57 +0000
treeherdermozilla-central@c82d5fcdc416 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt
bugs927349
milestone37.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 927349 part 16 - Do a full reflow when we have pending animations; r=jwatt We want to time animations from when their first frame is painted. However, interruptible reflow complicates this since, for a given set of pending animations, some may be painted whilst others are not. To simplify this we simply force an uninterruptible reflow when we have animations that are waiting to start.
dom/animation/PendingPlayerTracker.h
layout/base/nsRefreshDriver.cpp
--- a/dom/animation/PendingPlayerTracker.h
+++ b/dom/animation/PendingPlayerTracker.h
@@ -27,16 +27,17 @@ public:
 
   void AddPlayPending(dom::AnimationPlayer& aPlayer);
   void RemovePlayPending(dom::AnimationPlayer& aPlayer);
   bool IsWaitingToPlay(dom::AnimationPlayer const& aPlayer) const;
 
   // Causes any pending players to resume at |aReadyTime| by first
   // fast-forwarding their timeline to the corresponding time.
   void StartPendingPlayers(const TimeStamp& aReadyTime);
+  bool HasPendingPlayers() const { return mPlayPendingSet.Count() > 0; }
 
 private:
   ~PendingPlayerTracker() { }
 
   void EnsurePaintIsScheduled();
 
   typedef nsTHashtable<nsRefPtrHashKey<dom::AnimationPlayer>>
     AnimationPlayerSet;
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -33,16 +33,17 @@
 #include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 #include "nsComponentManagerUtils.h"
 #include "prlog.h"
 #include "nsAutoPtr.h"
 #include "nsIDocument.h"
 #include "jsapi.h"
 #include "nsContentUtils.h"
+#include "mozilla/PendingPlayerTracker.h"
 #include "mozilla/Preferences.h"
 #include "nsViewManager.h"
 #include "GeckoProfiler.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsPerformance.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "RestyleManager.h"
 #include "Layers.h"
@@ -1064,16 +1065,28 @@ struct DocumentFrameCallbacks {
   nsIDocument::FrameRequestCallbackList mCallbacks;
 };
 
 static nsDocShell* GetDocShell(nsPresContext* aPresContext)
 {
   return static_cast<nsDocShell*>(aPresContext->GetDocShell());
 }
 
+static bool
+HasPendingAnimations(nsIPresShell* aShell)
+{
+  nsIDocument* doc = aShell->GetDocument();
+  if (!doc) {
+    return false;
+  }
+
+  PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
+  return tracker && tracker->HasPendingPlayers();
+}
+
 /**
  * Return a list of all the child docShells in a given root docShell that are
  * visible and are recording markers for the profilingTimeline
  */
 static void GetProfileTimelineSubDocShells(nsDocShell* aRootDocShell,
                                            nsTArray<nsDocShell*>& aShells)
 {
   if (!aRootDocShell || nsDocShell::gProfileTimelineRecordingsCount == 0) {
@@ -1299,18 +1312,20 @@ nsRefreshDriver::Tick(int64_t aNowEpoch,
             profiler_tracing("Paint", "Reflow", mReflowCause, TRACING_INTERVAL_START);
             mReflowCause = nullptr;
           }
 
           NS_ADDREF(shell);
           mLayoutFlushObservers.RemoveElement(shell);
           shell->mReflowScheduled = false;
           shell->mSuppressInterruptibleReflows = false;
-          shell->FlushPendingNotifications(ChangesToFlush(Flush_InterruptibleLayout,
-                                                          false));
+          mozFlushType flushType = HasPendingAnimations(shell)
+                                 ? Flush_Layout
+                                 : Flush_InterruptibleLayout;
+          shell->FlushPendingNotifications(ChangesToFlush(flushType, false));
           // Inform the FontFaceSet that we ticked, so that it can resolve its
           // ready promise if it needs to.
           nsPresContext* presContext = shell->GetPresContext();
           if (presContext) {
             presContext->NotifyFontFaceSetOnRefresh();
           }
           NS_RELEASE(shell);
         }