Bug 1340005 - Part 3: Use AnimationValue on the compositor thread. r=birtles
authorBoris Chiou <boris.chiou@gmail.com>
Thu, 21 Sep 2017 17:01:48 +0800
changeset 426523 b43c82ffe651880e52322b7dcdc50cc0752baeb6
parent 426522 143169e5a42dac7c6a2a24b68494886b44ec748c
child 426524 6ba6dfa9f2293f92ecc1431efa67cce1a4c25d3f
push idunknown
push userunknown
push dateunknown
reviewersbirtles
bugs1340005
milestone58.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 1340005 - Part 3: Use AnimationValue on the compositor thread. r=birtles MozReview-Commit-ID: CtnDLsdcr9x
gfx/layers/AnimationHelper.cpp
gfx/layers/AnimationHelper.h
gfx/layers/AnimationInfo.h
gfx/layers/Layers.h
gfx/layers/composite/AsyncCompositionManager.cpp
layout/style/StyleAnimationValue.cpp
--- a/gfx/layers/AnimationHelper.cpp
+++ b/gfx/layers/AnimationHelper.cpp
@@ -190,21 +190,22 @@ SampleValue(double aPortion, const layer
     StyleAnimationValue::Interpolate(aAnimation.property(),
                                      startValue, endValue,
                                      aPortion, interpolatedValue);
   MOZ_ASSERT(uncomputeResult, "could not uncompute value");
   return interpolatedValue;
 }
 
 bool
