Bug 1279071 - Change GetOpacity to GetAnimationOpacity to return opacity value applied by animation. r?birtles,mstange draft
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Thu, 25 Aug 2016 09:07:56 +0900
changeset 405186 069aa228b3150cb41ea61a5ade0938b0f80d9e90
parent 404988 01748a2b1a463f24efd9cd8abad9ccfd76b037b8
child 405249 ee261365639209857e9f6c94d90a92a93cb3418c
push id27428
push userbmo:hiikezoe@mozilla-japan.org
push dateThu, 25 Aug 2016 02:13:48 +0000
reviewersbirtles, mstange
bugs1279071
milestone51.0a1
Bug 1279071 - Change GetOpacity to GetAnimationOpacity to return opacity value applied by animation. r?birtles,mstange MozReview-Commit-ID: 6rMUlnppOeK
dom/base/nsDOMWindowUtils.cpp
gfx/layers/composite/AsyncCompositionManager.cpp
gfx/layers/composite/LayerManagerComposite.cpp
gfx/layers/composite/LayerManagerComposite.h
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayerTransactionParent.h
gfx/layers/ipc/PLayerTransaction.ipdl
layout/style/test/test_animations_omta.html
layout/style/test/test_animations_omta_start.html
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -3632,23 +3632,28 @@ nsDOMWindowUtils::GetOMTAStyle(nsIDOMEle
     }
   }
   if (frame && nsLayoutUtils::AreAsyncAnimationsEnabled()) {
     if (aProperty.EqualsLiteral("opacity")) {
       Layer* layer =
         FrameLayerBuilder::GetDedicatedLayer(frame,
                                              nsDisplayItem::TYPE_OPACITY);
       if (layer) {
-        float value;
         ShadowLayerForwarder* forwarder = layer->Manager()->AsShadowForwarder();
         if (forwarder && forwarder->HasShadowManager()) {
-          forwarder->GetShadowManager()->SendGetOpacity(
-            layer->AsShadowableLayer()->GetShadow(), &value);
-          cssValue = new nsROCSSPrimitiveValue;
-          cssValue->SetNumber(value);
+          float value;
+          bool hadAnimatedOpacity;
+          forwarder->GetShadowManager()->SendGetAnimationOpacity(
+            layer->AsShadowableLayer()->GetShadow(),
+            &value, &hadAnimatedOpacity);
+
+          if (hadAnimatedOpacity) {
+            cssValue = new nsROCSSPrimitiveValue;
+            cssValue->SetNumber(value);
+          }
         }
       }
     } else if (aProperty.EqualsLiteral("transform")) {
       Layer* layer =
         FrameLayerBuilder::GetDedicatedLayer(frame,
                                              nsDisplayItem::TYPE_TRANSFORM);
       if (layer) {
         ShadowLayerForwarder* forwarder = layer->Manager()->AsShadowForwarder();
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -680,16 +680,17 @@ SampleAnimations(Layer* aLayer, TimeStam
           Animatable interpolatedValue;
           SampleValue(portion, animation, animData.mStartValues[segmentIndex],
                       animData.mEndValues[segmentIndex], &interpolatedValue, layer);
           LayerComposite* layerComposite = layer->AsLayerComposite();
           switch (animation.property()) {
           case eCSSProperty_opacity:
           {
             layerComposite->SetShadowOpacity(interpolatedValue.get_float());
+            layerComposite->SetShadowOpacitySetByAnimation(true);
             break;
           }
           case eCSSProperty_transform:
           {
             Matrix4x4 matrix = interpolatedValue.get_ArrayOfTransformFunction()[0].get_TransformMatrix().value();
             if (ContainerLayer* c = layer->AsContainerLayer()) {
               matrix.PostScale(c->GetInheritedXScale(), c->GetInheritedYScale(), 1);
             }
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -1328,16 +1328,17 @@ LayerManagerComposite::ChangeCompositor(
   mTwoPassTmpTarget = nullptr;
 }
 
 LayerComposite::LayerComposite(LayerManagerComposite *aManager)
   : mCompositeManager(aManager)
   , mCompositor(aManager->GetCompositor())
   , mShadowOpacity(1.0)
   , mShadowTransformSetByAnimation(false)
+  , mShadowOpacitySetByAnimation(false)
   , mDestroyed(false)
   , mLayerComposited(false)
 { }
 
 LayerComposite::~LayerComposite()
 {
 }
 
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -501,16 +501,20 @@ public:
   {
     mShadowVisibleRegion = aRegion;
   }
 
   void SetShadowOpacity(float aOpacity)
   {
     mShadowOpacity = aOpacity;
   }
+  void SetShadowOpacitySetByAnimation(bool aSetByAnimation)
+  {
+    mShadowOpacitySetByAnimation = aSetByAnimation;
+  }
 
   void SetShadowClipRect(const Maybe<ParentLayerIntRect>& aRect)
   {
     mShadowClipRect = aRect;
   }
 
   void SetShadowBaseTransform(const gfx::Matrix4x4& aMatrix)
   {
@@ -533,16 +537,17 @@ public:
 
   // These getters can be used anytime.
   float GetShadowOpacity() { return mShadowOpacity; }
   const Maybe<ParentLayerIntRect>& GetShadowClipRect() { return mShadowClipRect; }
   const LayerIntRegion& GetShadowVisibleRegion() { return mShadowVisibleRegion; }
   const gfx::Matrix4x4& GetShadowBaseTransform() { return mShadowTransform; }
   gfx::Matrix4x4 GetShadowTransform();
   bool GetShadowTransformSetByAnimation() { return mShadowTransformSetByAnimation; }
+  bool GetShadowOpacitySetByAnimation() { return mShadowOpacitySetByAnimation; }
   bool HasLayerBeenComposited() { return mLayerComposited; }
   gfx::IntRect GetClearRect() { return mClearRect; }
 
   // Returns false if the layer is attached to an older compositor.
   bool HasStaleCompositor() const;
 
   /**
    * Return the part of the visible region that has been fully rendered.
@@ -560,16 +565,17 @@ public:
 protected:
   gfx::Matrix4x4 mShadowTransform;
   LayerIntRegion mShadowVisibleRegion;
   Maybe<ParentLayerIntRect> mShadowClipRect;
   LayerManagerComposite* mCompositeManager;
   RefPtr<Compositor> mCompositor;
   float mShadowOpacity;
   bool mShadowTransformSetByAnimation;
+  bool mShadowOpacitySetByAnimation;
   bool mDestroyed;
   bool mLayerComposited;
   gfx::IntRect mClearRect;
 };
 
 // Render aLayer using aCompositor and apply all mask layers of aLayer: The
 // layer's own mask layer (aLayer->GetMaskLayer()), and any ancestor mask
 // layers.
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1155,16 +1155,17 @@ CompositorBridgeParent::SetShadowPropert
         // FIXME: Bug 717688 -- Do these updates in LayerTransactionParent::RecvUpdate.
         LayerComposite* layerComposite = layer->AsLayerComposite();
         // Set the layerComposite's base transform to the layer's base transform.
         layerComposite->SetShadowBaseTransform(layer->GetBaseTransform());
         layerComposite->SetShadowTransformSetByAnimation(false);
         layerComposite->SetShadowVisibleRegion(layer->GetVisibleRegion());
         layerComposite->SetShadowClipRect(layer->GetClipRect());
         layerComposite->SetShadowOpacity(layer->GetOpacity());
+        layerComposite->SetShadowOpacitySetByAnimation(false);
       }
     );
 }
 
 void
 CompositorBridgeParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRect)
 {
   profiler_tracing("Paint", "Composite", TRACING_INTERVAL_START);
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -720,31 +720,38 @@ LayerTransactionParent::RecvSetTestSampl
 bool
 LayerTransactionParent::RecvLeaveTestMode()
 {
   mShadowLayersManager->LeaveTestMode(this);
   return true;
 }
 
 bool
-LayerTransactionParent::RecvGetOpacity(PLayerParent* aParent,
-                                       float* aOpacity)
+LayerTransactionParent::RecvGetAnimationOpacity(PLayerParent* aParent,
+                                                float* aOpacity,
+                                                bool* aHasAnimationOpacity)
 {
+  *aHasAnimationOpacity = false;
   if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
     return false;
   }
 
   Layer* layer = cast(aParent)->AsLayer();
   if (!layer) {
     return false;
   }
 
   mShadowLayersManager->ApplyAsyncProperties(this);
 
+  if (!layer->AsLayerComposite()->GetShadowOpacitySetByAnimation()) {
+    return true;
+  }
+
   *aOpacity = layer->GetLocalOpacity();
+  *aHasAnimationOpacity = true;
   return true;
 }
 
 bool
 LayerTransactionParent::RecvGetAnimationTransform(PLayerParent* aParent,
                                                   MaybeTransform* aTransform)
 {
   if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -138,18 +138,19 @@ protected:
                                 const bool& isRepeatTransaction,
                                 const mozilla::TimeStamp& aTransactionStart,
                                 const int32_t& aPaintSyncId) override;
 
   virtual bool RecvClearCachedResources() override;
   virtual bool RecvForceComposite() override;
   virtual bool RecvSetTestSampleTime(const TimeStamp& aTime) override;
   virtual bool RecvLeaveTestMode() override;
-  virtual bool RecvGetOpacity(PLayerParent* aParent,
-                              float* aOpacity) override;
+  virtual bool RecvGetAnimationOpacity(PLayerParent* aParent,
+                                       float* aOpacity,
+                                       bool* aHasAnimationOpacity) override;
   virtual bool RecvGetAnimationTransform(PLayerParent* aParent,
                                          MaybeTransform* aTransform)
                                          override;
   virtual bool RecvSetAsyncScrollOffset(const FrameMetrics::ViewID& aId,
                                         const float& aX, const float& aY) override;
   virtual bool RecvSetAsyncZoom(const FrameMetrics::ViewID& aId,
                                 const float& aValue) override;
   virtual bool RecvFlushApzRepaints() override;
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -73,17 +73,21 @@ parent:
   // Testing APIs
 
   // Enter test mode, set the sample time to sampleTime, and resample
   // animations. sampleTime must not be null.
   sync SetTestSampleTime(TimeStamp sampleTime);
   // Leave test mode and resume normal compositing
   sync LeaveTestMode();
 
-  sync GetOpacity(PLayer layer) returns (float opacity);
+  // Returns the value of the opacity applied to the layer by animation.
+  // |hasAnimationOpacity| is true if the layer has an opacity value
+  // specified by animation. If it's false, |opacity| value is indefinite.
+  sync GetAnimationOpacity(PLayer layer) returns (float opacity,
+                                                  bool hasAnimationOpacity);
 
   // Returns the value of the transform applied to the layer by animation after
   // factoring out translation components introduced to account for the offset
   // of the corresponding frame and transform origin and after converting to CSS
   // pixels. If the layer is not transformed by animation, the return value will
   // be void_t.
   sync GetAnimationTransform(PLayer layer) returns (MaybeTransform transform);
 
--- a/layout/style/test/test_animations_omta.html
+++ b/layout/style/test/test_animations_omta.html
@@ -1200,44 +1200,44 @@ addAsyncAnimTest(function *() {
   omta_is("transform", { ty: 0 }, RunningOn.Compositor,
           "animation-play-state test 3, at 0s");
   advance_clock(250);
   gDiv.style.animationPlayState = "paused, running"; // pause 1
   yield waitForPaintsFlushed();
   // As noted with the tests for animation-iteration-count, for opacity
   // animations we don't strictly check the finished animation is being animated
   // on the main thread, but simply that it is producing the correct result.
-  omta_is_approx("opacity", gTF.ease_out(0.25), 0.01, RunningOn.Either,
-                 "animation-play-state test 2 at 250ms");
+  omta_is_approx("opacity", gTF.ease_out(0.25), 0.01, RunningOn.MainThread,
+                 "animation-play-state test 2 at 250ms"); // paused
   omta_is_approx("transform", { ty: 100 * gTF.ease_in(0.125) }, 0.01,
                  RunningOn.Compositor,
                  "animation-play-state test 3 at 250ms");
   advance_clock(250);
-  omta_is_approx("opacity", gTF.ease_out(0.25), 0.01, RunningOn.Either,
-                 "animation-play-state test 2 at 500ms");
+  omta_is_approx("opacity", gTF.ease_out(0.25), 0.01, RunningOn.MainThread,
+                 "animation-play-state test 2 at 500ms"); // paused
   omta_is_approx("transform", { ty: 100 * gTF.ease_in(0.25) }, 0.01,
                  RunningOn.Compositor,
                  "animation-play-state test 3 at 500ms");
   advance_clock(250);
   gDiv.style.animationPlayState = "running, paused"; // unpause 1, pause 2
   yield waitForPaintsFlushed();
   advance_clock(250);
   omta_is_approx("opacity", gTF.ease_out(0.5), 0.01, RunningOn.Compositor,
                  "animation-play-state test 2 at 1000ms");
   omta_is_approx("transform", { ty: 100 * gTF.ease_in(0.375) }, 0.01,
                  RunningOn.MainThread,
-                 "animation-play-state test 3 at 1000ms");
+                 "animation-play-state test 3 at 1000ms"); // paused
   gDiv.style.animationPlayState = "paused"; // pause all
   yield waitForPaintsFlushed();
   advance_clock(3000);
-  omta_is_approx("opacity", gTF.ease_out(0.5), 0.01, RunningOn.Either,
-                 "animation-play-state test 2 at 4000ms");
+  omta_is_approx("opacity", gTF.ease_out(0.5), 0.01, RunningOn.MainThread,
+                 "animation-play-state test 2 at 4000ms"); // paused
   omta_is_approx("transform", { ty: 100 * gTF.ease_in(0.375) }, 0.01,
                  RunningOn.MainThread,
-                 "animation-play-state test 3 at 4000ms");
+                 "animation-play-state test 3 at 4000ms"); // paused
   gDiv.style.animationPlayState = "running, paused"; // pause 2
   yield waitForPaintsFlushed();
   advance_clock(850);
   omta_is_approx("opacity", gTF.ease_out(0.65), 0.01, RunningOn.Compositor,
                  "animation-play-state test 2 at 4850ms");
   omta_is_approx("transform", { ty: 100 * gTF.ease_in(0.375) }, 0.01,
                  RunningOn.MainThread,
                  "animation-play-state test 3 at 4850ms");
@@ -1357,20 +1357,20 @@ addAsyncAnimTest(function *() {
   omta_is("opacity", 1, RunningOn.Either,
           "delay and play-state delay test at 0ms");
   advance_clock(400);
   omta_is("opacity", 1, RunningOn.Either,
           "delay and play-state delay test at 400ms");
   gDiv.style.animationPlayState = "paused";
   yield waitForPaintsFlushed();
   advance_clock(100);
-  omta_is("opacity", 1, RunningOn.Either,
+  omta_is("opacity", 1, RunningOn.MainThread, // paused
           "delay and play-state delay test at 500ms");
   advance_clock(500);
-  omta_is("opacity", 1, RunningOn.Either,
+  omta_is("opacity", 1, RunningOn.MainThread, // paused
           "delay and play-state delay test at 1000ms");
   gDiv.style.animationPlayState = "running";
   yield waitForPaintsFlushed();
   advance_clock(100);
   yield waitForPaints();
   omta_is("opacity", 0, RunningOn.Compositor,
           "delay and play-state delay test at 1100ms");
   advance_clock(100);
--- a/layout/style/test/test_animations_omta_start.html
+++ b/layout/style/test/test_animations_omta_start.html
@@ -151,16 +151,22 @@ function testTransitionTakingOver() {
     waitForAllPaints(function() {
       child.style.opacity = "1.0";
       var opacity = gUtils.getOMTAStyle(child, "opacity");
       // FIXME Bug 1039799 (or lower priority followup): Animations
       // inherited from an animating parent element don't get shipped to
       // the compositor thread.
       todo_is(opacity, "0.4",
          "transition that interrupted animation is correct");
+
+      // Trigger to start the transition, without this the transition will
+      // be pending in advanceTimeAndRefresh(0) so the transition will not
+      // be sent to the compositor until we call advanceTimeAndRefresh with
+      // a positive time value.
+      getComputedStyle(child).opacity;
       gUtils.advanceTimeAndRefresh(0);
       waitForAllPaints(function() {
         var opacity = gUtils.getOMTAStyle(child, "opacity");
         is(opacity, "0.4",
            "transition that interrupted animation is correct");
         gUtils.advanceTimeAndRefresh(5000);
         waitForAllPaints(function() {
           opacity = gUtils.getOMTAStyle(child, "opacity");