Bug 1426386 - Split the transform sent to webrender back into the transform and positioning components. r?mstange draft
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 22 Jan 2018 12:00:30 -0500
changeset 723207 eb4799acfedb530dceb5a35fe627b4b323382b1f
parent 723206 4bf3964f6129d42da6fcf6b9c7d61d6e07697c79
child 723208 793731d5ee441adf52ba50fbb3650d78c743abfd
push id96365
push userkgupta@mozilla.com
push dateMon, 22 Jan 2018 18:40:44 +0000
reviewersmstange
bugs1426386
milestone60.0a1
Bug 1426386 - Split the transform sent to webrender back into the transform and positioning components. r?mstange MozReview-Commit-ID: XHqgYPwjZ0
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
layout/reftests/bugs/reftest.list
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -605,17 +605,18 @@ AddAnimationForProperty(nsIFrame* aFrame
       static_cast<uint8_t>(segment.mToComposite);
     animSegment->sampleFn() = ToTimingFunction(segment.mTimingFunction);
   }
 }
 
 static void
 AddAnimationsForProperty(nsIFrame* aFrame, nsDisplayListBuilder* aBuilder,
                          nsDisplayItem* aItem, nsCSSPropertyID aProperty,
-                         AnimationInfo& aAnimationInfo, bool aPending)
+                         AnimationInfo& aAnimationInfo, bool aPending,
+                         bool aIsForWebRender)
 {
   if (aPending) {
     aAnimationInfo.ClearAnimationsForNextTransaction();
   } else {
     aAnimationInfo.ClearAnimations();
   }
 
   // Update the animation generation on the layer. We need to do this before
@@ -662,17 +663,21 @@ AddAnimationsForProperty(nsIFrame* aFram
     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) {
+    if (aIsForWebRender) {
+      // leave origin empty, because we are sending it separately on the stacking
+      // context that we are pushing to WR, and WR will automatically include
+      // it when picking up the animated transform values
+    } else 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
@@ -840,17 +845,17 @@ nsDisplayListBuilder::AddAnimationsAndTr
   if (!(backend == layers::LayersBackend::LAYERS_CLIENT ||
         backend == layers::LayersBackend::LAYERS_WR)) {
     return;
   }
 
   bool pending = !aBuilder;
   AnimationInfo& animationInfo = aLayer->GetAnimationInfo();
   AddAnimationsForProperty(aFrame, aBuilder, aItem, aProperty,
-                           animationInfo, pending);
+                           animationInfo, pending, false);
   animationInfo.TransferMutatedFlagToLayer(aLayer);
 }
 
 nsDisplayItem*
 nsDisplayListBuilder::MergeItems(nsTArray<nsDisplayItem*>& aMergedItems)
 {
   // For merging, we create a temporary item by cloning the last item of the
   // mergeable items list. This ensures that the temporary item will have the
@@ -6667,17 +6672,17 @@ nsDisplayOpacity::CreateWebRenderCommand
                                           nsDisplayListBuilder* aDisplayListBuilder)
 {
   float* opacityForSC = &mOpacity;
 
   RefPtr<WebRenderAnimationData> animationData = aManager->CommandBuilder().CreateOrRecycleWebRenderUserData<WebRenderAnimationData>(this);
   AnimationInfo& animationInfo = animationData->GetAnimationInfo();
   AddAnimationsForProperty(Frame(), aDisplayListBuilder,
                            this, eCSSProperty_opacity,
-                           animationInfo, false);
+                           animationInfo, false, true);
   animationInfo.StartPendingAnimations(aManager->GetAnimationReadyTime());
 
   // Note that animationsId can be 0 (uninitialized in AnimationInfo) if there
   // are no active animations.
   uint64_t animationsId = animationInfo.GetCompositorAnimationsId();
   wr::WrAnimationProperty prop;
 
   if (!animationInfo.GetAnimations().IsEmpty()) {
@@ -8418,19 +8423,28 @@ nsDisplayTransform::GetTransform() const
         GetResultingTransformMatrix(mFrame, ToReferenceFrame(),
                                     scale, INCLUDE_PERSPECTIVE|OFFSET_BY_ORIGIN);
     }
   }
   return mTransform;
 }
 
 Matrix4x4