-AnimationHelper::SampleAnimationForEachNode(TimeStamp aTime,
-                           AnimationArray& aAnimations,
-                           InfallibleTArray<AnimData>& aAnimationData,
-                           StyleAnimationValue& aAnimationValue,
-                           bool& aHasInEffectAnimations)
+AnimationHelper::SampleAnimationForEachNode(
+  TimeStamp aTime,
+  AnimationArray& aAnimations,
+  InfallibleTArray<AnimData>& aAnimationData,
+  AnimationValue& aAnimationValue,
+  bool& aHasInEffectAnimations)
 {
   bool activeAnimations = false;
 
   if (aAnimations.IsEmpty()) {
     return activeAnimations;
   }
 
   // Process in order, since later aAnimations override earlier ones.
@@ -264,30 +265,31 @@ AnimationHelper::SampleAnimationForEachN
       (segment->endPortion() - segment->startPortion());
 
     double portion =
       ComputedTimingFunction::GetPortion(animData.mFunctions[segmentIndex],
                                          positionInSegment,
                                      computedTiming.mBeforeFlag);
 
     StyleAnimationValueCompositePair from {
-      animData.mStartValues[segmentIndex],
+      animData.mStartValues[segmentIndex].mGecko,
       static_cast<dom::CompositeOperation>(segment->startComposite())
     };
     StyleAnimationValueCompositePair to {
-      animData.mEndValues[segmentIndex],
+      animData.mEndValues[segmentIndex].mGecko,
       static_cast<dom::CompositeOperation>(segment->endComposite())
     };
     // interpolate the property
-    aAnimationValue = SampleValue(portion,
-                                 animation,
-                                 from, to,
-                                 animData.mEndValues.LastElement(),
-                                 computedTiming.mCurrentIteration,
-                                 aAnimationValue);
+    aAnimationValue.mGecko =
+      SampleValue(portion,
+                  animation,
+                  from, to,
+                  animData.mEndValues.LastElement().mGecko,
+                  computedTiming.mCurrentIteration,
+                  aAnimationValue.mGecko);
     aHasInEffectAnimations = true;
   }
 
 #ifdef DEBUG
   // Sanity check that all of animation data are the same.
   const AnimationData& lastData = aAnimations.LastElement().data();
   for (const Animation& animation : aAnimations) {
     const AnimationData& data = animation.data();
@@ -488,17 +490,17 @@ ToAnimationValue(const Animatable& aAnim
   }
 
   return result;
 }
 
 void
 AnimationHelper::SetAnimations(AnimationArray& aAnimations,
                                InfallibleTArray<AnimData>& aAnimData,
-                               StyleAnimationValue& aBaseAnimationStyle)
+                               AnimationValue& aBaseAnimationStyle)
 {
   for (uint32_t i = 0; i < aAnimations.Length(); i++) {
     Animation& animation = aAnimations[i];
     // Adjust fill mode to fill forwards so that if the main thread is delayed
     // in clearing this animation we don't introduce flicker by jumping back to
     // the old underlying value
     switch (static_cast<dom::FillMode>(animation.fillMode())) {
       case dom::FillMode::None:
@@ -507,29 +509,29 @@ AnimationHelper::SetAnimations(Animation
       case dom::FillMode::Backwards:
         animation.fillMode() = static_cast<uint8_t>(dom::FillMode::Both);
         break;
       default:
         break;
     }
 
     if (animation.baseStyle().type() != Animatable::Tnull_t) {
-      aBaseAnimationStyle = ToAnimationValue(animation.baseStyle()).mGecko;
+      aBaseAnimationStyle = ToAnimationValue(animation.baseStyle());
     }
 
     AnimData* data = aAnimData.AppendElement();
     InfallibleTArray<Maybe<ComputedTimingFunction>>& functions =
       data->mFunctions;
-    InfallibleTArray<StyleAnimationValue>& startValues = data->mStartValues;
-    InfallibleTArray<StyleAnimationValue>& endValues = data->mEndValues;
+    InfallibleTArray<AnimationValue>& startValues = data->mStartValues;
+    InfallibleTArray<AnimationValue>& endValues = data->mEndValues;
 
     const InfallibleTArray<AnimationSegment>& segments = animation.segments();
     for (const AnimationSegment& segment : segments) {
-      startValues.AppendElement(ToAnimationValue(segment.startState()).mGecko);
-      endValues.AppendElement(ToAnimationValue(segment.endState()).mGecko);
+      startValues.AppendElement(ToAnimationValue(segment.startState()));
+      endValues.AppendElement(ToAnimationValue(segment.endState()));
 
       TimingFunction tf = segment.sampleFn();
       Maybe<ComputedTimingFunction> ctf =
         AnimationUtils::TimingFunctionToComputedTimingFunction(tf);
       functions.AppendElement(ctf);
     }
   }
 }
@@ -557,17 +559,17 @@ AnimationHelper::SampleAnimations(Compos
     return;
   }
 
   //Sample the animations in CompositorAnimationStorage
   for (auto iter = aStorage->ConstAnimationsTableIter();
        !iter.Done(); iter.Next()) {
     bool hasInEffectAnimations = false;
     AnimationArray* animations = iter.UserData();
-    StyleAnimationValue animationValue;
+    AnimationValue animationValue;
     InfallibleTArray<AnimData> animationData;
     AnimationHelper::SetAnimations(*animations,
                                    animationData,
                                    animationValue);
     AnimationHelper::SampleAnimationForEachNode(aTime,
                                                 *animations,
                                                 animationData,
                                                 animationValue,
@@ -576,22 +578,22 @@ AnimationHelper::SampleAnimations(Compos
     if (!hasInEffectAnimations) {
       continue;
     }
 
     // Store the AnimatedValue
     Animation& animation = animations->LastElement();
     switch (animation.property()) {
       case eCSSProperty_opacity: {
-        aStorage->SetAnimatedValue(iter.Key(),
-                                   animationValue.GetFloatValue());
+        aStorage->SetAnimatedValue(iter.Key(), animationValue.GetOpacity());
         break;
       }
       case eCSSProperty_transform: {
-        nsCSSValueSharedList* list = animationValue.GetCSSValueSharedListValue();
+        // TODO: Convert AnimationValue into css shared list.
+        nsCSSValueSharedList* list = animationValue.mGecko.GetCSSValueSharedListValue();
         const TransformData& transformData = animation.data().get_TransformData();
         nsPoint origin = transformData.origin();
         // we expect all our transform data to arrive in device pixels
         gfx::Point3D transformOrigin = transformData.transformOrigin();
         nsDisplayTransform::FrameTransformProperties props(list,
                                                            transformOrigin);
 
         gfx::Matrix4x4 transform =
--- a/gfx/layers/AnimationHelper.h
+++ b/gfx/layers/AnimationHelper.h
@@ -8,25 +8,25 @@
 #define mozilla_layers_AnimationHelper_h
 
 #include "mozilla/ComputedTimingFunction.h" // for ComputedTimingFunction
 #include "mozilla/layers/LayersMessages.h" // for TransformData, etc
 #include "mozilla/TimeStamp.h"          // for TimeStamp
 
 
 namespace mozilla {
-class StyleAnimationValue;
+struct AnimationValue;
 namespace layers {
 class Animation;
 
 typedef InfallibleTArray<layers::Animation> AnimationArray;
 
 struct AnimData {
-  InfallibleTArray<mozilla::StyleAnimationValue> mStartValues;
-  InfallibleTArray<mozilla::StyleAnimationValue> mEndValues;
+  InfallibleTArray<mozilla::AnimationValue> mStartValues;
+  InfallibleTArray<mozilla::AnimationValue> mEndValues;
   InfallibleTArray<Maybe<mozilla::ComputedTimingFunction>> mFunctions;
 };
 
 struct AnimationTransform {
   /*
    * This transform is calculated from sampleanimation in device pixel
    * and used by compositor.
    */
@@ -198,26 +198,26 @@ public:
    * its animation data.
    * Returns true if there exists compositor animation, and stores corresponding
    * animated value in |aAnimationValue|.
    */
   static bool
   SampleAnimationForEachNode(TimeStamp aTime,
                              AnimationArray& aAnimations,
                              InfallibleTArray<AnimData>& aAnimationData,
-                             StyleAnimationValue& aAnimationValue,
+                             AnimationValue& aAnimationValue,
                              bool& aHasInEffectAnimations);
   /**
    * Populates AnimData stuctures into |aAnimData| and |aBaseAnimationStyle|
    * based on |aAnimations|.
    */
   static void
   SetAnimations(AnimationArray& aAnimations,
                 InfallibleTArray<AnimData>& aAnimData,
-                StyleAnimationValue& aBaseAnimationStyle);
+                AnimationValue& aBaseAnimationStyle);
 
   /**
    * Get a unique id to represent the compositor animation between child
    * and parent side. This id will be used as a key to store animation
    * data in the CompositorAnimationStorage per compositor.
    * Each layer on the content side calls this when it gets new animation
    * data.
    */
--- a/gfx/layers/AnimationInfo.h
+++ b/gfx/layers/AnimationInfo.h
@@ -45,32 +45,32 @@ public:
   // ClearAnimations clears animations on this layer.
   void ClearAnimations();
   void ClearAnimationsForNextTransaction();
   void SetCompositorAnimations(const CompositorAnimations& aCompositorAnimations);
   bool StartPendingAnimations(const TimeStamp& aReadyTime);
   void TransferMutatedFlagToLayer(Layer* aLayer);
 
   uint64_t GetCompositorAnimationsId() { return mCompositorAnimationsId; }
-  StyleAnimationValue GetBaseAnimationStyle() const { return mBaseAnimationStyle; }
+  AnimationValue GetBaseAnimationStyle() const { return mBaseAnimationStyle; }
   InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
   AnimationArray& GetAnimations() { return mAnimations; }
   bool ApplyPendingUpdatesForThisTransaction();
   bool HasOpacityAnimation() const;
   bool HasTransformAnimation() const;
 
 protected:
   LayerManager* mManager;
   AnimationArray mAnimations;
   uint64_t mCompositorAnimationsId;
   nsAutoPtr<AnimationArray> mPendingAnimations;
   InfallibleTArray<AnimData> mAnimationData;
   // If this layer is used for OMTA, then this counter is used to ensure we
   // stay in sync with the animation manager
   uint64_t mAnimationGeneration;
-  StyleAnimationValue mBaseAnimationStyle;
+  AnimationValue mBaseAnimationStyle;
   bool mMutated;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // GFX_ANIMATIONINFO_H
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -1431,17 +1431,17 @@ public:
   uint64_t GetCompositorAnimationsId() { return mAnimationInfo.GetCompositorAnimationsId(); }
   InfallibleTArray<AnimData>& GetAnimationData();
 
   uint64_t GetAnimationGeneration() { return mAnimationInfo.GetAnimationGeneration(); }
 
   bool HasTransformAnimation() const;
   bool HasOpacityAnimation() const;
 
-  StyleAnimationValue GetBaseAnimationStyle() const
+  AnimationValue GetBaseAnimationStyle() const
   {
     return mAnimationInfo.GetBaseAnimationStyle();
   }
 
   /**
    * Returns the local transform for this layer: either mTransform or,
    * for shadow layers, GetShadowBaseTransform(), in either case with the
    * pre- and post-scales applied.
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -574,40 +574,39 @@ AsyncCompositionManager::AlignFixedAndSt
   }
 }
 
 static void
 ApplyAnimatedValue(Layer* aLayer,
                    CompositorAnimationStorage* aStorage,
                    nsCSSPropertyID aProperty,
                    const AnimationData& aAnimationData,
-                   const StyleAnimationValue& aValue)
+                   const AnimationValue& aValue)
 {
   if (aValue.IsNull()) {
-    // Return gracefully if we have no valid StyleAnimationValue.
+    // Return gracefully if we have no valid AnimationValue.
     return;
   }
 
   HostLayer* layerCompositor = aLayer->AsHostLayer();
   switch (aProperty) {
     case eCSSProperty_opacity: {
-      MOZ_ASSERT(aValue.GetUnit() == StyleAnimationValue::eUnit_Float,
-                 "Interpolated value for opacity should be float");
-      layerCompositor->SetShadowOpacity(aValue.GetFloatValue());
+      layerCompositor->SetShadowOpacity(aValue.GetOpacity());
       layerCompositor->SetShadowOpacitySetByAnimation(true);
       aStorage->SetAnimatedValue(aLayer->GetCompositorAnimationsId(),
-                                 aValue.GetFloatValue());
+                                 aValue.GetOpacity());
 
       break;
     }
     case eCSSProperty_transform: {
-      MOZ_ASSERT(aValue.GetUnit() == StyleAnimationValue::eUnit_Transform,
+      MOZ_ASSERT(aValue.mGecko.GetUnit() == StyleAnimationValue::eUnit_Transform,
                  "The unit of interpolated value for transform should be "
                  "transform");
-      nsCSSValueSharedList* list = aValue.GetCSSValueSharedListValue();
+      // TODO: Convert AnimationValue into css shared list.
+      nsCSSValueSharedList* list = aValue.mGecko.GetCSSValueSharedListValue();
 
       const TransformData& transformData = aAnimationData.get_TransformData();
       nsPoint origin = transformData.origin();
       // we expect all our transform data to arrive in device pixels
       Point3D transformOrigin = transformData.transformOrigin();
       nsDisplayTransform::FrameTransformProperties props(list,
                                                          transformOrigin);
 
@@ -664,17 +663,17 @@ SampleAnimations(Layer* aLayer,
       aLayer,
       [&] (Layer* layer)
       {
         if (!ancestorRefLayer) {
           ancestorRefLayer = layer->AsRefLayer();
         }
 
         bool hasInEffectAnimations = false;
-        StyleAnimationValue animationValue = layer->GetBaseAnimationStyle();
+        AnimationValue animationValue = layer->GetBaseAnimationStyle();
         if (AnimationHelper::SampleAnimationForEachNode(aTime,
                                                         layer->GetAnimations(),
                                                         layer->GetAnimationData(),
                                                         animationValue,
                                                         hasInEffectAnimations)) {
           animProcess |= (ancestorRefLayer ? AnimationProcessTypes::eContent
                                            : AnimationProcessTypes::eChrome);
         }
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -5349,16 +5349,18 @@ AnimationValue::operator!=(const Animati
 {
   return !operator==(aOther);
 }
 
 float
 AnimationValue::GetOpacity() const
 {
   MOZ_ASSERT(!mServo != mGecko.IsNull());
+  MOZ_ASSERT(mServo || mGecko.GetUnit() == StyleAnimationValue::eUnit_Float,
+             "Should have the correct unit on Gecko backend");
   return mServo ? Servo_AnimationValue_GetOpacity(mServo)
                 : mGecko.GetFloatValue();
 }
 
 gfxSize
 AnimationValue::GetScaleValue(const nsIFrame* aFrame) const
 {
   MOZ_ASSERT(!mServo != mGecko.IsNull());