Bug 1340005 - Part 3: Use AnimationValue on the compositor thread. draft
authorBoris Chiou <boris.chiou@gmail.com>
Thu, 21 Sep 2017 17:01:48 +0800
changeset 687788 26c8e2d8e61eaa5b486c992c525bc63389424804
parent 687787 42f358b6e5fadd7fea06234383050cb62a4f7fac
child 687789 f8345ee25f6b61cbc2c51d9558d7ce37220f1c79
push id86604
push userbmo:boris.chiou@gmail.com
push dateFri, 27 Oct 2017 19:27:11 +0000
bugs1340005
milestone58.0a1
Bug 1340005 - Part 3: Use AnimationValue on the compositor thread. 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());