Bug 1511042 - Back out some commits from bug 1503447 for introducing correctness and perf regressions. r=backout
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 29 Nov 2018 14:22:37 -0500
changeset 448751 9358169404d156136a8fe82ef43fb78523123cc1
parent 448750 e9a34518f07892f8c5c26064fd8c3348911e523d
child 448752 82bbee36c7dc5273252d761b6ec66da6f2b0ead5
push id110251
push userkgupta@mozilla.com
push dateThu, 29 Nov 2018 19:26:49 +0000
treeherdermozilla-inbound@9358169404d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1511042, 1503447
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1511042 - Back out some commits from bug 1503447 for introducing correctness and perf regressions. r=backout This backs out hg commits 1e214baf8fc1, 7d4adeee5236, and f5ffebdcc014.
gfx/layers/ipc/WebRenderMessages.ipdlh
gfx/layers/wr/AsyncImagePipelineManager.cpp
gfx/layers/wr/AsyncImagePipelineManager.h
gfx/layers/wr/ClipManager.cpp
gfx/layers/wr/StackingContextHelper.cpp
gfx/layers/wr/StackingContextHelper.h
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderCommandBuilder.cpp
gfx/layers/wr/WebRenderUserData.cpp
gfx/layers/wr/WebRenderUserData.h
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi_generated.h
layout/base/nsLayoutUtils.h
layout/generic/nsHTMLCanvasFrame.cpp
layout/painting/nsDisplayList.cpp
layout/reftests/bugs/reftest.list
layout/reftests/svg/conditions-07.svg
--- a/gfx/layers/ipc/WebRenderMessages.ipdlh
+++ b/gfx/layers/ipc/WebRenderMessages.ipdlh
@@ -21,17 +21,16 @@ using mozilla::wr::MaybeFontInstanceOpti
 using mozilla::wr::MaybeFontInstancePlatformOptions from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::FontInstanceKey from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::FontKey from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::ImageKey from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::BlobImageKey from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::PipelineId from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::gfx::MaybeIntSize from "mozilla/gfx/Point.h";
 using mozilla::LayoutDeviceRect from "Units.h";
