Bug 1358437 - pass layer's transform attributes for transform animation, r?kats draft
authorpeter chang <pchang@mozilla.com>
Mon, 17 Apr 2017 11:35:42 +0800
changeset 570179 80ed5dd93c302d9d0cdc44b3b52cf15763f4740f
parent 570178 d6ab3225f07cbc6a01db0e2d3e5e9664f8bc470c
child 570180 6e49bcb1e885b0eb6c03179ab53ac4b1359bea5f
push id56417
push userbmo:howareyou322@gmail.com
push dateFri, 28 Apr 2017 13:34:36 +0000
reviewerskats
bugs1358437
milestone55.0a1
Bug 1358437 - pass layer's transform attributes for transform animation, r?kats MozReview-Commit-ID: J7JHuwvWuet
gfx/layers/AnimationHelper.cpp
gfx/layers/ipc/LayersMessages.ipdlh
gfx/layers/wr/WebRenderContainerLayer.cpp
gfx/layers/wr/WebRenderContainerLayer.h
layout/painting/nsDisplayList.cpp
--- a/gfx/layers/AnimationHelper.cpp
+++ b/gfx/layers/AnimationHelper.cpp
@@ -535,31 +535,28 @@ AnimationHelper::SampleAnimations(Compos
         nsDisplayTransform::FrameTransformProperties props(list,
                                                            transformOrigin);
 
         gfx::Matrix4x4 transform =
           nsDisplayTransform::GetResultingTransformMatrix(props, origin,
                                                           transformData.appUnitsPerDevPixel(),
                                                           0, &transformData.bounds());
         gfx::Matrix4x4 frameTransform = transform;
-
-        //TODO how do we support this without layer information
-        // If our parent layer is a perspective layer, then the offset into reference
-        // frame coordinates is already on that layer. If not, then we need to ask
+        // If the parent has perspective transform, then the offset into reference
+        // frame coordinates is already on this transform. If not, then we need to ask
         // for it to be added here.
-        // if (!aLayer->GetParent() ||
-        //     !aLayer->GetParent()->GetTransformIsPerspective()) {
-        //   nsLayoutUtils::PostTranslate(transform, origin,
-        //                                transformData.appUnitsPerDevPixel(),
-        //                                true);
-        // }
+        if (!transformData.hasPerspectiveParent()) {
+           nsLayoutUtils::PostTranslate(transform, origin,
+                                        transformData.appUnitsPerDevPixel(),
+                                        true);
+        }
 
-        // if (ContainerLayer* c = aLayer->AsContainerLayer()) {
-        //   transform.PostScale(c->GetInheritedXScale(), c->GetInheritedYScale(), 1);
-        // }
+        transform.PostScale(transformData.inheritedXScale(),
+                            transformData.inheritedYScale(),
+                            1);
 
         aStorage->SetAnimatedValue(iter.Key(),
                                    Move(transform), Move(frameTransform),
                                    transformData);
         break;
       }
       default:
         MOZ_ASSERT_UNREACHABLE("Unhandled animated property");
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -182,16 +182,21 @@ struct AnimationSegment {
 // functions to a Matrix4x4 that can be applied directly to the layer.
 struct TransformData {
   // the origin of the frame being transformed in app units
   nsPoint origin;
   // the transform-origin property for the transform in device pixels
   Point3D transformOrigin;
   nsRect bounds;
   int32_t appUnitsPerDevPixel;
+  // The resolution scale inherited from the parent
+  float inheritedXScale;
+  float inheritedYScale;
+  // True if the parent has perspective transform
+  bool hasPerspectiveParent;
 };
 
 union AnimationData {
   null_t;
   TransformData;
 };
 
 struct Animation {
--- a/gfx/layers/wr/WebRenderContainerLayer.cpp
+++ b/gfx/layers/wr/WebRenderContainerLayer.cpp
@@ -23,42 +23,58 @@ WebRenderContainerLayer::ClearAnimations
     mManager->AsWebRenderLayerManager()->
       AddCompositorAnimationsIdForDiscard(GetCompositorAnimationsId());
   }
 
   Layer::ClearAnimations();
 }
 
 void
