Bug 1317209 - Part 2: Call Servo's Interpolation from Gecko. r=heycam draft
authorBoris Chiou <boris.chiou@gmail.com>
Tue, 24 Jan 2017 15:21:52 +0800
changeset 466068 1e2415841e68b85fac380a87640f847572ed35d2
parent 466067 6a3d7fc2521f80dc0c35592226d4574dbfa28901
child 466069 15dc731f342f81d6764e4bfaa360ca694c377c75
push id42776
push userbmo:boris.chiou@gmail.com
push dateWed, 25 Jan 2017 06:34:29 +0000
reviewersheycam
bugs1317209
milestone53.0a1
Bug 1317209 - Part 2: Call Servo's Interpolation from Gecko. r=heycam 1. Call Servo's interpolation from KeyframeEffectReadOnly::ComposeStyle(). 2. Store the results into ServoAnimationRule. MozReview-Commit-ID: LOp2mbXforg
dom/animation/KeyframeEffectReadOnly.cpp
layout/style/ServoBindingList.h
--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -492,16 +492,19 @@ KeyframeEffectReadOnly::ComposeStyle(
 
     // Note, however, that we don't actually send animations with a negative
     // playback rate in their end delay phase to the compositor at this stage
     // (bug 1330498).
     EnsureBaseStylesForCompositor(aPropertiesToSkip);
     return;
   }
 
+  nsPresContext* presContext = GetPresContext();
+  bool isServoBackend = presContext && presContext->StyleSet()->IsServo();
+
   mNeedsBaseStyleSet.Empty();
 
   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");
@@ -527,82 +530,141 @@ KeyframeEffectReadOnly::ComposeStyle(
       MOZ_ASSERT(segment->mFromKey == (segment-1)->mToKey, "incorrect keys");
     }
     MOZ_ASSERT(segment->mFromKey <= segment->mToKey, "incorrect keys");
     MOZ_ASSERT(segment >= prop.mSegments.Elements() &&
                size_t(segment - prop.mSegments.Elements()) <
                  prop.mSegments.Length(),
                "out of array bounds");
 