-using mozilla::LayoutDeviceSize from "Units.h";
 using mozilla::ImageIntRect from "Units.h";
 using mozilla::gfx::Rect from "mozilla/gfx/Rect.h";
 using class mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 
 namespace mozilla {
 namespace layers {
 
@@ -76,17 +75,17 @@ struct OpRemovePipelineIdForCompositable
 };
 
 struct OpReleaseTextureOfImage {
   ImageKey key;
 };
 
 struct OpUpdateAsyncImagePipeline {
   PipelineId pipelineId;
-  LayoutDeviceSize scSize;
+  LayoutDeviceRect scBounds;
   Matrix4x4 scTransform;
   MaybeIntSize scaleToSize;
   ImageRendering filter;
   MixBlendMode mixBlendMode;
 };
 
 struct OpUpdatedAsyncImagePipeline {
   PipelineId pipelineId;
--- a/gfx/layers/wr/AsyncImagePipelineManager.cpp
+++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ -190,31 +190,31 @@ AsyncImagePipelineManager::RemoveAsyncIm
     }
     entry.Remove();
     RemovePipeline(aPipelineId, epoch);
   }
 }
 
 void
 AsyncImagePipelineManager::UpdateAsyncImagePipeline(const wr::PipelineId& aPipelineId,
-                                                    const LayoutDeviceSize& aSize,
+                                                    const LayoutDeviceRect& aScBounds,
                                                     const gfx::Matrix4x4& aScTransform,
                                                     const gfx::MaybeIntSize& aScaleToSize,
                                                     const wr::ImageRendering& aFilter,
                                                     const wr::MixBlendMode& aMixBlendMode)
 {
   if (mDestroyed) {
     return;
   }
   AsyncImagePipeline* pipeline = mAsyncImagePipelines.Get(wr::AsUint64(aPipelineId));
   if (!pipeline) {
     return;
   }
   pipeline->mInitialised = true;
-  pipeline->Update(aSize,
+  pipeline->Update(aScBounds,
                    aScTransform,
                    aScaleToSize,
                    aFilter,
                    aMixBlendMode);
 }
 
 Maybe<TextureHost::ResourceUpdateOp>
 AsyncImagePipelineManager::UpdateImageKeys(const wr::Epoch& aEpoch,
@@ -412,20 +412,23 @@ AsyncImagePipelineManager::ApplyAsyncIma
     aSceneBuilderTxn.UpdateEpoch(aPipelineId, aEpoch);
     if (aPipeline->mCurrentTexture) {
       HoldExternalImage(aPipelineId, aEpoch, aPipeline->mCurrentTexture->AsWebRenderTextureHost());
     }
     return;
   }
 
   aPipeline->mIsChanged = false;
-  wr::DisplayListBuilder builder(aPipelineId, wr::ToLayoutSize(aPipeline->mSize));
+
+  wr::LayoutSize contentSize { aPipeline->mScBounds.Width(), aPipeline->mScBounds.Height() };
+  wr::DisplayListBuilder builder(aPipelineId, contentSize);
 
   float opacity = 1.0f;
   Maybe<wr::WrClipId> referenceFrameId = builder.PushStackingContext(
+    wr::ToRoundedLayoutRect(aPipeline->mScBounds),
     nullptr,
     nullptr,
     &opacity,
     aPipeline->mScTransform.IsIdentity() ? nullptr : &aPipeline->mScTransform,
     wr::TransformStyle::Flat,
     nullptr,
     aPipeline->mMixBlendMode,
     nsTArray<wr::WrFilterOp>(),
@@ -461,17 +464,17 @@ AsyncImagePipelineManager::ApplyAsyncIma
   builder.PopStackingContext(referenceFrameId.isSome());
 
   wr::BuiltDisplayList dl;
   wr::LayoutSize builderContentSize;
   builder.Finalize(builderContentSize, dl);
   aSceneBuilderTxn.SetDisplayList(
     gfx::Color(0.f, 0.f, 0.f, 0.f),
     aEpoch,
-    aPipeline->mSize,
+    LayerSize(aPipeline->mScBounds.Width(), aPipeline->mScBounds.Height()),
     aPipelineId, builderContentSize,
     dl.dl_desc, dl.dl);
 }
 
 void
 AsyncImagePipelineManager::ApplyAsyncImageForPipeline(const wr::PipelineId& aPipelineId,
                                                       wr::TransactionBuilder& aTxn,
                                                       wr::TransactionBuilder& aTxnForImageBridge)
@@ -508,27 +511,27 @@ AsyncImagePipelineManager::SetEmptyDispl
   if (!pipeline) {
     return;
   }
 
   // Transaction for async image pipeline that uses ImageBridge always need to be non low priority.
   auto& txn = pipeline->mImageHost->GetAsyncRef() ? aTxnForImageBridge : aTxn;
 
   wr::Epoch epoch = GetNextImageEpoch();
-  wr::DisplayListBuilder builder(aPipelineId, wr::ToLayoutSize(pipeline->mSize));
+  wr::LayoutSize contentSize { pipeline->mScBounds.Width(), pipeline->mScBounds.Height() };
+  wr::DisplayListBuilder builder(aPipelineId, contentSize);
 
   wr::BuiltDisplayList dl;
   wr::LayoutSize builderContentSize;
   builder.Finalize(builderContentSize, dl);
-  txn.SetDisplayList(
-    gfx::Color(0.f, 0.f, 0.f, 0.f),
-    epoch,
-    pipeline->mSize,
-    aPipelineId, builderContentSize,
-    dl.dl_desc, dl.dl);
+  txn.SetDisplayList(gfx::Color(0.f, 0.f, 0.f, 0.f),
+                     epoch,
+                     LayerSize(pipeline->mScBounds.Width(), pipeline->mScBounds.Height()),
+                     aPipelineId, builderContentSize,
+                     dl.dl_desc, dl.dl);
 }
 
 void
 AsyncImagePipelineManager::HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, WebRenderTextureHost* aTexture)
 {
   if (mDestroyed) {
     return;
   }
--- a/gfx/layers/wr/AsyncImagePipelineManager.h
+++ b/gfx/layers/wr/AsyncImagePipelineManager.h
@@ -84,17 +84,17 @@ public:
     return mCompositeUntilTime;
   }
 
   void AddAsyncImagePipeline(const wr::PipelineId& aPipelineId, WebRenderImageHost* aImageHost);
   void RemoveAsyncImagePipeline(const wr::PipelineId& aPipelineId,
                                 wr::TransactionBuilder& aTxn);
 
   void UpdateAsyncImagePipeline(const wr::PipelineId& aPipelineId,
-                                const LayoutDeviceSize& aSize,
+                                const LayoutDeviceRect& aScBounds,
                                 const gfx::Matrix4x4& aScTransform,
                                 const gfx::MaybeIntSize& aScaleToSize,
                                 const wr::ImageRendering& aFilter,
                                 const wr::MixBlendMode& aMixBlendMode);
   void ApplyAsyncImagesOfImageBridge(wr::TransactionBuilder& aSceneBuilderTxn, wr::TransactionBuilder& aFastTxn);
   void ApplyAsyncImageForPipeline(const wr::PipelineId& aPipelineId, wr::TransactionBuilder& aTxn, wr::TransactionBuilder& aTxnForImageBridge);
 
   void SetEmptyDisplayList(const wr::PipelineId& aPipelineId,
@@ -165,38 +165,38 @@ private:
     std::queue<ForwardingTextureHostWrapper> mTextureHostWrappers;
     std::queue<UniquePtr<ForwardingExternalImage>> mExternalImages;
     Maybe<wr::Epoch> mDestroyedEpoch;
     WebRenderBridgeParent* MOZ_NON_OWNING_REF mWrBridge = nullptr;
   };
 
   struct AsyncImagePipeline {
     AsyncImagePipeline();
-    void Update(const LayoutDeviceSize& aSize,
+    void Update(const LayoutDeviceRect& aScBounds,
                 const gfx::Matrix4x4& aScTransform,
                 const gfx::MaybeIntSize& aScaleToSize,
                 const wr::ImageRendering& aFilter,
                 const wr::MixBlendMode& aMixBlendMode)
     {
-      mIsChanged |= mSize != aSize ||
+      mIsChanged |= !mScBounds.IsEqualEdges(aScBounds) ||
                     mScTransform != aScTransform ||
                     mScaleToSize != aScaleToSize ||
                     mFilter != aFilter ||
                     mMixBlendMode != aMixBlendMode;
-      mSize = aSize;
+      mScBounds = aScBounds;
       mScTransform = aScTransform;
       mScaleToSize = aScaleToSize;
       mFilter = aFilter;
       mMixBlendMode = aMixBlendMode;
     }
 
     bool mInitialised;
     bool mIsChanged;
     bool mUseExternalImage;
-    LayoutDeviceSize mSize;
+    LayoutDeviceRect mScBounds;
     gfx::Matrix4x4 mScTransform;
     gfx::MaybeIntSize mScaleToSize;
     wr::ImageRendering mFilter;
     wr::MixBlendMode mMixBlendMode;
     RefPtr<WebRenderImageHost> mImageHost;
     CompositableTextureHostRef mCurrentTexture;
     RefPtr<WebRenderTextureHostWrapper> mWrTextureWrapper;
     nsTArray<wr::ImageKey> mKeys;
--- a/gfx/layers/wr/ClipManager.cpp
+++ b/gfx/layers/wr/ClipManager.cpp
@@ -56,39 +56,49 @@ ClipManager::EndBuild()
   MOZ_ASSERT(mCacheStack.empty());
   MOZ_ASSERT(mASROverride.empty());
   MOZ_ASSERT(mItemClipStack.empty());
 }
 
 void
 ClipManager::BeginList(const StackingContextHelper& aStackingContext)
 {
-  if (aStackingContext.ReferenceFrameId()) {
-    PushOverrideForASR(
-        mItemClipStack.empty() ? nullptr : mItemClipStack.top().mASR,
-        aStackingContext.ReferenceFrameId().ref());
+  if (aStackingContext.AffectsClipPositioning()) {
+    if (aStackingContext.ReferenceFrameId()) {
+      PushOverrideForASR(
+          mItemClipStack.empty() ? nullptr : mItemClipStack.top().mASR,
+          aStackingContext.ReferenceFrameId().ref());
+    } else {
+      // Start a new cache
+      mCacheStack.emplace();
+    }
   }
 
   ItemClips clips(nullptr, nullptr, false);
   if (!mItemClipStack.empty()) {
     clips.CopyOutputsFrom(mItemClipStack.top());
   }
   mItemClipStack.push(clips);
 }
 
 void
 ClipManager::EndList(const StackingContextHelper& aStackingContext)
 {
   MOZ_ASSERT(!mItemClipStack.empty());
   mItemClipStack.top().Unapply(mBuilder);
   mItemClipStack.pop();
 
-  if (aStackingContext.ReferenceFrameId()) {
-    PopOverrideForASR(
+  if (aStackingContext.AffectsClipPositioning()) {
+    if (aStackingContext.ReferenceFrameId()) {
+      PopOverrideForASR(
         mItemClipStack.empty() ? nullptr : mItemClipStack.top().mASR);
+    } else {
+      MOZ_ASSERT(!mCacheStack.empty());
+      mCacheStack.pop();
+    }
   }
 }
 
 void
 ClipManager::PushOverrideForASR(const ActiveScrolledRoot* aASR,
                                 const wr::WrClipId& aClipId)
 {
   Maybe<wr::WrClipId> scrollId = GetScrollLayer(aASR);
--- a/gfx/layers/wr/StackingContextHelper.cpp
+++ b/gfx/layers/wr/StackingContextHelper.cpp
@@ -10,49 +10,45 @@
 #include "nsDisplayList.h"
 
 namespace mozilla {
 namespace layers {
 
 StackingContextHelper::StackingContextHelper()
   : mBuilder(nullptr)
   , mScale(1.0f, 1.0f)
+  , mAffectsClipPositioning(false)
   , mIsPreserve3D(false)
   , mRasterizeLocally(false)
 {
   // mOrigin remains at 0,0
 }
 
 StackingContextHelper::StackingContextHelper(const StackingContextHelper& aParentSC,
                                              const ActiveScrolledRoot* aAsr,
                                              wr::DisplayListBuilder& aBuilder,
                                              const nsTArray<wr::WrFilterOp>& aFilters,
+                                             const LayoutDeviceRect& aBounds,
                                              const gfx::Matrix4x4* aBoundTransform,
                                              const wr::WrAnimationProperty* aAnimation,
                                              const float* aOpacityPtr,
-                                             const LayoutDevicePoint& aOrigin,
                                              const gfx::Matrix4x4* aTransformPtr,
                                              const gfx::Matrix4x4* aPerspectivePtr,
                                              const gfx::CompositionOp& aMixBlendMode,
                                              bool aBackfaceVisible,
                                              bool aIsPreserve3D,
                                              const Maybe<nsDisplayTransform*>& aDeferredTransformItem,
                                              const wr::WrClipId* aClipNodeId,
                                              bool aAnimated)
   : mBuilder(&aBuilder)
   , mScale(1.0f, 1.0f)
-  , mInheritedStickyOrigin(aOrigin)
   , mDeferredTransformItem(aDeferredTransformItem)
   , mIsPreserve3D(aIsPreserve3D)
   , mRasterizeLocally(aAnimated || aParentSC.mRasterizeLocally)
 {
-  if (aOrigin != LayoutDevicePoint()) {
-    mOriginFrameId = Some(mBuilder->PushOrigin(wr::ToLayoutPoint(aOrigin)));
-  }
-
   // Compute scale for fallback rendering. We don't try to guess a scale for 3d
   // transformed items
   gfx::Matrix transform2d;
   if (aBoundTransform && aBoundTransform->CanDraw2D(&transform2d)
       && !aPerspectivePtr
       && !aParentSC.mIsPreserve3D) {
     mInheritedTransform = transform2d * aParentSC.mInheritedTransform;
     mScale = mInheritedTransform.ScaleFactors(true);
@@ -66,27 +62,31 @@ StackingContextHelper::StackingContextHe
     mScale = aParentSC.mScale;
   }
 
   auto rasterSpace = mRasterizeLocally
     ? wr::RasterSpace::Local(std::max(mScale.width, mScale.height))
     : wr::RasterSpace::Screen();
 
   mReferenceFrameId = mBuilder->PushStackingContext(
+          wr::ToLayoutRect(aBounds),
           aClipNodeId,
           aAnimation,
           aOpacityPtr,
           aTransformPtr,
           aIsPreserve3D ? wr::TransformStyle::Preserve3D : wr::TransformStyle::Flat,
           aPerspectivePtr,
           wr::ToMixBlendMode(aMixBlendMode),
           aFilters,
           aBackfaceVisible,
           rasterSpace);
 
+  mAffectsClipPositioning = mReferenceFrameId.isSome() ||
+      (aBounds.TopLeft() != LayoutDevicePoint());
+
   // If the parent stacking context has a deferred transform item, inherit it
   // into this stacking context, as long as the ASR hasn't changed. Refer to
   // the comments on StackingContextHelper::mDeferredTransformItem for an
   // explanation of what goes in these fields.
   if (aParentSC.mDeferredTransformItem &&
       aAsr == (*aParentSC.mDeferredTransformItem)->GetActiveScrolledRoot()) {
     if (mDeferredTransformItem) {
       // If we are deferring another transform, put the combined transform from
@@ -94,39 +94,25 @@ StackingContextHelper::StackingContextHe
       mDeferredAncestorTransform = aParentSC.GetDeferredTransformMatrix();
     } else {
       // We are not deferring another transform, so we can just inherit the
       // parent stacking context's deferred data without any modification.
       mDeferredTransformItem = aParentSC.mDeferredTransformItem;
       mDeferredAncestorTransform = aParentSC.mDeferredAncestorTransform;
     }
   }
-
-  // Update the origin for use by sticky frames.
-  if (!mReferenceFrameId) {
-    mInheritedStickyOrigin += aParentSC.mInheritedStickyOrigin;
-  }
 }
 
 StackingContextHelper::~StackingContextHelper()
 {
   if (mBuilder) {
     mBuilder->PopStackingContext(mReferenceFrameId.isSome());
-    if (mOriginFrameId) {
-      mBuilder->PopOrigin();
-    }
   }
 }
 
-Maybe<wr::WrClipId>
-StackingContextHelper::ReferenceFrameId() const
-{
-  return mReferenceFrameId ? mReferenceFrameId : mOriginFrameId;
-}
-
 const Maybe<nsDisplayTransform*>&
 StackingContextHelper::GetDeferredTransformItem() const
 {
   return mDeferredTransformItem;
 }
 
 Maybe<gfx::Matrix4x4>
 StackingContextHelper::GetDeferredTransformMatrix() const
--- a/gfx/layers/wr/StackingContextHelper.h
+++ b/gfx/layers/wr/StackingContextHelper.h
@@ -27,20 +27,20 @@ namespace layers {
  */
 class MOZ_RAII StackingContextHelper
 {
 public:
   StackingContextHelper(const StackingContextHelper& aParentSC,
                         const ActiveScrolledRoot* aAsr,
                         wr::DisplayListBuilder& aBuilder,
                         const nsTArray<wr::WrFilterOp>& aFilters = nsTArray<wr::WrFilterOp>(),
+                        const LayoutDeviceRect& aBounds = LayoutDeviceRect(),
                         const gfx::Matrix4x4* aBoundTransform = nullptr,
                         const wr::WrAnimationProperty* aAnimation = nullptr,
                         const float* aOpacityPtr = nullptr,
-                        const LayoutDevicePoint& aOrigin = LayoutDevicePoint(),
                         const gfx::Matrix4x4* aTransformPtr = nullptr,
                         const gfx::Matrix4x4* aPerspectivePtr = nullptr,
                         const gfx::CompositionOp& aMixBlendMode = gfx::CompositionOp::OP_OVER,
                         bool aBackfaceVisible = true,
                         bool aIsPreserve3D = false,
                         const Maybe<nsDisplayTransform*>& aDeferredTransformItem = Nothing(),
                         const wr::WrClipId* aClipNodeId = nullptr,
                         bool aAnimated = false);
@@ -64,40 +64,32 @@ public:
   const gfx::Matrix& GetSnappingSurfaceTransform() const
   {
     return mSnappingSurfaceTransform;
   }
 
   const Maybe<nsDisplayTransform*>& GetDeferredTransformItem() const;
   Maybe<gfx::Matrix4x4> GetDeferredTransformMatrix() const;
 
-  Maybe<wr::WrClipId> ReferenceFrameId() const;
-
-  const LayoutDevicePoint& GetInheritedStickyOrigin() const {
-    return mInheritedStickyOrigin;
-  }
+  bool AffectsClipPositioning() const { return mAffectsClipPositioning; }
+  Maybe<wr::WrClipId> ReferenceFrameId() const { return mReferenceFrameId; }
 
 private:
   wr::DisplayListBuilder* mBuilder;
   gfx::Size mScale;
   gfx::Matrix mInheritedTransform;
 
-  // A stacking context may insert a special WR reference frame if we have
-  // origin provided. It only affects sticky frames below it, which need to
-  // compensate for the origin when computing the viewport.
-  LayoutDevicePoint mInheritedStickyOrigin;
-
   // The "snapping surface" defines the space that we want to snap in.
   // You can think of it as the nearest physical surface.
   // Animated transforms create a new snapping surface, so that changes to their transform don't affect the snapping of their contents.
   // Non-animated transforms do *not* create a new snapping surface,
   // so that for example the existence of a non-animated identity transform does not affect snapping.
   gfx::Matrix mSnappingSurfaceTransform;
+  bool mAffectsClipPositioning;
   Maybe<wr::WrClipId> mReferenceFrameId;
-  Maybe<wr::WrClipId> mOriginFrameId;
 
   // The deferred transform item is used when building the WebRenderScrollData
   // structure. The backstory is that APZ needs to know about transforms that
   // apply to the different APZC instances. Prior to bug 1423370, we would do
   // this by creating a new WebRenderLayerScrollData for each nsDisplayTransform
   // item we encountered. However, this was unnecessarily expensive because it
   // turned out a lot of nsDisplayTransform items didn't have new ASRs defined
   // as descendants, so we'd create the WebRenderLayerScrollData and send it
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -989,17 +989,17 @@ WebRenderBridgeParent::RecvSetDisplayLis
 
   if (validTransaction) {
     if (IsRootWebRenderBridgeParent()) {
       LayoutDeviceIntSize widgetSize = mWidget->GetClientSize();
       LayoutDeviceIntRect docRect(LayoutDeviceIntPoint(), widgetSize);
       txn.SetWindowParameters(widgetSize, docRect);
     }
     gfx::Color clearColor(0.f, 0.f, 0.f, 0.f);
-    txn.SetDisplayList(clearColor, wrEpoch, LayoutDeviceSize(aSize.width, aSize.height),
+    txn.SetDisplayList(clearColor, wrEpoch, LayerSize(aSize.width, aSize.height),
                        mPipelineId, aContentSize,
                        dlDesc, dlData);
 
     if (observeLayersUpdate) {
       txn.Notify(
         wr::Checkpoint::SceneBuilt,
         MakeUnique<ScheduleObserveLayersUpdate>(
           mCompositorBridge,
@@ -1228,17 +1228,17 @@ WebRenderBridgeParent::ProcessWebRenderP
       case WebRenderParentCommand::TOpReleaseTextureOfImage: {
         const OpReleaseTextureOfImage& op = cmd.get_OpReleaseTextureOfImage();
         ReleaseTextureOfImage(op.key());
         break;
       }
       case WebRenderParentCommand::TOpUpdateAsyncImagePipeline: {
         const OpUpdateAsyncImagePipeline& op = cmd.get_OpUpdateAsyncImagePipeline();
         mAsyncImageManager->UpdateAsyncImagePipeline(op.pipelineId(),
-                                                     op.scSize(),
+                                                     op.scBounds(),
                                                      op.scTransform(),
                                                      op.scaleToSize(),
                                                      op.filter(),
                                                      op.mixBlendMode());
         mAsyncImageManager->ApplyAsyncImageForPipeline(op.pipelineId(), aTxn, txnForImageBridge);
         break;
       }
       case WebRenderParentCommand::TOpUpdatedAsyncImagePipeline: {
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -1144,17 +1144,17 @@ Grouper::ConstructItemInsideInactive(Web
 
   /* mInvalid unfortunately persists across paints. Clear it so that if we don't
    * set it to 'true' we ensure that we're not using the value from the last
    * time that we painted */
   data->mInvalid = false;
 
   // we compute the geometry change here because we have the transform around still
   aGroup->ComputeGeometryChange(aItem, data, mTransform, mDisplayListBuilder);
-
+  
   // Temporarily restrict the image bounds to the bounds of the container so that
   // clipped children within the container know about the clip.
   IntRect oldImageBounds = aGroup->mImageBounds;
   aGroup->mImageBounds = aGroup->mImageBounds.Intersect(data->mRect);
 
   if (aItem->GetType() == DisplayItemType::TYPE_FILTER) {
     gfx::Size scale(1, 1);
     // If ComputeDifferences finds any change, we invalidate the entire container item.
@@ -1357,17 +1357,17 @@ WebRenderCommandBuilder::BuildWebRenderC
   {
     if (!mZoomProp && gfxPrefs::APZAllowZooming() && XRE_IsContentProcess()) {
       mZoomProp.emplace();
       mZoomProp->effect_type = wr::WrAnimationType::Transform;
       mZoomProp->id = AnimationHelper::GetNextCompositorAnimationsId();
     }
 
     StackingContextHelper pageRootSc(sc, nullptr, aBuilder, aFilters,
-        nullptr, mZoomProp.ptrOr(nullptr));
+        LayoutDeviceRect(), nullptr, mZoomProp.ptrOr(nullptr));
     if (ShouldDumpDisplayList(aDisplayListBuilder)) {
       mBuilderDumpIndex = aBuilder.Dump(mDumpIndent + 1, Some(mBuilderDumpIndex), Nothing());
     }
     CreateWebRenderCommandsFromDisplayList(aDisplayList, nullptr, aDisplayListBuilder,
                                            pageRootSc, aBuilder, aResourceUpdates);
   }
 
   // Make a "root" layer data that has everything else as descendants
@@ -1619,28 +1619,30 @@ WebRenderCommandBuilder::CreateImageKey(
 {
   RefPtr<WebRenderImageData> imageData = CreateOrRecycleWebRenderUserData<WebRenderImageData>(aItem);
   MOZ_ASSERT(imageData);
 
   if (aContainer->IsAsync()) {
     MOZ_ASSERT(aAsyncImageBounds);
 
     LayoutDeviceRect rect = aAsyncImageBounds.value();
+    LayoutDeviceRect scBounds(LayoutDevicePoint(0, 0), rect.Size());
     gfx::MaybeIntSize scaleToSize;
     if (!aContainer->GetScaleHint().IsEmpty()) {
       scaleToSize = Some(aContainer->GetScaleHint());
     }
     gfx::Matrix4x4 transform = gfx::Matrix4x4::From2D(aContainer->GetTransformHint());
     // TODO!
     // We appear to be using the image bridge for a lot (most/all?) of
     // layers-free image handling and that breaks frame consistency.
     imageData->CreateAsyncImageWebRenderCommands(aBuilder,
                                                  aContainer,
                                                  aSc,
                                                  rect,
+                                                 scBounds,
                                                  transform,
                                                  scaleToSize,
                                                  aRendering,
                                                  wr::MixBlendMode::Normal,
                                                  !aItem->BackfaceIsHidden());
     return Nothing();
   }
 
--- a/gfx/layers/wr/WebRenderUserData.cpp
+++ b/gfx/layers/wr/WebRenderUserData.cpp
@@ -224,16 +224,17 @@ WebRenderImageData::GetImageClient()
   return imageClient.forget();
 }
 
 void
 WebRenderImageData::CreateAsyncImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                                       ImageContainer* aContainer,
                                                       const StackingContextHelper& aSc,
                                                       const LayoutDeviceRect& aBounds,
+                                                      const LayoutDeviceRect& aSCBounds,
                                                       const gfx::Matrix4x4& aSCTransform,
                                                       const gfx::MaybeIntSize& aScaleToSize,
                                                       const wr::ImageRendering& aFilter,
                                                       const wr::MixBlendMode& aMixBlendMode,
                                                       bool aIsBackfaceVisible)
 {
   MOZ_ASSERT(aContainer->IsAsync());
 
@@ -257,31 +258,20 @@ WebRenderImageData::CreateAsyncImageWebR
   //
   // We don't push a stacking context for this async image pipeline here.
   // Instead, we do it inside the iframe that hosts the image. As a result,
   // a bunch of the calculations normally done as part of that stacking
   // context need to be done manually and pushed over to the parent side,
   // where it will be done when we build the display list for the iframe.
   // That happens in AsyncImagePipelineManager.
   wr::LayoutRect r = wr::ToRoundedLayoutRect(aBounds);
-
-  Maybe<wr::WrClipId> originFrameId;
-  if (r.origin.x != 0.0 || r.origin.y != 0.0) {
-    originFrameId = Some(aBuilder.PushOrigin(r.origin));
-    r.origin = wr::LayoutPoint { 0.0, 0.0 };
-  }
-
   aBuilder.PushIFrame(r, aIsBackfaceVisible, mPipelineId.ref(), /*ignoreMissingPipelines*/ false);
 
-  if (originFrameId) {
-    aBuilder.PopOrigin();
-  }
-
   WrBridge()->AddWebRenderParentCommand(OpUpdateAsyncImagePipeline(mPipelineId.value(),
-                                                                   aBounds.Size(),
+                                                                   aSCBounds,
                                                                    aSCTransform,
                                                                    aScaleToSize,
                                                                    aFilter,
                                                                    aMixBlendMode));
 }
 
 void
 WebRenderImageData::CreateImageClientIfNeeded()
--- a/gfx/layers/wr/WebRenderUserData.h
+++ b/gfx/layers/wr/WebRenderUserData.h
@@ -134,16 +134,17 @@ public:
   Maybe<wr::ImageKey> UpdateImageKey(ImageContainer* aContainer,
                                      wr::IpcResourceUpdateQueue& aResources,
                                      bool aFallback = false);
 
   void CreateAsyncImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                          ImageContainer* aContainer,
                                          const StackingContextHelper& aSc,
                                          const LayoutDeviceRect& aBounds,
+                                         const LayoutDeviceRect& aSCBounds,
                                          const gfx::Matrix4x4& aSCTransform,
                                          const gfx::MaybeIntSize& aScaleToSize,
                                          const wr::ImageRendering& aFilter,
                                          const wr::MixBlendMode& aMixBlendMode,
                                          bool aIsBackfaceVisible);
 
   void CreateImageClientIfNeeded();
 
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -184,17 +184,17 @@ void
 TransactionBuilder::RemovePipeline(PipelineId aPipelineId)
 {
   wr_transaction_remove_pipeline(mTxn, aPipelineId);
 }
 
 void
 TransactionBuilder::SetDisplayList(gfx::Color aBgColor,
                                    Epoch aEpoch,
-                                   LayoutDeviceSize aViewportSize,
+                                   mozilla::LayerSize aViewportSize,
                                    wr::WrPipelineId pipeline_id,
                                    const wr::LayoutSize& content_size,
                                    wr::BuiltDisplayListDescriptor dl_descriptor,
                                    wr::Vec<uint8_t>& dl_data)
 {
   wr_transaction_set_display_list(mTxn,
                                   aEpoch,
                                   ToColorF(aBgColor),
@@ -865,39 +865,19 @@ DisplayListBuilder::Finalize(wr::LayoutS
                              BuiltDisplayList& aOutDisplayList)
 {
   wr_api_finalize_builder(mWrState,
                           &aOutContentSize,
                           &aOutDisplayList.dl_desc,
                           &aOutDisplayList.dl.inner);
 }
 
-wr::WrClipId
-DisplayListBuilder::PushOrigin(const wr::LayoutPoint& aOrigin)
-{
-  WRDL_LOG("PushOrigin t=%s\n", mWrState,
-      Stringify(aOrigin).c_str());
-
-  //Note: there could be a simpler way to convert LayoutPoint -> LayoutTransform
-  wr::LayoutTransform transform = ToLayoutTransform(
-    gfx::Matrix4x4::Translation(aOrigin.x, aOrigin.y, 0.0));
-
-  auto id = wr_dp_push_reference_frame(mWrState, &transform);
-  return wr::WrClipId { id };
-}
-
-void
-DisplayListBuilder::PopOrigin()
-{
-  WRDL_LOG("PopOrigin\n", mWrState);
-  wr_dp_pop_reference_frame(mWrState);
-}
-
 Maybe<wr::WrClipId>
-DisplayListBuilder::PushStackingContext(const wr::WrClipId* aClipNodeId,
+DisplayListBuilder::PushStackingContext(const wr::LayoutRect& aBounds,
+                                        const wr::WrClipId* aClipNodeId,
                                         const WrAnimationProperty* aAnimation,
                                         const float* aOpacity,
                                         const gfx::Matrix4x4* aTransform,
                                         wr::TransformStyle aTransformStyle,
                                         const gfx::Matrix4x4* aPerspective,
                                         const wr::MixBlendMode& aMixBlendMode,
                                         const nsTArray<wr::WrFilterOp>& aFilters,
                                         bool aIsBackfaceVisible,
@@ -910,23 +890,24 @@ DisplayListBuilder::PushStackingContext(
   if (aTransform) {
     matrix = ToLayoutTransform(*aTransform);
   }
   const wr::LayoutTransform* maybeTransform = aTransform ? &matrix : nullptr;
   wr::LayoutTransform perspective;
   if (aPerspective) {
     perspective = ToLayoutTransform(*aPerspective);
   }
+
   const wr::LayoutTransform* maybePerspective = aPerspective ? &perspective : nullptr;
-  WRDL_LOG("PushStackingContext t=%s\n", mWrState,
+  WRDL_LOG("PushStackingContext b=%s t=%s\n", mWrState, Stringify(aBounds).c_str(),
       aTransform ? Stringify(*aTransform).c_str() : "none");
 
   bool outIsReferenceFrame = false;
   uintptr_t outReferenceFrameId = 0;
-  wr_dp_push_stacking_context(mWrState, aClipNodeId, aAnimation,
+  wr_dp_push_stacking_context(mWrState, aBounds, aClipNodeId, aAnimation,
                               aOpacity, maybeTransform, aTransformStyle,
                               maybePerspective, aMixBlendMode,
                               aFilters.Elements(), aFilters.Length(),
                               aIsBackfaceVisible, aRasterSpace,
                               &outIsReferenceFrame, &outReferenceFrameId);
   return outIsReferenceFrame ? Some(wr::WrClipId { outReferenceFrameId }) : Nothing();
 }
 
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -82,17 +82,17 @@ public:
   void UpdateEpoch(PipelineId aPipelineId, Epoch aEpoch);
 
   void SetRootPipeline(PipelineId aPipelineId);
 
   void RemovePipeline(PipelineId aPipelineId);
 
   void SetDisplayList(gfx::Color aBgColor,
                       Epoch aEpoch,
-                      LayoutDeviceSize aViewportSize,
+                      mozilla::LayerSize aViewportSize,
                       wr::WrPipelineId pipeline_id,
                       const wr::LayoutSize& content_size,
                       wr::BuiltDisplayListDescriptor dl_descriptor,
                       wr::Vec<uint8_t>& dl_data);
 
   void ClearDisplayList(Epoch aEpoch, wr::WrPipelineId aPipeline);
 
   void GenerateFrame();
@@ -330,20 +330,18 @@ public:
   void Save();
   void Restore();
   void ClearSave();
   usize Dump(usize aIndent, const Maybe<usize>& aStart, const Maybe<usize>& aEnd);
 
   void Finalize(wr::LayoutSize& aOutContentSize,
                 wr::BuiltDisplayList& aOutDisplayList);
 
-  wr::WrClipId PushOrigin(const wr::LayoutPoint& aOrigin);
-  void PopOrigin();
-
   Maybe<wr::WrClipId> PushStackingContext(
+          const wr::LayoutRect& aBounds, // TODO: We should work with strongly typed rects
           const wr::WrClipId* aClipNodeId,
           const wr::WrAnimationProperty* aAnimation,
           const float* aOpacity,
           const gfx::Matrix4x4* aTransform,
           wr::TransformStyle aTransformStyle,
           const gfx::Matrix4x4* aPerspective,
           const wr::MixBlendMode& aMixBlendMode,
           const nsTArray<wr::WrFilterOp>& aFilters,
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1849,41 +1849,18 @@ pub extern "C" fn wr_dp_restore(state: &
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_clear_save(state: &mut WrState) {
     state.frame_builder.dl_builder.clear_save();
 }
 
 #[no_mangle]
-pub extern "C" fn wr_dp_push_reference_frame(state: &mut WrState,
-                                             transform: &LayoutTransform) -> usize {
-    debug_assert!(unsafe { !is_in_render_thread() });
-
-    let perspective = None;
-    let ref_frame_id = state.frame_builder.dl_builder.push_reference_frame(
-        &LayoutPrimitiveInfo::new(LayoutRect::zero()),
-        Some(PropertyBinding::Value(*transform)),
-        perspective,
-    );
-
-    state.frame_builder.dl_builder.push_clip_id(ref_frame_id);
-    pack_clip_id(ref_frame_id)
-}
-
-#[no_mangle]
-pub extern "C" fn wr_dp_pop_reference_frame(state: &mut WrState) {
-    debug_assert!(unsafe { !is_in_render_thread() });
-
-    state.frame_builder.dl_builder.pop_clip_id();
-    state.frame_builder.dl_builder.pop_reference_frame();
-}
-
-#[no_mangle]
 pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
+                                              bounds: LayoutRect,
                                               clip_node_id: *const WrClipId,
                                               animation: *const WrAnimationProperty,
                                               opacity: *const f32,
                                               transform: *const LayoutTransform,
                                               transform_style: TransformStyle,
                                               perspective: *const LayoutTransform,
                                               mix_blend_mode: MixBlendMode,
                                               filters: *const WrFilterOp,
@@ -1910,108 +1887,110 @@ pub extern "C" fn wr_dp_push_stacking_co
                                                                c_filter.argument,
                                                                c_filter.color),
             WrFilterOpType::ColorMatrix => FilterOp::ColorMatrix(c_filter.matrix),
             WrFilterOpType::SrgbToLinear => FilterOp::SrgbToLinear,
             WrFilterOpType::LinearToSrgb => FilterOp::LinearToSrgb,
         }
     }).collect();
 
-    let clip_node_id = match unsafe { clip_node_id.as_ref() } {
+    let clip_node_id_ref = unsafe { clip_node_id.as_ref() };
+    let clip_node_id = match clip_node_id_ref {
         Some(clip_node_id) => Some(unpack_clip_id(*clip_node_id, state.pipeline_id)),
         None => None,
     };
 
-    let transform = unsafe { transform.as_ref() }.cloned();
-    let mut transform_binding = transform.map(PropertyBinding::Value);
-    let opacity = unsafe { opacity.as_ref() }.cloned();
+    let transform_ref = unsafe { transform.as_ref() };
+    let mut transform_binding = match transform_ref {
+        Some(transform) => Some(PropertyBinding::Value(transform.clone())),
+        None => None,
+    };
 
+    let opacity_ref = unsafe { opacity.as_ref() };
     let mut has_opacity_animation = false;
-    if let Some(anim) = unsafe { animation.as_ref() } {
+    let anim = unsafe { animation.as_ref() };
+    if let Some(anim) = anim {
         debug_assert!(anim.id > 0);
         match anim.effect_type {
             WrAnimationType::Opacity => {
-                filters.push(FilterOp::Opacity(
-                    PropertyBinding::Binding(
-                        PropertyBindingKey::new(anim.id),
-                        // We have to set the static opacity value as
-                        // the value for the case where the animation is
-                        // in not in-effect (e.g. in the delay phase
-                        // with no corresponding fill mode).
-                        opacity.unwrap_or(1.0),
-                    ),
-                    1.0,
-                ));
+                filters.push(FilterOp::Opacity(PropertyBinding::Binding(PropertyBindingKey::new(anim.id),
+                                                                        // We have to set the static opacity value as
+                                                                        // the value for the case where the animation is
+                                                                        // in not in-effect (e.g. in the delay phase
+                                                                        // with no corresponding fill mode).
+                                                                        opacity_ref.cloned().unwrap_or(1.0)),
+                                                                        1.0));
                 has_opacity_animation = true;
             },
             WrAnimationType::Transform => {
                 transform_binding =
-                    Some(PropertyBinding::Binding(
-                        PropertyBindingKey::new(anim.id),
-                        // Same as above opacity case.
-                        transform.unwrap_or(LayoutTransform::identity()),
-                ));
+                    Some(PropertyBinding::Binding(PropertyBindingKey::new(anim.id),
+                                                  // Same as above opacity case.
+                                                  transform_ref.cloned().unwrap_or(LayoutTransform::identity())));
             },
         }
     }
 
-    if let Some(opacity) = opacity {
-        if !has_opacity_animation && opacity < 1.0 {
-            filters.push(FilterOp::Opacity(PropertyBinding::Value(opacity), opacity));
+    if let Some(opacity) = opacity_ref {
+        if !has_opacity_animation && *opacity < 1.0 {
+            filters.push(FilterOp::Opacity(PropertyBinding::Value(*opacity), *opacity));
         }
     }
 
-    let perspective = unsafe { perspective.as_ref() }.cloned();
-    // The only field of primitive info currently used by WR for stacking contexts
-    // is backface visibility. Layout rectangles don't matter.
-    let mut prim_info = LayoutPrimitiveInfo::new(LayoutRect::zero());
+    let perspective_ref = unsafe { perspective.as_ref() };
+    let perspective = match perspective_ref {
+        Some(perspective) => Some(perspective.clone()),
+        None => None,
+    };
+
+    let mut prim_info = LayoutPrimitiveInfo::new(bounds);
 
     *out_is_reference_frame = transform_binding.is_some() || perspective.is_some();
     if *out_is_reference_frame {
         let ref_frame_id = state.frame_builder
             .dl_builder
             .push_reference_frame(&prim_info, transform_binding, perspective);
         *out_reference_frame_id = pack_clip_id(ref_frame_id);
 
+        prim_info.rect.origin = LayoutPoint::zero();
+        prim_info.clip_rect.origin = LayoutPoint::zero();
         state.frame_builder.dl_builder.push_clip_id(ref_frame_id);
     }
 
     prim_info.is_backface_visible = is_backface_visible;
     prim_info.tag = state.current_tag;
 
-    state.frame_builder.dl_builder.push_stacking_context(
-        &prim_info,
-        clip_node_id,
-        transform_style,
-        mix_blend_mode,
-        &filters,
-        glyph_raster_space,
-    );
+    state.frame_builder
+         .dl_builder
+         .push_stacking_context(&prim_info,
+                                clip_node_id,
+                                transform_style,
+                                mix_blend_mode,
+                                &filters,
+                                glyph_raster_space);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_pop_stacking_context(state: &mut WrState,
                                              is_reference_frame: bool) {
     debug_assert!(unsafe { !is_in_render_thread() });
-
     state.frame_builder.dl_builder.pop_stacking_context();
     if is_reference_frame {
         state.frame_builder.dl_builder.pop_clip_id();
         state.frame_builder.dl_builder.pop_reference_frame();
     }
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_define_clipchain(state: &mut WrState,
                                          parent_clipchain_id: *const u64,
                                          clips: *const WrClipId,
                                          clips_count: usize)
                                          -> u64 {
     debug_assert!(unsafe { is_in_main_thread() });
-
     let parent = unsafe { parent_clipchain_id.as_ref() }.map(|id| ClipChainId(*id, state.pipeline_id));
     let pipeline_id = state.pipeline_id;
     let clips = make_slice(clips, clips_count)
         .iter()
         .map(|id| unpack_clip_id(*id, pipeline_id));
 
     let clipchain_id = state.frame_builder.dl_builder.define_clip_chain(parent, clips);
     assert!(clipchain_id.1 == state.pipeline_id);
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -811,16 +811,38 @@ struct GradientStop {
   ColorF color;
 
   bool operator==(const GradientStop& aOther) const {
     return offset == aOther.offset &&
            color == aOther.color;
   }
 };
 
+struct Shadow {
+  LayoutVector2D offset;
+  ColorF color;
+  float blur_radius;
+
+  bool operator==(const Shadow& aOther) const {
+    return offset == aOther.offset &&
+           color == aOther.color &&
+           blur_radius == aOther.blur_radius;
+  }
+};
+
+struct WrAnimationProperty {
+  WrAnimationType effect_type;
+  uint64_t id;
+
+  bool operator==(const WrAnimationProperty& aOther) const {
+    return effect_type == aOther.effect_type &&
+           id == aOther.id;
+  }
+};
+
 // A 3d transform stored as a 4 by 4 matrix in row-major order in memory.
 //
 // Transforms can be parametrized over the source and destination units, to describe a
 // transformation from a space to another.
 // For example, `TypedTransform3D<f32, WorldSpace, ScreenSpace>::transform_point3d`
 // takes a `TypedPoint3D<f32, WorldSpace>` and returns a `TypedPoint3D<f32, ScreenSpace>`.
 //
 // Transforms expose a set of convenience methods for pre- and post-transformations.
@@ -863,38 +885,16 @@ struct TypedTransform3D {
            m42 == aOther.m42 &&
            m43 == aOther.m43 &&
            m44 == aOther.m44;
   }
 };
 
 using LayoutTransform = TypedTransform3D<float, LayoutPixel, LayoutPixel>;
 
-struct Shadow {
-  LayoutVector2D offset;
-  ColorF color;
-  float blur_radius;
-
-  bool operator==(const Shadow& aOther) const {
-    return offset == aOther.offset &&
-           color == aOther.color &&
-           blur_radius == aOther.blur_radius;
-  }
-};
-
-struct WrAnimationProperty {
-  WrAnimationType effect_type;
-  uint64_t id;
-
-  bool operator==(const WrAnimationProperty& aOther) const {
-    return effect_type == aOther.effect_type &&
-           id == aOther.id;
-  }
-};
-
 struct WrFilterOp {
   WrFilterOpType filter_type;
   float argument;
   LayoutVector2D offset;
   ColorF color;
   float matrix[20];
 };
 
@@ -1355,20 +1355,16 @@ WR_INLINE
 void wr_dp_pop_clip(WrState *aState)
 WR_FUNC;
 
 WR_INLINE
 void wr_dp_pop_clip_and_scroll_info(WrState *aState)
 WR_FUNC;
 
 WR_INLINE
-void wr_dp_pop_reference_frame(WrState *aState)
-WR_FUNC;
-
-WR_INLINE
 void wr_dp_pop_scroll_layer(WrState *aState)
 WR_FUNC;
 
 WR_INLINE
 void wr_dp_pop_stacking_context(WrState *aState,
                                 bool aIsReferenceFrame)
 WR_FUNC;
 
@@ -1528,35 +1524,31 @@ WR_INLINE
 void wr_dp_push_rect(WrState *aState,
                      LayoutRect aRect,
                      LayoutRect aClip,
                      bool aIsBackfaceVisible,
                      ColorF aColor)
 WR_FUNC;
 
 WR_INLINE
-uintptr_t wr_dp_push_reference_frame(WrState *aState,
-                                     const LayoutTransform *aTransform)
-WR_FUNC;
-
-WR_INLINE
 void wr_dp_push_scroll_layer(WrState *aState,
                              WrClipId aScrollId)
 WR_FUNC;
 
 WR_INLINE
 void wr_dp_push_shadow(WrState *aState,
                        LayoutRect aBounds,
                        LayoutRect aClip,
                        bool aIsBackfaceVisible,
                        Shadow aShadow)
 WR_FUNC;
 
 WR_INLINE
 void wr_dp_push_stacking_context(WrState *aState,
+                                 LayoutRect aBounds,
                                  const WrClipId *aClipNodeId,
                                  const WrAnimationProperty *aAnimation,
                                  const float *aOpacity,
                                  const LayoutTransform *aTransform,
                                  TransformStyle aTransformStyle,
                                  const LayoutTransform *aPerspective,
                                  MixBlendMode aMixBlendMode,
                                  const WrFilterOp *aFilters,
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -182,17 +182,16 @@ public:
   typedef mozilla::layers::ScrollableLayerGuid::ViewID ViewID;
   typedef mozilla::CSSPoint CSSPoint;
   typedef mozilla::CSSSize CSSSize;
   typedef mozilla::CSSIntSize CSSIntSize;
   typedef mozilla::CSSRect CSSRect;
   typedef mozilla::ScreenMargin ScreenMargin;
   typedef mozilla::LayoutDeviceIntSize LayoutDeviceIntSize;
   typedef mozilla::LayoutDeviceRect LayoutDeviceRect;
-  typedef mozilla::LayoutDeviceSize LayoutDeviceSize;
   typedef mozilla::StyleGeometryBox StyleGeometryBox;
   typedef mozilla::SVGImageContext SVGImageContext;
   typedef mozilla::LogicalSize LogicalSize;
 
   /**
    * Finds previously assigned ViewID for the given content element, if any.
    * Returns whether a ViewID was previously assigned.
    */
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -180,20 +180,21 @@ public:
         gfxRect destGFXRect = mFrame->PresContext()->AppUnitsToGfxUnits(dest);
         scTransform.PreScale(destGFXRect.Width() / canvasSizeInPx.width,
                              destGFXRect.Height() / canvasSizeInPx.height, 1.0f);
         if (data->NeedsYFlip()) {
           scTransform = scTransform.PreTranslate(0, data->GetSize().height, 0).PreScale(1, -1, 1);
         }
 
         MaybeIntSize scaleToSize;
+        LayoutDeviceRect scBounds(LayoutDevicePoint(0, 0), bounds.Size());
         wr::ImageRendering filter = wr::ToImageRendering(nsLayoutUtils::GetSamplingFilterForFrame(mFrame));
         wr::MixBlendMode mixBlendMode = wr::MixBlendMode::Normal;
         aManager->WrBridge()->AddWebRenderParentCommand(OpUpdateAsyncImagePipeline(data->GetPipelineId().value(),
-                                                                                   bounds.Size(),
+                                                                                   scBounds,
                                                                                    scTransform,
                                                                                    scaleToSize,
                                                                                    filter,
                                                                                    mixBlendMode));
         break;
       }
       case CanvasContextType::ImageBitmap:
       {
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -6825,16 +6825,17 @@ nsDisplayOpacity::CreateWebRenderCommand
     animationsId,
   };
 
   nsTArray<mozilla::wr::WrFilterOp> filters;
   StackingContextHelper sc(aSc,
                            GetActiveScrolledRoot(),
                            aBuilder,
                            filters,
+                           LayoutDeviceRect(),
                            nullptr,
                            animationsId ? &prop : nullptr,
                            opacityForSC);
 
   aManager->CommandBuilder().CreateWebRenderCommandsFromDisplayList(
     &mList, this, aDisplayListBuilder, sc, aBuilder, aResources);
   return true;
 }
@@ -6878,20 +6879,20 @@ nsDisplayBlendMode::CreateWebRenderComma
   mozilla::layers::WebRenderLayerManager* aManager,
   nsDisplayListBuilder* aDisplayListBuilder)
 {
   nsTArray<mozilla::wr::WrFilterOp> filters;
   StackingContextHelper sc(aSc,
                            GetActiveScrolledRoot(),
                            aBuilder,
                            filters,
+                           LayoutDeviceRect(),
                            nullptr,
                            nullptr,
                            nullptr,
-                           LayoutDevicePoint(),
                            nullptr,
                            nullptr,
                            nsCSSRendering::GetGFXBlendMode(mBlendMode));
 
   return nsDisplayWrapList::CreateWebRenderCommands(
     aBuilder, aResources, sc, aManager, aDisplayListBuilder);
 }
 
@@ -7170,16 +7171,17 @@ nsDisplayOwnLayer::CreateWebRenderComman
   wr::WrAnimationProperty prop;
   prop.id = mWrAnimationId;
   prop.effect_type = wr::WrAnimationType::Transform;
 
   StackingContextHelper sc(aSc,
                            GetActiveScrolledRoot(),
                            aBuilder,
                            nsTArray<wr::WrFilterOp>(),
+                           LayoutDeviceRect(),
                            nullptr,
                            &prop);
 
   nsDisplayWrapList::CreateWebRenderCommands(
     aBuilder, aResources, sc, aManager, aDisplayListBuilder);
   return true;
 }
 
@@ -7828,24 +7830,16 @@ nsDisplayStickyPosition::CreateWebRender
     nsIFrame* scrollFrame = do_QueryFrame(stickyScrollContainer->ScrollFrame());
     nsPoint offset = scrollFrame->GetOffsetToCrossDoc(ReferenceFrame());
 
     // Adjust the scrollPort coordinates to be relative to the reference frame,
     // so that it is in the same space as everything else.
     nsRect scrollPort =
       stickyScrollContainer->ScrollFrame()->GetScrollPortRect();
     scrollPort += offset;
-    // It would be cleaner to just modify `scrollPort` here instead of
-    // adjusting the computed margins, but the `scrollOrigin` is in a different
-    // space.
-    // Note: we aren't applying the reference frame origin if the scroll frame
-    // is already attached to it.
-    auto& scrollOrigin =
-      nsLayoutUtils::GetReferenceFrame(scrollFrame) == ReferenceFrame() ?
-      LayoutDevicePoint() : aSc.GetInheritedStickyOrigin();
 
     // The following computations make more sense upon understanding the
     // semantics of "inner" and "outer", which is explained in the comment on
     // SetStickyPositionData in Layers.h.
 
     if (outer.YMost() != inner.YMost()) {
       // Question: How far will itemBounds.y be from the top of the scrollport
       // when we have scrolled from the current scroll position of "0" to
@@ -7859,18 +7853,17 @@ nsDisplayStickyPosition::CreateWebRender
       // top of the scrollport. So in that case the adjustment is -distance.
       // If the distance is positive (0 < inner.YMost() <= outer.YMost()) then
       // we would be scrolling downwards, itemBounds.y would decrease, and we
       // again need to adjust by -distance. If we are already in the range
       // then no adjustment is needed and distance is 0 so again using
       // -distance works.
       nscoord distance = DistanceToRange(inner.YMost(), outer.YMost());
       topMargin = Some(NSAppUnitsToFloatPixels(
-        itemBounds.y - scrollPort.y - distance, auPerDevPixel
-        ) - scrollOrigin.y);
+        itemBounds.y - scrollPort.y - distance, auPerDevPixel));
       // Question: What is the maximum positive ("downward") offset that WR
       // will have to apply to this item in order to prevent the item from
       // visually moving?
       // Answer: Since the item is "sticky" in the range [inner.YMost(),
       // outer.YMost()], the maximum offset will be the size of the range, which
       // is outer.YMost() - inner.YMost().
       vBounds.max =
         NSAppUnitsToFloatPixels(outer.YMost() - inner.YMost(), auPerDevPixel);
@@ -7886,48 +7879,45 @@ nsDisplayStickyPosition::CreateWebRender
         MOZ_ASSERT(appliedOffset.y > 0);
       }
     }
     if (outer.Y() != inner.Y()) {
       // Similar logic as in the previous section, but this time we care about
       // the distance from itemBounds.YMost() to scrollPort.YMost().
       nscoord distance = DistanceToRange(outer.Y(), inner.Y());
       bottomMargin = Some(NSAppUnitsToFloatPixels(
-        scrollPort.YMost() - itemBounds.YMost() + distance, auPerDevPixel
-        ) - scrollOrigin.y);
+        scrollPort.YMost() - itemBounds.YMost() + distance, auPerDevPixel));
       // And here WR will be moving the item upwards rather than downwards so
       // again things are inverted from the previous block.
       vBounds.min =
         NSAppUnitsToFloatPixels(outer.Y() - inner.Y(), auPerDevPixel);
       // We can't have appliedOffset be both positive and negative, and the top
       // adjustment takes priority. So here we only update appliedOffset.y if
       // it wasn't set by the top-sticky case above.
       if (appliedOffset.y == 0 && inner.Y() > 0) {
         appliedOffset.y = std::max(0, outer.Y()) - inner.Y();
         MOZ_ASSERT(appliedOffset.y < 0);
       }
     }
     // Same as above, but for the x-axis
     if (outer.XMost() != inner.XMost()) {
       nscoord distance = DistanceToRange(inner.XMost(), outer.XMost());
       leftMargin = Some(NSAppUnitsToFloatPixels(
-        itemBounds.x - scrollPort.x - distance, auPerDevPixel
-        ) - scrollOrigin.x);
+        itemBounds.x - scrollPort.x - distance, auPerDevPixel));
       hBounds.max =
         NSAppUnitsToFloatPixels(outer.XMost() - inner.XMost(), auPerDevPixel);
       if (inner.XMost() < 0) {
         appliedOffset.x = std::min(0, outer.XMost()) - inner.XMost();
         MOZ_ASSERT(appliedOffset.x > 0);
       }
     }
     if (outer.X() != inner.X()) {
       nscoord distance = DistanceToRange(outer.X(), inner.X());
       rightMargin = Some(NSAppUnitsToFloatPixels(
-        scrollPort.XMost() - itemBounds.XMost() + distance, auPerDevPixel
-        ) - scrollOrigin.x);
+        scrollPort.XMost() - itemBounds.XMost() + distance, auPerDevPixel));
       hBounds.min =
         NSAppUnitsToFloatPixels(outer.X() - inner.X(), auPerDevPixel);
       if (appliedOffset.x == 0 && inner.X() > 0) {
         appliedOffset.x = std::max(0, outer.X()) - inner.X();
         MOZ_ASSERT(appliedOffset.x < 0);
       }
     }
 
@@ -8921,20 +8911,20 @@ nsDisplayTransform::CreateWebRenderComma
   // (disabling subpixel-aa and global pixel snapping)
   bool animated =
     ActiveLayerTracker::IsStyleMaybeAnimated(Frame(), eCSSProperty_transform);
 
   StackingContextHelper sc(aSc,
                            GetActiveScrolledRoot(),
                            aBuilder,
                            filters,
+                           LayoutDeviceRect(position, LayoutDeviceSize()),
                            &newTransformMatrix,
                            animationsId ? &prop : nullptr,
                            nullptr,
-                           position,
                            transformForSC,
                            nullptr,
                            gfx::CompositionOp::OP_OVER,
                            !BackfaceIsHidden(),
                            mFrame->Extend3DContext() && !mNoExtendContext,
                            deferredTransformItem,
                            nullptr,
                            animated);
@@ -9571,20 +9561,20 @@ nsDisplayPerspective::CreateWebRenderCom
 
   nsIFrame* perspectiveFrame = mFrame->GetContainingBlock(nsIFrame::SKIP_SCROLLED_FRAME);
 
   nsTArray<mozilla::wr::WrFilterOp> filters;
   StackingContextHelper sc(aSc,
                            GetActiveScrolledRoot(),
                            aBuilder,
                            filters,
+                           LayoutDeviceRect(),
                            nullptr,
                            nullptr,
                            nullptr,
-                           LayoutDevicePoint(),
                            &transformForSC,
                            &perspectiveMatrix,
                            gfx::CompositionOp::OP_OVER,
                            !BackfaceIsHidden(),
                            perspectiveFrame->Extend3DContext());
 
   return mList.CreateWebRenderCommands(
     aBuilder, aResources, sc, aManager, aDisplayListBuilder);
@@ -10274,20 +10264,20 @@ nsDisplayMasksAndClipPaths::CreateWebRen
     Maybe<float> opacity = clip->second() == HandleOpacity::Yes
       ? Some(mFrame->StyleEffects()->mOpacity)
       : Nothing();
 
     layer.emplace(aSc,
                   GetActiveScrolledRoot(),
                   aBuilder,
                   /*aFilters: */ nsTArray<wr::WrFilterOp>(),
+                  /*aBounds: */ bounds,
                   /*aBoundTransform: */ nullptr,
                   /*aAnimation: */ nullptr,
                   /*aOpacity: */ opacity.ptrOr(nullptr),
-                  /*aOrigin: */ LayoutDevicePoint(),
                   /*aTransform: */ nullptr,
                   /*aPerspective: */ nullptr,
                   /*aMixBlendMode: */ gfx::CompositionOp::OP_OVER,
                   /*aBackfaceVisible: */ true,
                   /*aIsPreserve3D: */ false,
                   /*aTransformForScrollData: */ Nothing(),
                   /*aClipNodeId: */ &clipId);
     sc = layer.ptr();
@@ -10597,21 +10587,21 @@ nsDisplayFilters::CreateWebRenderCommand
   wr::WrClipId clipId =
     aBuilder.DefineClip(Nothing(), wr::ToLayoutRect(postFilterBounds));
 
   float opacity = mFrame->StyleEffects()->mOpacity;
   StackingContextHelper sc(aSc,
                            GetActiveScrolledRoot(),
                            aBuilder,
                            wrFilters,
+                           LayoutDeviceRect(),
                            nullptr,
                            nullptr,
                            opacity != 1.0f && mHandleOpacity ? &opacity
                                                              : nullptr,
-                           LayoutDevicePoint(),
                            nullptr,
                            nullptr,
                            gfx::CompositionOp::OP_OVER,
                            true,
                            false,
                            Nothing(),
                            &clipId);
 
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -2072,17 +2072,17 @@ fuzzy-if(!(webrender&&gtkWidget),1-2,175
 test-pref(font.size.systemFontScale,200) == 1412743.html 1412743-ref.html
 == 1419820-1.html 1419820-1-ref.html
 == 1420946-1.html 1420946-1-ref.html
 == 1422393.html 1422393-ref.html
 == 1424177.html 1424177-ref.html
 == 1424680.html 1424680-ref.html
 == 1424798-1.html 1424798-ref.html
 fuzzy-if(!webrender,0-74,0-2234) == 1425243-1.html 1425243-1-ref.html
-fuzzy-if(Android,0-66,0-574) fuzzy-if(d2d,0-89,0-777) fuzzy-if(!Android&&!d2d,0-1,0-31341) fuzzy-if(webrender&&winWidget,1-1,31308-31320) == 1425243-2.html 1425243-2-ref.html
+fuzzy-if(Android,0-66,0-574) fuzzy-if(d2d,0-89,0-777) fuzzy-if(!Android&&!d2d,0-1,0-31341) fuzzy-if(webrender&&winWidget,1-1,31320-31320) == 1425243-2.html 1425243-2-ref.html
 == 1430869.html 1430869-ref.html
 == 1432541.html 1432541-ref.html
 pref(layout.css.moz-document.url-prefix-hack.enabled,true) == 1446470.html 1035091-ref.html
 pref(layout.css.moz-document.url-prefix-hack.enabled,false) == 1446470-2.html 1035091-ref.html
 test-pref(layout.css.prefixes.gradients,false) == 1451874.html 1451874-ref.html
 == 1456111-1.html about:blank
 test-pref(layout.css.contain.enabled,false) == 1466008.html 1466008-ref.html
 fuzzy(0-1,0-625) == 1466638-1.html 1466638-1-ref.html
--- a/layout/reftests/svg/conditions-07.svg
+++ b/layout/reftests/svg/conditions-07.svg
@@ -12,28 +12,28 @@
         try {
           var f1 = document.getElementById("f1");
           var i0 = f1.systemLanguage.getItem(0);
 
           if(i0 != "x") {
             return;
           }
           f1.removeAttribute("systemLanguage");
-
+          
         } catch(e) {
           var f = document.getElementById("fail");
           f.setAttribute("fill", "red");
         }
       }
     </script>
   </defs>
 
   <rect width="100%" height="100%" fill="lime"/>
   <!-- background images -->
-  <rect x="100" y="100" width="100" height="100" fill="yellow"/>
+  <rect x="100" y="100" width="100" height="100" fill="red"/>
 
   <!-- tests -->
   <foreignObject id="f1" x="100" y="100" width="100" height="100" systemLanguage="x">
     <svg>
       <rect width="100%" height="100%" fill="lime"/>
     </svg>
   </foreignObject>
   <rect id="fail" width="100%" height="100%" fill="none"/>