+WebRenderContainerLayer::UpdateTransformDataForAnimation()
+{
+  for(Animation& animation : mAnimations) {
+    if (animation.property() == eCSSProperty_transform) {
+      TransformData& transformData = animation.data().get_TransformData();
+      transformData.inheritedXScale() = GetInheritedXScale();
+      transformData.inheritedYScale() = GetInheritedYScale();
+      if (GetParent() && GetParent()->GetTransformIsPerspective()) {
+        transformData.hasPerspectiveParent() = true;
+      }
+    }
+  }
+}
+
+void
 WebRenderContainerLayer::RenderLayer(wr::DisplayListBuilder& aBuilder)
 {
   nsTArray<LayerPolygon> children = SortChildrenBy3DZOrder(SortMode::WITHOUT_GEOMETRY);
 
   gfx::Matrix4x4 transform = GetTransform();
   gfx::Matrix4x4* maybeTransform = &transform;
   float opacity = GetLocalOpacity();
   float* maybeOpacity = &opacity;
   uint64_t animationsId = 0;
 
   if (gfxPrefs::WebRenderOMTAEnabled() &&
       !GetAnimations().IsEmpty()) {
     MOZ_ASSERT(GetCompositorAnimationsId());
 
+    if (!HasOpacityAnimation()) {
+      maybeOpacity = nullptr;
+    }
+    if (!HasTransformAnimation()) {
+      maybeTransform = nullptr;
+      UpdateTransformDataForAnimation();
+    }
+
     animationsId = GetCompositorAnimationsId();
     CompositorAnimations anim;
     anim.animations() = GetAnimations();
     anim.id() = animationsId;
     WrBridge()->AddWebRenderParentCommand(OpAddCompositorAnimations(anim));
-
-    if (!HasOpacityAnimation()) {
-      maybeOpacity = nullptr;
-    }
-    if (!HasTransformAnimation()) {
-      maybeTransform = nullptr;
-    }
   }
 
   StackingContextHelper sc(aBuilder, this, animationsId, maybeOpacity, maybeTransform);
 
   LayerRect rect = Bounds();
   DumpLayerInfo("ContainerLayer", rect);
 
   Maybe<WrImageMask> mask = BuildWrMaskLayer(true);
--- a/gfx/layers/wr/WebRenderContainerLayer.h
+++ b/gfx/layers/wr/WebRenderContainerLayer.h
@@ -33,16 +33,18 @@ protected:
       mManager->AsWebRenderLayerManager()->
         AddCompositorAnimationsIdForDiscard(GetCompositorAnimationsId());
     }
 
     ContainerLayer::RemoveAllChildren();
     MOZ_COUNT_DTOR(WebRenderContainerLayer);
   }
 
+  void UpdateTransformDataForAnimation();
+
 public:
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder) override;
 
   void ClearAnimations() override;
   virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) override
   {
     DefaultComputeEffectiveTransforms(aTransformToSurface);
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -818,33 +818,37 @@ nsDisplayListBuilder::AddAnimationsAndTr
     TransformReferenceBox refBox(aFrame);
     nsRect bounds(0, 0, refBox.Width(), refBox.Height());
     // all data passed directly to the compositor should be in dev pixels
     int32_t devPixelsToAppUnits = aFrame->PresContext()->AppUnitsPerDevPixel();
     float scale = devPixelsToAppUnits;
     Point3D offsetToTransformOrigin =
       nsDisplayTransform::GetDeltaToTransformOrigin(aFrame, scale, &bounds);
     nsPoint origin;
+    float scaleX = 1.0f;
+    float scaleY = 1.0f;
+    bool hasPerspectiveParent = false;
     if (aItem) {
       // This branch is for display items to leverage the cache of
       // nsDisplayListBuilder.
       origin = aItem->ToReferenceFrame();
     } else {
       // This branch is running for restyling.
       // Animations are animated at the coordination of the reference
       // frame outside, not the given frame itself.  The given frame
       // is also reference frame too, so the parent's reference frame
       // are used.
       nsIFrame* referenceFrame =
         nsLayoutUtils::GetReferenceFrame(nsLayoutUtils::GetCrossDocParentFrame(aFrame));
       origin = aFrame->GetOffsetToCrossDoc(referenceFrame);
     }
 
     data = TransformData(origin, offsetToTransformOrigin,
-                         bounds, devPixelsToAppUnits);
+                         bounds, devPixelsToAppUnits,
+                         scaleX, scaleY, hasPerspectiveParent);
   } else if (aProperty == eCSSProperty_opacity) {
     data = null_t();
   }
 
   AddAnimationsForProperty(aFrame, aProperty, compositorAnimations,
                            aLayer, data, pending);
 }