Bug 1344619 - Part 1: Introduce WillCompose() to update various state that we need to update as the result of ComposeStyle(). r?birtles draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Tue, 07 Mar 2017 18:24:08 +0900
changeset 494576 98264024b84f98dfc89d5b0d545b784d460d23c3
parent 494263 b7e42143bbbc9dc3e5c05bd1e93b6485ce1d0ad4
child 494577 5f25ee9396b28f93d66610544c60592e04387d5c
push id48066
push userhikezoe@mozilla.com
push dateTue, 07 Mar 2017 10:06:22 +0000
reviewersbirtles
bugs1344619
milestone55.0a1
Bug 1344619 - Part 1: Introduce WillCompose() to update various state that we need to update as the result of ComposeStyle(). r?birtles MozReview-Commit-ID: JznBR3OghKG
dom/animation/Animation.cpp
dom/animation/Animation.h
dom/animation/KeyframeEffectReadOnly.cpp
dom/animation/KeyframeEffectReadOnly.h
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -921,16 +921,22 @@ Animation::HasLowerCompositeOrderThan(co
              "Animation indices should be unique");
 
   // 3. Finally, generic animations sort by their position in the global
   // animation array.
   return mAnimationIndex < aOther.mAnimationIndex;
 }
 
 void
+Animation::WillComposeStyle()
+{
+  mFinishedAtLastComposeStyle = (PlayState() == AnimationPlayState::Finished);
+}
+
+void
 Animation::ComposeStyle(AnimationRule& aStyleRule,
                         const nsCSSPropertyIDSet& aPropertiesToSkip)
 {
   if (!mEffect) {
     return;
   }
 
   // In order to prevent flicker, there are a few cases where we want to use
@@ -989,17 +995,16 @@ Animation::ComposeStyle(AnimationRule& a
     KeyframeEffectReadOnly* keyframeEffect = mEffect->AsKeyframeEffect();
     if (keyframeEffect) {
       keyframeEffect->ComposeStyle(aStyleRule, aPropertiesToSkip);
     }
   }
 
   MOZ_ASSERT(playState == PlayState(),
              "Play state should not change during the course of compositing");
-  mFinishedAtLastComposeStyle = (playState == AnimationPlayState::Finished);
 }
 
 void
 Animation::NotifyEffectTimingUpdated()
 {
   MOZ_ASSERT(mEffect,
              "We should only update timing effect when we have a target "
              "effect");
--- a/dom/animation/Animation.h
+++ b/dom/animation/Animation.h
@@ -307,16 +307,25 @@ public:
   }
 
   /**
    * Returns true if this animation does not currently need to update
    * style on the main thread (e.g. because it is empty, or is
    * running on the compositor).
    */
   bool CanThrottle() const;
+
+  /**
+   * Updates various state that we need to update as the results of
+   * ComposeStyle().
+   * This will be called from KeyframeEffectReadOnly::WillComposeStyle().
+   * See the comment of KeyframeEffectReadOnly::WillComposeStyle for more detail.
+   */
+  void WillComposeStyle();
+
   /**
    * Updates |aStyleRule| with the animation values of this animation's effect,
    * if any.
    * Any properties contained in |aPropertiesToSkip| will not be added or
    * updated in |aStyleRule|.
    */
   void ComposeStyle(AnimationRule& aStyleRule,
                     const nsCSSPropertyIDSet& aPropertiesToSkip);
--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -509,41 +509,55 @@ KeyframeEffectReadOnly::EnsureBaseStyles
 
       Unused << ResolveBaseStyle(property.mProperty, aStyleContext);
       break;
     }
   }
 }
 
 void
+KeyframeEffectReadOnly::WillComposeStyle()
+{
+  ComputedTiming computedTiming = GetComputedTiming();
+  mProgressOnLastCompose = computedTiming.mProgress;
+  mCurrentIterationOnLastCompose = computedTiming.mCurrentIteration;
+
+  mAnimation->WillComposeStyle();
+}
+
+void
 KeyframeEffectReadOnly::ComposeStyle(
   AnimationRule& aStyleRule,
   const nsCSSPropertyIDSet& aPropertiesToSkip)
 {
   MOZ_DIAGNOSTIC_ASSERT(!mIsComposingStyle,
                         "Should not be called recursively");
   if (mIsComposingStyle) {
     return;
   }
 
+  bool isServoBackend = mDocument->IsStyledByServo();
+
+  if (!isServoBackend) {
+    // In servo backend, WillComposeStyle() is called as a pre-traversal step
+    // from EffectCompositor::PreTraverse().
+    WillComposeStyle();
+  }
+
   AutoRestore<bool> isComposingStyle(mIsComposingStyle);
   mIsComposingStyle = true;
 
   ComputedTiming computedTiming = GetComputedTiming();
-  mProgressOnLastCompose = computedTiming.mProgress;
-  mCurrentIterationOnLastCompose = computedTiming.mCurrentIteration;
 
   // If the progress is null, we don't have fill data for the current
   // time so we shouldn't animate.
   if (computedTiming.mProgress.IsNull()) {
     return;
   }
 
-  bool isServoBackend = mDocument->IsStyledByServo();
-
   for (size_t propIdx = 0, propEnd = mProperties.Length();
        propIdx != propEnd; ++propIdx)
   {
     const AnimationProperty& prop = mProperties[propIdx];
 
     MOZ_ASSERT(prop.mSegments[0].mFromKey == 0.0, "incorrect first from key");
     MOZ_ASSERT(prop.mSegments[prop.mSegments.Length() - 1].mToKey == 1.0,
                "incorrect last to key");
--- a/dom/animation/KeyframeEffectReadOnly.h
+++ b/dom/animation/KeyframeEffectReadOnly.h
@@ -230,16 +230,23 @@ public:
   }
 
   // Update |mProperties| by recalculating from |mKeyframes| using
   // |aStyleContext| to resolve specified values.
   void UpdateProperties(nsStyleContext* aStyleContext);
   // Servo version of the above function.
   void UpdateProperties(const ServoComputedStyleValues& aServoValues);
 
+  // Update various state that we need to update as the results of
+  // ComposeStyle().
+  // We need to update those state outside ComposeStyle() because we should
+  // avoid mutating any state in ComposeStyle() since it might be called during
+  // parallel traversal.
+  void WillComposeStyle();
+
   // Updates |aStyleRule| with the animation values produced by this
   // AnimationEffect for the current time except any properties contained
   // in |aPropertiesToSkip|.
   void ComposeStyle(AnimationRule& aStyleRule,
                     const nsCSSPropertyIDSet& aPropertiesToSkip);
 
   // Composite |aValueToComposite| on |aUnderlyingValue| with
   // |aCompositeOperation|.