-nsDisplayTransform::GetTransformForRendering()
+nsDisplayTransform::GetTransformForRendering(LayoutDevicePoint* aOutOrigin)
 {
   if (!mFrame->HasPerspective() || mTransformGetter || mIsTransformSeparator) {
+    if (!mTransformGetter && !mIsTransformSeparator && aOutOrigin) {
+      // If aOutOrigin is provided, put the offset to origin into it, because
+      // we need to keep it separate for webrender. The combination of
+      // *aOutOrigin and the returned matrix here should always be equivalent
+      // to what GetTransform() would have returned.
+      float scale = mFrame->PresContext()->AppUnitsPerDevPixel();
+      *aOutOrigin = LayoutDevicePoint::FromAppUnits(ToReferenceFrame(), scale);
+      return GetResultingTransformMatrix(mFrame, nsPoint(0, 0), scale, INCLUDE_PERSPECTIVE);
+    }
     return GetTransform();
   }
   MOZ_ASSERT(!mTransformGetter);
 
   float scale = mFrame->PresContext()->AppUnitsPerDevPixel();
   // Don't include perspective transform, or the offset to origin, since
   // nsDisplayPerspective will handle both of those.
   return GetResultingTransformMatrix(mFrame, ToReferenceFrame(), scale, 0);
@@ -8476,31 +8490,38 @@ nsDisplayTransform::ShouldBuildLayerEven
 
 bool
 nsDisplayTransform::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                             mozilla::wr::IpcResourceUpdateQueue& aResources,
                                             const StackingContextHelper& aSc,
                                             WebRenderLayerManager* aManager,
                                             nsDisplayListBuilder* aDisplayListBuilder)
 {
-  Matrix4x4 newTransformMatrix = GetTransformForRendering();
+  // We want to make sure we don't pollute the transform property in the WR
+  // stacking context by including the position of this frame (relative to the
+  // parent reference frame). We need to keep those separate; the position of
+  // this frame goes into the stacking context bounds while the transform goes
+  // into the transform.
+  LayoutDevicePoint position;
+  Matrix4x4 newTransformMatrix = GetTransformForRendering(&position);
+
   gfx::Matrix4x4* transformForSC = &newTransformMatrix;
   if (newTransformMatrix.IsIdentity()) {
     // If the transform is an identity transform, strip it out so that WR
     // doesn't turn this stacking context into a reference frame, as it
     // affects positioning. Bug 1345577 tracks a better fix.
     transformForSC = nullptr;
   }
 
   RefPtr<WebRenderAnimationData> animationData = aManager->CommandBuilder().CreateOrRecycleWebRenderUserData<WebRenderAnimationData>(this);
 
   AnimationInfo& animationInfo = animationData->GetAnimationInfo();
   AddAnimationsForProperty(Frame(), aDisplayListBuilder,
                            this, eCSSProperty_transform,
-                           animationInfo, false);
+                           animationInfo, false, true);
   animationInfo.StartPendingAnimations(aManager->GetAnimationReadyTime());
 
   // Note that animationsId can be 0 (uninitialized in AnimationInfo) if there
   // are no active animations.
   uint64_t animationsId = animationInfo.GetCompositorAnimationsId();
   wr::WrAnimationProperty prop;
   if (!animationInfo.GetAnimations().IsEmpty()) {
     // Update transfrom as nullptr in stacking context if there exists
@@ -8524,17 +8545,17 @@ nsDisplayTransform::CreateWebRenderComma
     aManager->AddCompositorAnimationsIdForDiscard(animationsId);
     animationsId = 0;
   }
 
   nsTArray<mozilla::wr::WrFilterOp> filters;
   StackingContextHelper sc(aSc,
                            aBuilder,
                            filters,
-                           LayoutDeviceRect(),
+                           LayoutDeviceRect(position, LayoutDeviceSize()),
                            &newTransformMatrix,
                            animationsId ? &prop : nullptr,
                            nullptr,
                            transformForSC,
                            nullptr,
                            gfx::CompositionOp::OP_OVER,
                            !BackfaceIsHidden(),
                            mFrame->Extend3DContext() && !mNoExtendContext);
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -6150,17 +6150,17 @@ public:
 
   /**
    * We include the perspective matrix from our containing block for the
    * purposes of visibility calculations, but we exclude it from the transform
    * we set on the layer (for rendering), since there will be an
    * nsDisplayPerspective created for that.
    */
   const Matrix4x4& GetTransform() const;
-  Matrix4x4 GetTransformForRendering();
+  Matrix4x4 GetTransformForRendering(mozilla::LayoutDevicePoint* aOutOrigin = nullptr);
 
   /**
    * Return the transform that is aggregation of all transform on the
    * preserves3d chain.
    */
   const Matrix4x4& GetAccumulatedPreserved3DTransform(nsDisplayListBuilder* aBuilder);
 
   float GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder, const nsPoint& aPoint);
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1856,17 +1856,17 @@ pref(layout.css.moz-document.content.ena
 == 1059498-1.html 1059498-1-ref.html
 == 1059498-2.html 1059498-1-ref.html
 == 1059498-3.html 1059498-1-ref.html
 == 1062108-1.html 1062108-1-ref.html
 == 1062792-1.html 1062792-1-ref.html
 == 1062963-floatmanager-reflow.html 1062963-floatmanager-reflow-ref.html
 test-pref(dom.webcomponents.shadowdom.enabled,true) == 1066554-1.html 1066554-1-ref.html
 == 1069716-1.html 1069716-1-ref.html
-fails-if(webrender) == 1078262-1.html about:blank
+== 1078262-1.html about:blank
 test-pref(layout.testing.overlay-scrollbars.always-visible,false) == 1081072-1.html 1081072-1-ref.html
 == 1081185-1.html 1081185-1-ref.html
 == 1097437-1.html 1097437-1-ref.html
 == 1103258-1.html 1103258-1-ref.html # assertion crash test with layers culling test
 == 1105137-1.html 1105137-1-ref.html
 fuzzy-if(d2d,36,304) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)&&d2d,127,701) == 1116480-1-fakeitalic-overflow.html 1116480-1-fakeitalic-overflow-ref.html
 == 1111753-1.html about:blank
 == 1114526-1.html 1114526-1-ref.html