-    if (!aStyleRule.mGecko) {
-      // Allocate the style rule now that we know we have animation data.
-      aStyleRule.mGecko = new AnimValuesStyleRule();
-    }
+    // Bug 1333311 - We use two branches for Gecko and Stylo. However, it's
+    // better to remove the duplicated code.
+    if (isServoBackend) {
+      // Servo backend
+
+      // Bug 1329878 - Stylo: Implement accumulate and addition on Servo
+      // AnimationValue.
+      RawServoAnimationValue* servoFromValue = segment->mServoFromValue;
+      RawServoAnimationValue* servoToValue = segment->mServoToValue;
+
+      // For unsupported or non-animatable animation types, we get nullptrs.
+      if (!servoFromValue || !servoToValue) {
+        NS_ERROR("Compose style for unsupported or non-animatable property, "
+                 "so get invalid RawServoAnimationValues");
+        continue;
+      }
+
+      if (!aStyleRule.mServo) {
+        // Allocate the style rule now that we know we have animation data.
+        aStyleRule.mServo = new ServoAnimationRule();
+      }
+
+      // Special handling for zero-length segments
+      if (segment->mToKey == segment->mFromKey) {
+        if (computedTiming.mProgress.Value() < 0) {
+          aStyleRule.mServo->AddValue(prop.mProperty, servoFromValue);
+        } else {
+          aStyleRule.mServo->AddValue(prop.mProperty, servoToValue);
+        }
+        continue;
+      }
 
-    StyleAnimationValue fromValue =
-      CompositeValue(prop.mProperty, aStyleRule.mGecko,
-                     segment->mFromValue,
-                     segment->mFromComposite);
-    StyleAnimationValue toValue =
-      CompositeValue(prop.mProperty, aStyleRule.mGecko,
-                     segment->mToValue,
-                     segment->mToComposite);
+      double positionInSegment =
+        (computedTiming.mProgress.Value() - segment->mFromKey) /
+        (segment->mToKey - segment->mFromKey);
+      double valuePosition =
+        ComputedTimingFunction::GetPortion(segment->mTimingFunction,
+                                           positionInSegment,
+                                           computedTiming.mBeforeFlag);
+
+      MOZ_ASSERT(IsFinite(valuePosition), "Position value should be finite");
+
+      RefPtr<RawServoAnimationValue> interpolated =
+        Servo_AnimationValues_Interpolate(servoFromValue,
+                                          servoToValue,
+                                          valuePosition).Consume();
 
-    // Iteration composition for accumulate
-    if (mEffectOptions.mIterationComposite ==
+      if (interpolated) {
+        aStyleRule.mServo->AddValue(prop.mProperty, interpolated);
+      } else if (valuePosition < 0.5) {
+        aStyleRule.mServo->AddValue(prop.mProperty, servoFromValue);
+      } else {
+        aStyleRule.mServo->AddValue(prop.mProperty, servoToValue);
+      }
+    } else {
+      // Gecko backend
+
+      if (!aStyleRule.mGecko) {
+        // Allocate the style rule now that we know we have animation data.
+        aStyleRule.mGecko = new AnimValuesStyleRule();
+      }
+
+      StyleAnimationValue fromValue =
+        CompositeValue(prop.mProperty, aStyleRule.mGecko,
+                       segment->mFromValue,
+                       segment->mFromComposite);
+      StyleAnimationValue toValue =
+        CompositeValue(prop.mProperty, aStyleRule.mGecko,
+                       segment->mToValue,
+                       segment->mToComposite);
+
+      // Iteration composition for accumulate
+      if (mEffectOptions.mIterationComposite ==
           IterationCompositeOperation::Accumulate &&
-        computedTiming.mCurrentIteration > 0) {
-      const AnimationPropertySegment& lastSegment =
-        prop.mSegments.LastElement();
-      // FIXME: Bug 1293492: Add a utility function to calculate both of
-      // below StyleAnimationValues.
-      StyleAnimationValue lastValue = lastSegment.mToValue.IsNull()
-        ? GetUnderlyingStyle(prop.mProperty, aStyleRule.mGecko)
-        : lastSegment.mToValue;
-      fromValue =
-        StyleAnimationValue::Accumulate(prop.mProperty,
-                                        lastValue,
-                                        Move(fromValue),
-                                        computedTiming.mCurrentIteration);
-      toValue =
-        StyleAnimationValue::Accumulate(prop.mProperty,
-                                        lastValue,
-                                        Move(toValue),
-                                        computedTiming.mCurrentIteration);
-    }
+          computedTiming.mCurrentIteration > 0) {
+        const AnimationPropertySegment& lastSegment =
+          prop.mSegments.LastElement();
+        // FIXME: Bug 1293492: Add a utility function to calculate both of
+        // below StyleAnimationValues.
+        StyleAnimationValue lastValue = lastSegment.mToValue.IsNull()
+          ? GetUnderlyingStyle(prop.mProperty, aStyleRule.mGecko)
+          : lastSegment.mToValue;
+        fromValue =
+          StyleAnimationValue::Accumulate(prop.mProperty,
+                                          lastValue,
+                                          Move(fromValue),
+                                          computedTiming.mCurrentIteration);
+        toValue =
+          StyleAnimationValue::Accumulate(prop.mProperty,
+                                          lastValue,
+                                          Move(toValue),
+                                          computedTiming.mCurrentIteration);
+      }
 
-    // Special handling for zero-length segments
-    if (segment->mToKey == segment->mFromKey) {
-      if (computedTiming.mProgress.Value() < 0) {
+      // Special handling for zero-length segments
+      if (segment->mToKey == segment->mFromKey) {
+        if (computedTiming.mProgress.Value() < 0) {
+          aStyleRule.mGecko->AddValue(prop.mProperty, Move(fromValue));
+        } else {
+          aStyleRule.mGecko->AddValue(prop.mProperty, Move(toValue));
+        }
+        continue;
+      }
+
+      double positionInSegment =
+        (computedTiming.mProgress.Value() - segment->mFromKey) /
+        (segment->mToKey - segment->mFromKey);
+      double valuePosition =
+        ComputedTimingFunction::GetPortion(segment->mTimingFunction,
+                                           positionInSegment,
+                                           computedTiming.mBeforeFlag);
+
+      MOZ_ASSERT(IsFinite(valuePosition), "Position value should be finite");
+
+      StyleAnimationValue val;
+      if (StyleAnimationValue::Interpolate(prop.mProperty,
+                                           fromValue,
+                                           toValue,
+                                           valuePosition, val)) {
+        aStyleRule.mGecko->AddValue(prop.mProperty, Move(val));
+      } else if (valuePosition < 0.5) {
         aStyleRule.mGecko->AddValue(prop.mProperty, Move(fromValue));
       } else {
         aStyleRule.mGecko->AddValue(prop.mProperty, Move(toValue));
       }
-      continue;
-    }
-
-    double positionInSegment =
-      (computedTiming.mProgress.Value() - segment->mFromKey) /
-      (segment->mToKey - segment->mFromKey);
-    double valuePosition =
-      ComputedTimingFunction::GetPortion(segment->mTimingFunction,
-                                         positionInSegment,
-                                         computedTiming.mBeforeFlag);
-
-    MOZ_ASSERT(IsFinite(valuePosition), "Position value should be finite");
-    StyleAnimationValue val;
-    if (StyleAnimationValue::Interpolate(prop.mProperty,
-                                         fromValue,
-                                         toValue,
-                                         valuePosition, val)) {
-      aStyleRule.mGecko->AddValue(prop.mProperty, Move(val));
-    } else if (valuePosition < 0.5) {
-      aStyleRule.mGecko->AddValue(prop.mProperty, Move(fromValue));
-    } else {
-      aStyleRule.mGecko->AddValue(prop.mProperty, Move(toValue));
     }
   }
 
   // For properties that can be run on the compositor, we may need to prepare
   // base styles to send to the compositor even if the current processing
   // segment for properties does not have either an additive or accumulative
   // composite mode, and even if the animation is not in-effect. That's because
   // the animation may later progress to a segment which has an additive or
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -108,16 +108,21 @@ SERVO_BINDING_FUNC(Servo_RestyleWithAdde
 
 // AnimationValues handling
 SERVO_BINDING_FUNC(Servo_AnimationValues_Populate, void,
                    RawGeckoAnimationValueListBorrowedMut,
                    RawServoDeclarationBlockBorrowed,
                    ServoComputedValuesBorrowed,
                    ServoComputedValuesBorrowedOrNull,
                    RawGeckoPresContextBorrowed)
+SERVO_BINDING_FUNC(Servo_AnimationValues_Interpolate,
+                   RawServoAnimationValueStrong,
+                   RawServoAnimationValueBorrowed from,
+                   RawServoAnimationValueBorrowed to,
+                   double progress)
 SERVO_BINDING_FUNC(Servo_AnimationValues_Uncompute,
                    RawServoDeclarationBlockStrong,
                    RawServoAnimationValueBorrowedListBorrowed value)
 
 // Style attribute
 SERVO_BINDING_FUNC(Servo_ParseStyleAttribute, RawServoDeclarationBlockStrong,
                    const nsACString* data)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_CreateEmpty,