Bug 1479234 - Introduce a generic function to get an animation value on the compositor. r?boris,froydnj draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Tue, 31 Jul 2018 06:13:15 +0900
changeset 824448 7a137ca08ffff3833ba08337cfcb32da5e4504fc
parent 824364 b21e782599f6af1bef5a7232190ac406a3234453
child 824449 53dea49782c9bd94f4d6e3be1b3b9ca2d4741cd2
push id117909
push userhikezoe@mozilla.com
push dateMon, 30 Jul 2018 21:13:32 +0000
reviewersboris, froydnj
bugs1479234
milestone63.0a1
Bug 1479234 - Introduce a generic function to get an animation value on the compositor. r?boris,froydnj On the compositor we store animation values in a hash table and the hash is the compositor animation id which is a unique id for each property respectively. So we can get the corresponding animation value for the given property. In this patch there are lots of duplicated code, but they will be removed in the next patch. MozReview-Commit-ID: 7EboVcculcg
dom/base/nsDOMWindowUtils.cpp
gfx/layers/AnimationHelper.cpp
gfx/layers/AnimationHelper.h
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayerTransactionParent.h
gfx/layers/ipc/LayersMessages.ipdlh
gfx/layers/ipc/PLayerTransaction.ipdl
gfx/layers/ipc/PWebRenderBridge.ipdl
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
ipc/ipdl/sync-messages.ini
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -3674,66 +3674,61 @@ nsDOMWindowUtils::GetOMTAStyle(Element* 
   RefPtr<nsROCSSPrimitiveValue> cssValue = nullptr;
   if (frame && nsLayoutUtils::AreAsyncAnimationsEnabled()) {
     RefPtr<LayerManager> widgetLayerManager;
     if (nsIWidget* widget = GetWidget()) {
       widgetLayerManager = widget->GetLayerManager();
     }
 
     if (aProperty.EqualsLiteral("opacity")) {
-      float value = 0;
-      bool hadAnimatedOpacity = false;
+      OMTAValue value;
 
       Layer* layer =
         FrameLayerBuilder::GetDedicatedLayer(frame, DisplayItemType::TYPE_OPACITY);
       if (layer) {
         ShadowLayerForwarder* forwarder = layer->Manager()->AsShadowForwarder();
         if (forwarder && forwarder->HasShadowManager()) {
           forwarder->GetShadowManager()->
-            SendGetAnimationOpacity(layer->GetCompositorAnimationsId(),
-                                    &value,
-                                    &hadAnimatedOpacity);
+            SendGetAnimationValue(layer->GetCompositorAnimationsId(), &value);
         }
       } else if (WebRenderBridgeChild* wrbc = GetWebRenderBridge()) {
         RefPtr<WebRenderAnimationData> animationData =
             GetWebRenderUserData<WebRenderAnimationData>(frame, (uint32_t)DisplayItemType::TYPE_OPACITY);
         if (animationData) {
-          wrbc->SendGetAnimationOpacity(
+          wrbc->SendGetAnimationValue(
               animationData->GetAnimationInfo().GetCompositorAnimationsId(),
-              &value,
-              &hadAnimatedOpacity);
+              &value);
         }
       }
-      if (hadAnimatedOpacity) {
+      if (value.type() == OMTAValue::Tfloat) {
         cssValue = new nsROCSSPrimitiveValue;
-        cssValue->SetNumber(value);
+        cssValue->SetNumber(value.get_float());
       }
     } else if (aProperty.EqualsLiteral("transform")) {
-      MaybeTransform transform;
+      OMTAValue value;
 
       Layer* layer =
         FrameLayerBuilder::GetDedicatedLayer(frame, DisplayItemType::TYPE_TRANSFORM);
       if (layer) {
         ShadowLayerForwarder* forwarder = layer->Manager()->AsShadowForwarder();
         if (forwarder && forwarder->HasShadowManager()) {
           forwarder->GetShadowManager()->
-            SendGetAnimationTransform(layer->GetCompositorAnimationsId(), &transform);
+            SendGetAnimationValue(layer->GetCompositorAnimationsId(), &value);
         }
       } else if (WebRenderBridgeChild* wrbc = GetWebRenderBridge()) {
         RefPtr<WebRenderAnimationData> animationData =
             GetWebRenderUserData<WebRenderAnimationData>(frame, (uint32_t)DisplayItemType::TYPE_TRANSFORM);
         if (animationData) {
-          wrbc->SendGetAnimationTransform(
+          wrbc->SendGetAnimationValue(
               animationData->GetAnimationInfo().GetCompositorAnimationsId(),
-              &transform);
+              &value);
         }
       }
-      if (transform.type() == MaybeTransform::TMatrix4x4) {
-        Matrix4x4 matrix = transform.get_Matrix4x4();
-        cssValue = nsComputedDOMStyle::MatrixToCSSValue(matrix);
+      if (value.type() == OMTAValue::TMatrix4x4) {
+        cssValue = nsComputedDOMStyle::MatrixToCSSValue(value.get_Matrix4x4());
       }
     }
   }
 
   if (cssValue) {
     nsString text;
     ErrorResult rv;
     cssValue->GetCssText(text, rv);
--- a/gfx/layers/AnimationHelper.cpp
+++ b/gfx/layers/AnimationHelper.cpp
@@ -80,16 +80,57 @@ CompositorAnimationStorage::GetAnimation
     double(scale) / double(nsDeviceContext::AppUnitsPerCSSPixel());
   transform._41 *= devPerCss;
   transform._42 *= devPerCss;
   transform._43 *= devPerCss;
 
   return Some(transform);
 }
 
+OMTAValue
+CompositorAnimationStorage::GetOMTAValue(const uint64_t& aId) const
+{
+  OMTAValue omtaValue = mozilla::null_t();
+  auto animatedValue = GetAnimatedValue(aId);
+  if (!animatedValue) {
+    return omtaValue;
+  }
+
+  switch (animatedValue->mType) {
+    case AnimatedValue::OPACITY:
+      omtaValue = animatedValue->mOpacity;
+      break;
+    case AnimatedValue::TRANSFORM: {
+      gfx::Matrix4x4 transform = animatedValue->mTransform.mFrameTransform;
+      const TransformData& data = animatedValue->mTransform.mData;
+      float scale = data.appUnitsPerDevPixel();
+      gfx::Point3D transformOrigin = data.transformOrigin();
+
+      // Undo the rebasing applied by
+      // nsDisplayTransform::GetResultingTransformMatrixInternal
+      transform.ChangeBasis(-transformOrigin);
+
+      // Convert to CSS pixels (this undoes the operations performed by
+      // nsStyleTransformMatrix::ProcessTranslatePart which is called from
+      // nsDisplayTransform::GetResultingTransformMatrix)
+      double devPerCss =
+        double(scale) / double(nsDeviceContext::AppUnitsPerCSSPixel());
+      transform._41 *= devPerCss;
+      transform._42 *= devPerCss;
+      transform._43 *= devPerCss;
+      omtaValue = transform;
+      break;
+    }
+    case AnimatedValue::NONE:
+      break;
+  }
+
+  return omtaValue;
+}
+
 void
 CompositorAnimationStorage::SetAnimatedValue(uint64_t aId,
                                              gfx::Matrix4x4&& aTransformInDevSpace,
                                              gfx::Matrix4x4&& aFrameTransform,
                                              const TransformData& aData)
 {
   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   auto count = mAnimatedValues.Count();
--- a/gfx/layers/AnimationHelper.h
+++ b/gfx/layers/AnimationHelper.h
@@ -141,16 +141,18 @@ public:
   /**
    * Like GetAnimatedValue(), but ensures the value is a transform and returns
    * the transform matrix if possible, or Nothing() otherwise. It also does
    * some post-processing on the transform matrix as well. See the comments
    * inside the function for details.
    */
   Maybe<gfx::Matrix4x4> GetAnimationTransform(const uint64_t& aId) const;
 
+  OMTAValue GetOMTAValue(const uint64_t& aId) const;
+
   /**
    * Return the iterator of animated value table
    */
   AnimatedValueTable::Iterator ConstAnimatedValueTableIter() const
   {
     return mAnimatedValues.ConstIter();
   }
 
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -729,16 +729,39 @@ LayerTransactionParent::RecvGetAnimation
     *aTransform = *transform;
   } else {
     *aTransform = mozilla::void_t();
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
+LayerTransactionParent::RecvGetAnimationValue(const uint64_t& aCompositorAnimationsId,
+                                              OMTAValue* aValue)
+{
+  if (mDestroyed || !mLayerManager || mLayerManager->IsDestroyed()) {
+    return IPC_FAIL_NO_REASON(this);
+  }
+
+  // Make sure we apply the latest animation style or else we can end up with
+  // a race between when we temporarily clear the animation transform (in
+  // CompositorBridgeParent::SetShadowProperties) and when animation recalculates
+  // the value.
+  mCompositorBridge->ApplyAsyncProperties(
+    this, CompositorBridgeParentBase::TransformsToSkip::APZ);
+
+  if (!mAnimStorage) {
+    return IPC_FAIL_NO_REASON(this);
+  }
+
+  *aValue = mAnimStorage->GetOMTAValue(aCompositorAnimationsId);
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
 LayerTransactionParent::RecvGetTransform(const LayerHandle& aLayerHandle,
                                          MaybeTransform* aTransform)
 {
   if (mDestroyed || !mLayerManager || mLayerManager->IsDestroyed()) {
     return IPC_FAIL_NO_REASON(this);
   }
 
   Layer* layer = AsLayer(aLayerHandle);
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -125,16 +125,18 @@ protected:
   mozilla::ipc::IPCResult RecvScheduleComposite() override;
   mozilla::ipc::IPCResult RecvSetTestSampleTime(const TimeStamp& aTime) override;
   mozilla::ipc::IPCResult RecvLeaveTestMode() override;
   mozilla::ipc::IPCResult RecvGetAnimationOpacity(const uint64_t& aCompositorAnimationsId,
                                                   float* aOpacity,
                                                   bool* aHasAnimationOpacity) override;
   mozilla::ipc::IPCResult RecvGetAnimationTransform(const uint64_t& aCompositorAnimationsId,
                                                     MaybeTransform* aTransform) override;
+  mozilla::ipc::IPCResult RecvGetAnimationValue(const uint64_t& aCompositorAnimationsId,
+                                                OMTAValue* aValue) override;
   mozilla::ipc::IPCResult RecvGetTransform(const LayerHandle& aHandle,
                                            MaybeTransform* aTransform) override;
   mozilla::ipc::IPCResult RecvSetAsyncScrollOffset(const FrameMetrics::ViewID& aId,
                                                    const float& aX, const float& aY) override;
   mozilla::ipc::IPCResult RecvSetAsyncZoom(const FrameMetrics::ViewID& aId,
                                            const float& aValue) override;
   mozilla::ipc::IPCResult RecvFlushApzRepaints() override;
   mozilla::ipc::IPCResult RecvGetAPZTestData(APZTestData* aOutData) override;
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -565,10 +565,16 @@ struct TransactionInfo
   TimeStamp fwdTime;
 };
 
 union MaybeTransform {
   Matrix4x4;
   void_t;
 };
 
+union OMTAValue {
+  null_t;
+  float;
+  Matrix4x4;
+};
+
 } // namespace
 } // namespace
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -11,16 +11,17 @@ include protocol PCompositorBridge;
 include protocol PRenderFrame;
 include protocol PTexture;
 
 include "mozilla/GfxMessageUtils.h";
 include "mozilla/layers/LayersMessageUtils.h";
 
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
+using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
 using class mozilla::layers::APZTestData from "mozilla/layers/APZTestData.h";
 using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
 using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
 using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
 using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::LayerHandle from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::TransactionId from "mozilla/layers/LayersTypes.h";
@@ -70,16 +71,19 @@ 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();
 
+  // Returns |OMTAValue| applied to the layer.
+  sync GetAnimationValue(uint64_t aCompositorAnimationId) returns (OMTAValue value);
+
   // 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(uint64_t aCompositorAnimationsId) 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
--- a/gfx/layers/ipc/PWebRenderBridge.ipdl
+++ b/gfx/layers/ipc/PWebRenderBridge.ipdl
@@ -64,16 +64,17 @@ parent:
   sync SyncWithCompositor();
 
   // These correspond exactly to the equivalent APIs in PLayerTransaction -
   // see those for documentation.
   async SetConfirmedTargetAPZC(uint64_t aInputBlockId, ScrollableLayerGuid[] aTargets);
   // More copied from PLayerTransaction, but these are only used for testing.
   sync SetTestSampleTime(TimeStamp sampleTime);
   sync LeaveTestMode();
+  sync GetAnimationValue(uint64_t aCompositorAnimationsId) returns (OMTAValue value);
   sync GetAnimationOpacity(uint64_t aCompositorAnimationsId) returns (float opacity,
                                                   bool hasAnimationOpacity);
   sync GetAnimationTransform(uint64_t aCompositorAnimationId) returns (MaybeTransform transform);
   sync SetAsyncScrollOffset(ViewID scrollId, float x, float y);
   sync SetAsyncZoom(ViewID scrollId, float zoom);
   async FlushApzRepaints();
   sync GetAPZTestData() returns (APZTestData data);
 
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -1356,16 +1356,35 @@ WebRenderBridgeParent::RecvSetTestSample
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvLeaveTestMode()
 {
   mCompositorBridge->LeaveTestMode(GetLayersId());
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
+WebRenderBridgeParent::RecvGetAnimationValue(const uint64_t& aCompositorAnimationsId,
+                                             OMTAValue* aValue)
+{
+  if (mDestroyed) {
+    return IPC_FAIL_NO_REASON(this);
+  }
+
+  MOZ_ASSERT(mAnimStorage);
+  if (RefPtr<WebRenderBridgeParent> root = GetRootWebRenderBridgeParent()) {
+    root->AdvanceAnimations();
+  } else {
+    AdvanceAnimations();
+  }
+
+  *aValue = mAnimStorage->GetOMTAValue(aCompositorAnimationsId);
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvGetAnimationOpacity(const uint64_t& aCompositorAnimationsId,
                                                float* aOpacity,
                                                bool* aHasAnimationOpacity)
 {
   if (mDestroyed) {
     return IPC_FAIL_NO_REASON(this);
   }
 
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -113,16 +113,18 @@ public:
   mozilla::ipc::IPCResult RecvCapture() override;
   mozilla::ipc::IPCResult RecvSyncWithCompositor() override;
 
   mozilla::ipc::IPCResult RecvSetConfirmedTargetAPZC(const uint64_t& aBlockId,
                                                      nsTArray<ScrollableLayerGuid>&& aTargets) override;
 
   mozilla::ipc::IPCResult RecvSetTestSampleTime(const TimeStamp& aTime) override;
   mozilla::ipc::IPCResult RecvLeaveTestMode() override;
+  mozilla::ipc::IPCResult RecvGetAnimationValue(const uint64_t& aCompositorAnimationsId,
+                                                OMTAValue* aValue) override;
   mozilla::ipc::IPCResult RecvGetAnimationOpacity(const uint64_t& aCompositorAnimationsId,
                                                   float* aOpacity,
                                                   bool* aHasAnimationOpacity) override;
   mozilla::ipc::IPCResult RecvGetAnimationTransform(const uint64_t& aCompositorAnimationsId,
                                                     MaybeTransform* aTransform) override;
   mozilla::ipc::IPCResult RecvSetAsyncScrollOffset(const FrameMetrics::ViewID& aScrollId,
                                                    const float& aX,
                                                    const float& aY) override;
--- a/ipc/ipdl/sync-messages.ini
+++ b/ipc/ipdl/sync-messages.ini
@@ -994,16 +994,18 @@ description =
 [PLayerTransaction::SetTestSampleTime]
 description =
 [PLayerTransaction::LeaveTestMode]
 description =
 [PLayerTransaction::GetAnimationOpacity]
 description =
 [PLayerTransaction::GetAnimationTransform]
 description =
+[PLayerTransaction::GetAnimationValue]
+description = test only
 [PLayerTransaction::GetTransform]
 description = test only
 [PLayerTransaction::SetAsyncScrollOffset]
 description =
 [PLayerTransaction::SetAsyncZoom]
 description =
 [PLayerTransaction::GetAPZTestData]
 description =
@@ -1020,16 +1022,18 @@ description =
 [PWebRenderBridge::Create]
 description =
 [PWebRenderBridge::GetSnapshot]
 description =
 [PWebRenderBridge::SetTestSampleTime]
 description = test only
 [PWebRenderBridge::LeaveTestMode]
 description = test only
+[PWebRenderBridge::GetAnimationValue]
+description = test only
 [PWebRenderBridge::GetAnimationOpacity]
 description = test only
 [PWebRenderBridge::GetAnimationTransform]
 description = test only
 [PWebRenderBridge::SetAsyncScrollOffset]
 description = test only
 [PWebRenderBridge::SetAsyncZoom]
 description = test only