Bug 952977: Convert GetTransform to gfx::Matrix4x4 r=nical
authorDavid Zbarsky <dzbarsky@gmail.com>
Mon, 27 Jan 2014 10:28:47 -0500
changeset 181346 0ae9e982bf2f622b134812fd3a4c0b3bf521f4d8
parent 181345 6d8a33dcab140f264fa28450e4fe3bbef35528fb
child 181347 7776f7bdaa8d3d6404fa28d1835d6ebe3d12110b
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs952977
milestone29.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 952977: Convert GetTransform to gfx::Matrix4x4 r=nical
dom/base/nsDOMWindowUtils.cpp
gfx/layers/LayerSorter.cpp
gfx/layers/LayerTreeInvalidation.cpp
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/ReadbackProcessor.cpp
gfx/layers/composite/APZCTreeManager.cpp
gfx/layers/composite/AsyncCompositionManager.cpp
gfx/tests/gtest/TestLayers.cpp
layout/base/FrameLayerBuilder.cpp
layout/ipc/RenderFrameParent.cpp
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2677,22 +2677,22 @@ nsDOMWindowUtils::WrapDOMFile(nsIFile *a
   NS_ADDREF(*aDOMFile = new nsDOMFileFile(aFile));
   return NS_OK;
 }
 
 #ifdef DEBUG
 static bool
 CheckLeafLayers(Layer* aLayer, const nsIntPoint& aOffset, nsIntRegion* aCoveredRegion)
 {
-  gfxMatrix transform;
+  gfx::Matrix transform;
   if (!aLayer->GetTransform().Is2D(&transform) ||
       transform.HasNonIntegerTranslation())
     return false;
   transform.NudgeToIntegers();
-  nsIntPoint offset = aOffset + nsIntPoint(transform.x0, transform.y0);
+  nsIntPoint offset = aOffset + nsIntPoint(transform._31, transform._32);
 
   Layer* child = aLayer->GetFirstChild();
   if (child) {
     while (child) {
       if (!CheckLeafLayers(child, offset, aCoveredRegion))
         return false;
       child = child->GetNextSibling();
     }
--- a/gfx/layers/LayerSorter.cpp
+++ b/gfx/layers/LayerSorter.cpp
@@ -18,16 +18,18 @@
 #include "gfxRect.h"                    // for gfxRect
 #include "gfxTypes.h"                   // for gfxFloat
 #include "mozilla/gfx/BasePoint3D.h"    // for BasePoint3D
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nsTArray.h"                   // for nsTArray, etc
 #include "limits.h"
 #include "mozilla/Assertions.h"
 
+using namespace mozilla::gfx;
+
 namespace mozilla {
 namespace layers {
 
 enum LayerSortOrder {
   Undefined,
   ABeforeB,
   BBeforeA,
 };
@@ -73,18 +75,20 @@ static gfxFloat RecoverZDepth(const gfx3
  * in particular) and this generates the 'correct' looking ordering. For planes
  * that truely intersect, then there is no correct ordering and this remains
  * unsolved without changing our rendering code.
  */
 static LayerSortOrder CompareDepth(Layer* aOne, Layer* aTwo) {
   gfxRect ourRect = aOne->GetEffectiveVisibleRegion().GetBounds();
   gfxRect otherRect = aTwo->GetEffectiveVisibleRegion().GetBounds();
 
-  gfx3DMatrix ourTransform = aOne->GetTransform();
-  gfx3DMatrix otherTransform = aTwo->GetTransform();
+  gfx3DMatrix ourTransform;
+  To3DMatrix(aOne->GetTransform(), ourTransform);
+  gfx3DMatrix otherTransform;
+  To3DMatrix(aTwo->GetTransform(), otherTransform);
 
   // Transform both rectangles and project into 2d space.
   gfxQuad ourTransformedRect = ourTransform.TransformRect(ourRect);
   gfxQuad otherTransformedRect = otherTransform.TransformRect(otherRect);
 
   gfxRect ourBounds = ourTransformedRect.GetBounds();
   gfxRect otherBounds = otherTransformedRect.GetBounds();
 
--- a/gfx/layers/LayerTreeInvalidation.cpp
+++ b/gfx/layers/LayerTreeInvalidation.cpp
@@ -106,27 +106,27 @@ NotifySubdocumentInvalidationRecursive(L
 
 struct LayerPropertiesBase : public LayerProperties
 {
   LayerPropertiesBase(Layer* aLayer)
     : mLayer(aLayer)
     , mMaskLayer(nullptr)
     , mVisibleRegion(aLayer->GetVisibleRegion())
     , mInvalidRegion(aLayer->GetInvalidRegion())
-    , mTransform(aLayer->GetTransform())
     , mOpacity(aLayer->GetOpacity())
     , mUseClipRect(!!aLayer->GetClipRect())
   {
     MOZ_COUNT_CTOR(LayerPropertiesBase);
     if (aLayer->GetMaskLayer()) {
       mMaskLayer = CloneLayerTreePropertiesInternal(aLayer->GetMaskLayer());
     }
     if (mUseClipRect) {
       mClipRect = *aLayer->GetClipRect();
     }
+    gfx::To3DMatrix(aLayer->GetTransform(), mTransform);
   }
   LayerPropertiesBase()
     : mLayer(nullptr)
     , mMaskLayer(nullptr)
   {
     MOZ_COUNT_CTOR(LayerPropertiesBase);
   }
   ~LayerPropertiesBase()
@@ -136,17 +136,19 @@ struct LayerPropertiesBase : public Laye
   
   virtual nsIntRegion ComputeDifferences(Layer* aRoot, 
                                          NotifySubDocInvalidationFunc aCallback);
 
   virtual void MoveBy(const nsIntPoint& aOffset);
 
   nsIntRegion ComputeChange(NotifySubDocInvalidationFunc aCallback)
   {
-    bool transformChanged = !mTransform.FuzzyEqual(mLayer->GetTransform());
+    gfx3DMatrix transform;
+    gfx::To3DMatrix(mLayer->GetTransform(), transform);
+    bool transformChanged = !mTransform.FuzzyEqual(transform);
     Layer* otherMask = mLayer->GetMaskLayer();
     const nsIntRect* otherClip = mLayer->GetClipRect();
     nsIntRegion result;
     if ((mMaskLayer ? mMaskLayer->mLayer : nullptr) != otherMask ||
         (mUseClipRect != !!otherClip) ||
         mLayer->GetOpacity() != mOpacity ||
         transformChanged) 
     {
@@ -184,17 +186,19 @@ struct LayerPropertiesBase : public Laye
     }
 
     mLayer->ClearInvalidRect();
     return result;
   }
 
   nsIntRect NewTransformedBounds()
   {
-    return TransformRect(mLayer->GetVisibleRegion().GetBounds(), mLayer->GetTransform());
+    gfx3DMatrix transform;
+    gfx::To3DMatrix(mLayer->GetTransform(), transform);
+    return TransformRect(mLayer->GetVisibleRegion().GetBounds(), transform);
   }
 
   nsIntRect OldTransformedBounds()
   {
     return TransformRect(mVisibleRegion.GetBounds(), mTransform);
   }
 
   virtual nsIntRegion ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback) { return nsIntRect(); }
@@ -266,17 +270,19 @@ struct ContainerLayerProperties : public
           // |child| is new
           invalidateChildsCurrentArea = true;
         }
       } else {
         // |child| is new, or was reordered to a higher index
         invalidateChildsCurrentArea = true;
       }
       if (invalidateChildsCurrentArea) {
-        AddTransformedRegion(result, child->GetVisibleRegion(), child->GetTransform());
+        gfx3DMatrix transform;
+        gfx::To3DMatrix(child->GetTransform(), transform);
+        AddTransformedRegion(result, child->GetVisibleRegion(), transform);
         if (aCallback) {
           NotifySubdocumentInvalidationRecursive(child, aCallback);
         } else {
           ClearInvalidations(child);
         }
       }
     }
 
@@ -285,17 +291,19 @@ struct ContainerLayerProperties : public
       AddRegion(result, mChildren[i]->OldTransformedBounds());
       i++;
     }
 
     if (aCallback) {
       aCallback(container, result);
     }
 
-    return TransformRegion(result, mLayer->GetTransform());
+    gfx3DMatrix transform;
+    gfx::To3DMatrix(mLayer->GetTransform(), transform);
+    return TransformRegion(result, transform);
   }
 
   // The old list of children:
   nsAutoTArray<nsAutoPtr<LayerPropertiesBase>,1> mChildren;
 };
 
 struct ColorLayerProperties : public LayerPropertiesBase
 {
@@ -401,17 +409,19 @@ LayerPropertiesBase::ComputeDifferences(
 {
   NS_ASSERTION(aRoot, "Must have a layer tree to compare against!");
   if (mLayer != aRoot) {
     if (aCallback) {
       NotifySubdocumentInvalidationRecursive(aRoot, aCallback);
     } else {
       ClearInvalidations(aRoot);
     }
-    nsIntRect result = TransformRect(aRoot->GetVisibleRegion().GetBounds(), aRoot->GetTransform());
+    gfx3DMatrix transform;
+    gfx::To3DMatrix(aRoot->GetTransform(), transform);
+    nsIntRect result = TransformRect(aRoot->GetVisibleRegion().GetBounds(), transform);
     result = result.Union(OldTransformedBounds());
     return result;
   } else {
     return ComputeChange(aCallback);
   }
 }
   
 void 
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -612,24 +612,25 @@ Layer::CalculateScissorRect(const nsIntR
     gfx::Rect trScissor = aWorldTransform->TransformBounds(r);
     trScissor.Round();
     if (!gfxUtils::GfxRectToIntRect(ThebesRect(trScissor), &scissor))
       return nsIntRect(currentClip.TopLeft(), nsIntSize(0, 0));
   }
   return currentClip.Intersect(scissor);
 }
 
-const gfx3DMatrix
+const Matrix4x4
 Layer::GetTransform() const
 {
-  gfx3DMatrix transform = mTransform;
+  Matrix4x4 transform;
+  ToMatrix4x4(mTransform, transform);
   if (const ContainerLayer* c = AsContainerLayer()) {
     transform.Scale(c->GetPreXScale(), c->GetPreYScale(), 1.0f);
   }
-  transform.ScalePost(mPostXScale, mPostYScale, 1.0f);
+  transform = transform * Matrix4x4().Scale(mPostXScale, mPostYScale, 1.0f);
   return transform;
 }
 
 const Matrix4x4
 Layer::GetLocalTransform()
 {
   gfx3DMatrix transform;
   if (LayerComposite* shadow = AsLayerComposite())
@@ -692,23 +693,20 @@ Layer::GetEffectiveMixBlendMode()
 
 void
 Layer::ComputeEffectiveTransformForMaskLayer(const Matrix4x4& aTransformToSurface)
 {
   if (mMaskLayer) {
     mMaskLayer->mEffectiveTransform = aTransformToSurface;
 
 #ifdef DEBUG
-    gfxMatrix maskTranslation;
-    bool maskIs2D = mMaskLayer->GetTransform().CanDraw2D(&maskTranslation);
+    bool maskIs2D = mMaskLayer->GetTransform().CanDraw2D();
     NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
 #endif
-    Matrix4x4 maskTransform;
-    ToMatrix4x4(mMaskLayer->GetTransform(), maskTransform);
-    mMaskLayer->mEffectiveTransform = maskTransform * mMaskLayer->mEffectiveTransform;
+    mMaskLayer->mEffectiveTransform = mMaskLayer->GetTransform() * mMaskLayer->mEffectiveTransform;
   }
 }
 
 ContainerLayer::ContainerLayer(LayerManager* aManager, void* aImplData)
   : Layer(aManager, aImplData),
     mFirstChild(nullptr),
     mLastChild(nullptr),
     mPreXScale(1.0f),
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -862,18 +862,17 @@ public:
    * Ownership of aMaskLayer passes to this.
    * Typical use would be an ImageLayer with an alpha image used for masking.
    * See also ContainerState::BuildMaskLayer in FrameLayerBuilder.cpp.
    */
   void SetMaskLayer(Layer* aMaskLayer)
   {
 #ifdef DEBUG
     if (aMaskLayer) {
-      gfxMatrix maskTransform;
-      bool maskIs2D = aMaskLayer->GetTransform().CanDraw2D(&maskTransform);
+      bool maskIs2D = aMaskLayer->GetTransform().CanDraw2D();
       NS_ASSERTION(maskIs2D, "Mask layer has invalid transform.");
     }
 #endif
 
     if (mMaskLayer != aMaskLayer) {
       MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) MaskLayer", this));
       mMaskLayer = aMaskLayer;
       Mutated();
@@ -1046,17 +1045,17 @@ public:
   const EventRegions& GetEventRegions() const { return mEventRegions; }
   ContainerLayer* GetParent() { return mParent; }
   Layer* GetNextSibling() { return mNextSibling; }
   const Layer* GetNextSibling() const { return mNextSibling; }
   Layer* GetPrevSibling() { return mPrevSibling; }
   const Layer* GetPrevSibling() const { return mPrevSibling; }
   virtual Layer* GetFirstChild() const { return nullptr; }
   virtual Layer* GetLastChild() const { return nullptr; }
-  const gfx3DMatrix GetTransform() const;
+  const gfx::Matrix4x4 GetTransform() const;
   const gfx3DMatrix& GetBaseTransform() const { return mTransform; }
   float GetPostXScale() const { return mPostXScale; }
   float GetPostYScale() const { return mPostYScale; }
   bool GetIsFixedPosition() { return mIsFixedPosition; }
   bool GetIsStickyPosition() { return mStickyPositionData; }
   LayerPoint GetFixedPositionAnchor() { return mAnchor; }
   const LayerMargin& GetFixedPositionMargins() { return mMargins; }
   FrameMetrics::ViewID GetStickyScrollContainerId() { return mStickyPositionData->mScrollId; }
--- a/gfx/layers/ReadbackProcessor.cpp
+++ b/gfx/layers/ReadbackProcessor.cpp
@@ -41,29 +41,29 @@ ReadbackProcessor::BuildUpdates(Containe
       BuildUpdatesForLayer(static_cast<ReadbackLayer*>(l));
     }
   }
 }
 
 static Layer*
 FindBackgroundLayer(ReadbackLayer* aLayer, nsIntPoint* aOffset)
 {
-  gfxMatrix transform;
+  gfx::Matrix transform;
   if (!aLayer->GetTransform().Is2D(&transform) ||
       transform.HasNonIntegerTranslation())
     return nullptr;
-  nsIntPoint transformOffset(int32_t(transform.x0), int32_t(transform.y0));
+  nsIntPoint transformOffset(int32_t(transform._31), int32_t(transform._32));
 
   for (Layer* l = aLayer->GetPrevSibling(); l; l = l->GetPrevSibling()) {
-    gfxMatrix backgroundTransform;
+    gfx::Matrix backgroundTransform;
     if (!l->GetTransform().Is2D(&backgroundTransform) ||
-        backgroundTransform.HasNonIntegerTranslation())
+        gfx::ThebesMatrix(backgroundTransform).HasNonIntegerTranslation())
       return nullptr;
 
-    nsIntPoint backgroundOffset(int32_t(backgroundTransform.x0), int32_t(backgroundTransform.y0));
+    nsIntPoint backgroundOffset(int32_t(backgroundTransform._31), int32_t(backgroundTransform._32));
     nsIntRect rectInBackground(transformOffset - backgroundOffset, aLayer->GetSize());
     const nsIntRegion& visibleRegion = l->GetEffectiveVisibleRegion();
     if (!visibleRegion.Intersects(rectInBackground))
       continue;
     // Since l is present in the background, from here on we either choose l
     // or nothing.
     if (!visibleRegion.Contains(rectInBackground))
       return nullptr;
--- a/gfx/layers/composite/APZCTreeManager.cpp
+++ b/gfx/layers/composite/APZCTreeManager.cpp
@@ -209,17 +209,20 @@ APZCTreeManager::UpdatePanZoomController
         // In this case we intersect the composition bounds with that region.
         ScreenRect visible(container->GetFrameMetrics().mCompositionBounds);
         CSSRect touchSensitiveRegion;
         if (state->mController->GetTouchSensitiveRegion(&touchSensitiveRegion)) {
           visible = visible.Intersect(touchSensitiveRegion
                                       * container->GetFrameMetrics().LayersPixelsPerCSSPixel()
                                       * LayerToScreenScale(1.0));
         }
-        apzc->SetLayerHitTestData(visible, aTransform, aLayer->GetTransform());
+        gfx3DMatrix transform;
+        gfx::To3DMatrix(aLayer->GetTransform(), transform);
+
+        apzc->SetLayerHitTestData(visible, aTransform, transform);
         APZC_LOG("Setting rect(%f %f %f %f) as visible region for APZC %p\n", visible.x, visible.y,
                                                                               visible.width, visible.height,
                                                                               apzc);
 
         // Bind the APZC instance into the tree of APZCs
         if (aNextSibling) {
           aNextSibling->SetPrevSibling(apzc);
         } else if (aParent) {
@@ -255,17 +258,19 @@ APZCTreeManager::UpdatePanZoomController
   }
 
   // Accumulate the CSS transform between layers that have an APZC, but exclude any
   // any layers that do have an APZC, and reset the accumulation at those layers.
   if (apzc) {
     aTransform = gfx3DMatrix();
   } else {
     // Multiply child layer transforms on the left so they get applied first
-    aTransform = aLayer->GetTransform() * aTransform;
+    gfx3DMatrix matrix;
+    gfx::To3DMatrix(aLayer->GetTransform(), matrix);
+    aTransform = matrix * aTransform;
   }
 
   uint64_t childLayersId = (aLayer->AsRefLayer() ? aLayer->AsRefLayer()->GetReferentId() : aLayersId);
   // If there's no APZC at this level, any APZCs for our child layers will
   // have our siblings as siblings.
   AsyncPanZoomController* next = apzc ? nullptr : aNextSibling;
   for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) {
     next = UpdatePanZoomControllerTree(aCompositor, child, childLayersId, aTransform, aParent, next,
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -118,53 +118,54 @@ AsyncCompositionManager::ComputeRotation
   if (!mTargetConfig.naturalBounds().IsEmpty()) {
     mLayerManager->SetWorldTransform(
       ComputeTransformForRotation(mTargetConfig.naturalBounds(),
                                   mTargetConfig.rotation()));
   }
 }
 
 static bool
-GetBaseTransform2D(Layer* aLayer, gfxMatrix* aTransform)
+GetBaseTransform2D(Layer* aLayer, Matrix* aTransform)
 {
   // Start with the animated transform if there is one
-  gfx3DMatrix localTransform;
-  To3DMatrix(aLayer->GetLocalTransform(), localTransform);
   return (aLayer->AsLayerComposite()->GetShadowTransformSetByAnimation() ?
-          localTransform : aLayer->GetTransform()).Is2D(aTransform);
+          aLayer->GetLocalTransform() : aLayer->GetTransform()).Is2D(aTransform);
 }
 
 static void
 TranslateShadowLayer2D(Layer* aLayer,
                        const gfxPoint& aTranslation)
 {
-  gfxMatrix layerTransform;
+  Matrix layerTransform;
   if (!GetBaseTransform2D(aLayer, &layerTransform)) {
     return;
   }
 
   // Apply the 2D translation to the layer transform.
-  layerTransform.x0 += aTranslation.x;
-  layerTransform.y0 += aTranslation.y;
+  layerTransform._31 += aTranslation.x;
+  layerTransform._32 += aTranslation.y;
 
   // The transform already takes the resolution scale into account.  Since we
   // will apply the resolution scale again when computing the effective
   // transform, we must apply the inverse resolution scale here.
-  gfx3DMatrix layerTransform3D = gfx3DMatrix::From2D(layerTransform);
+  Matrix4x4 layerTransform3D = Matrix4x4::From2D(layerTransform);
   if (ContainerLayer* c = aLayer->AsContainerLayer()) {
     layerTransform3D.Scale(1.0f/c->GetPreXScale(),
                            1.0f/c->GetPreYScale(),
                            1);
   }
-  layerTransform3D.ScalePost(1.0f/aLayer->GetPostXScale(),
-                             1.0f/aLayer->GetPostYScale(),
-                             1);
+  layerTransform3D = layerTransform3D *
+    Matrix4x4().Scale(1.0f/aLayer->GetPostXScale(),
+                      1.0f/aLayer->GetPostYScale(),
+                      1);
 
+  gfx3DMatrix matrix;
+  To3DMatrix(layerTransform3D, matrix);
   LayerComposite* layerComposite = aLayer->AsLayerComposite();
-  layerComposite->SetShadowTransform(layerTransform3D);
+  layerComposite->SetShadowTransform(matrix);
   layerComposite->SetShadowTransformSetByAnimation(false);
 
   const nsIntRect* clipRect = aLayer->GetClipRect();
   if (clipRect) {
     nsIntRect transformedClipRect(*clipRect);
     transformedClipRect.MoveBy(aTranslation.x, aTranslation.y);
     layerComposite->SetShadowClipRect(&transformedClipRect);
   }
@@ -172,21 +173,21 @@ TranslateShadowLayer2D(Layer* aLayer,
 
 static bool
 AccumulateLayerTransforms2D(Layer* aLayer,
                             Layer* aAncestor,
                             gfxMatrix& aMatrix)
 {
   // Accumulate the transforms between this layer and the subtree root layer.
   for (Layer* l = aLayer; l && l != aAncestor; l = l->GetParent()) {
-    gfxMatrix l2D;
+    Matrix l2D;
     if (!GetBaseTransform2D(l, &l2D)) {
       return false;
     }
-    aMatrix.Multiply(l2D);
+    aMatrix.Multiply(ThebesMatrix(l2D));
   }
 
   return true;
 }
 
 static LayerPoint
 GetLayerFixedMarginsOffset(Layer* aLayer,
                            const LayerMargin& aFixedLayerMargins)
@@ -267,49 +268,49 @@ AsyncCompositionManager::AlignFixedAndSt
     if (newCumulativeTransform.IsSingular()) {
       return;
     }
     gfxMatrix newCumulativeTransformInverse = newCumulativeTransform;
     newCumulativeTransformInverse.Invert();
 
     // Now work out the translation necessary to make sure the layer doesn't
     // move given the new sub-tree root transform.
-    gfxMatrix layerTransform;
+    Matrix layerTransform;
     if (!GetBaseTransform2D(aLayer, &layerTransform)) {
       return;
     }
 
     // Calculate any offset necessary, in previous transform sub-tree root
     // space. This is used to make sure fixed position content respects
     // content document fixed position margins.
     LayerPoint offsetInOldSubtreeLayerSpace = GetLayerFixedMarginsOffset(aLayer, aFixedLayerMargins);
 
     // Add the above offset to the anchor point so we can offset the layer by
     // and amount that's specified in old subtree layer space.
     const LayerPoint& anchorInOldSubtreeLayerSpace = aLayer->GetFixedPositionAnchor();
     LayerPoint offsetAnchorInOldSubtreeLayerSpace = anchorInOldSubtreeLayerSpace + offsetInOldSubtreeLayerSpace;
 
     // Add the local layer transform to the two points to make the equation
     // below this section more convenient.
-    gfxPoint anchor(anchorInOldSubtreeLayerSpace.x, anchorInOldSubtreeLayerSpace.y);
-    gfxPoint offsetAnchor(offsetAnchorInOldSubtreeLayerSpace.x, offsetAnchorInOldSubtreeLayerSpace.y);
-    gfxPoint locallyTransformedAnchor = layerTransform.Transform(anchor);
-    gfxPoint locallyTransformedOffsetAnchor = layerTransform.Transform(offsetAnchor);
+    Point anchor(anchorInOldSubtreeLayerSpace.x, anchorInOldSubtreeLayerSpace.y);
+    Point offsetAnchor(offsetAnchorInOldSubtreeLayerSpace.x, offsetAnchorInOldSubtreeLayerSpace.y);
+    Point locallyTransformedAnchor = layerTransform * anchor;
+    Point locallyTransformedOffsetAnchor = layerTransform * offsetAnchor;
 
     // Transforming the locallyTransformedAnchor by oldCumulativeTransform
     // returns the layer's anchor point relative to the parent of
     // aTransformedSubtreeRoot, before the new transform was applied.
     // Then, applying newCumulativeTransformInverse maps that point relative
     // to the layer's parent, which is the same coordinate space as
     // locallyTransformedAnchor again, allowing us to subtract them and find
     // out the offset necessary to make sure the layer stays stationary.
     gfxPoint oldAnchorPositionInNewSpace =
       newCumulativeTransformInverse.Transform(
-        oldCumulativeTransform.Transform(locallyTransformedOffsetAnchor));
-    gfxPoint translation = oldAnchorPositionInNewSpace - locallyTransformedAnchor;
+        oldCumulativeTransform.Transform(ThebesPoint(locallyTransformedOffsetAnchor)));
+    gfxPoint translation = oldAnchorPositionInNewSpace - ThebesPoint(locallyTransformedAnchor);
 
     if (aLayer->GetIsStickyPosition()) {
       // For sticky positioned layers, the difference between the two rectangles
       // defines a pair of translation intervals in each dimension through which
       // the layer should not move relative to the scroll container. To
       // accomplish this, we limit each dimension of the |translation| to that
       // part of it which overlaps those intervals.
       const LayerRect& stickyOuter = aLayer->GetStickyScrollRangeOuter();
@@ -330,17 +331,19 @@ AsyncCompositionManager::AlignFixedAndSt
   }
 
   // Fixed layers are relative to their nearest scrollable layer, so when we
   // encounter a scrollable layer, reset the transform to that layer and remove
   // the fixed margins.
   if (aLayer->AsContainerLayer() &&
       aLayer->AsContainerLayer()->GetFrameMetrics().IsScrollable() &&
       aLayer != aTransformedSubtreeRoot) {
-    AlignFixedAndStickyLayers(aLayer, aLayer, aLayer->GetTransform(), LayerMargin(0, 0, 0, 0));
+    gfx3DMatrix matrix;
+    To3DMatrix(aLayer->GetTransform(), matrix);
+    AlignFixedAndStickyLayers(aLayer, aLayer, matrix, LayerMargin(0, 0, 0, 0));
     return;
   }
 
   for (Layer* child = aLayer->GetFirstChild();
        child; child = child->GetNextSibling()) {
     AlignFixedAndStickyLayers(child, aTransformedSubtreeRoot,
                               aPreviousTransformForRoot, aFixedLayerMargins);
   }
@@ -487,17 +490,18 @@ AsyncCompositionManager::ApplyAsyncConte
 
   ContainerLayer* container = aLayer->AsContainerLayer();
   if (!container) {
     return appliedTransform;
   }
 
   if (AsyncPanZoomController* controller = container->GetAsyncPanZoomController()) {
     LayerComposite* layerComposite = aLayer->AsLayerComposite();
-    gfx3DMatrix oldTransform = aLayer->GetTransform();
+    gfx3DMatrix oldTransform;
+    To3DMatrix(aLayer->GetTransform(), oldTransform);
 
     ViewTransform treeTransform;
     ScreenPoint scrollOffset;
     *aWantNextFrame |=
       controller->SampleContentTransformForFrame(aCurrentFrame,
                                                  &treeTransform,
                                                  scrollOffset);
 
@@ -512,17 +516,19 @@ AsyncCompositionManager::ApplyAsyncConte
                      mIsFirstPaint, fixedLayerMargins, offset);
 
     mIsFirstPaint = false;
     mLayersUpdated = false;
 
     // Apply the render offset
     mLayerManager->GetCompositor()->SetScreenRenderOffset(offset);
 
-    gfx3DMatrix transform(gfx3DMatrix(treeTransform) * aLayer->GetTransform());
+    gfx3DMatrix transform;
+    To3DMatrix(aLayer->GetTransform(), transform);
+    transform = gfx3DMatrix(treeTransform) * transform;
     // GetTransform already takes the pre- and post-scale into account.  Since we
     // will apply the pre- and post-scale again when computing the effective
     // transform, we must apply the inverses here.
     transform.Scale(1.0f/container->GetPreXScale(),
                     1.0f/container->GetPreYScale(),
                     1);
     transform.ScalePost(1.0f/aLayer->GetPostXScale(),
                         1.0f/aLayer->GetPostYScale(),
@@ -605,17 +611,19 @@ AsyncCompositionManager::ApplyAsyncTrans
       scrollbarTransform.TranslatePost(gfxPoint3D(0, -transientTransform._42 * scale, 0));
     }
     if (aLayer->GetScrollbarDirection() == Layer::HORIZONTAL) {
       float scale = metrics.CalculateCompositedRectInCssPixels().width / metrics.mScrollableRect.width;
       scrollbarTransform.ScalePost(1.f / transientTransform.GetXScale(), 1.f, 1.f);
       scrollbarTransform.TranslatePost(gfxPoint3D(-transientTransform._41 * scale, 0, 0));
     }
 
-    gfx3DMatrix transform = scrollbarTransform * aLayer->GetTransform();
+    gfx3DMatrix transform;
+    To3DMatrix(aLayer->GetTransform(), transform);
+    transform = scrollbarTransform * transform;
     // GetTransform already takes the pre- and post-scale into account.  Since we
     // will apply the pre- and post-scale again when computing the effective
     // transform, we must apply the inverses here.
     transform.Scale(1.0f/aLayer->GetPreXScale(),
                     1.0f/aLayer->GetPreYScale(),
                     1);
     transform.ScalePost(1.0f/aLayer->GetPostXScale(),
                         1.0f/aLayer->GetPostYScale(),
@@ -630,17 +638,18 @@ void
 AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer)
 {
   LayerComposite* layerComposite = aLayer->AsLayerComposite();
   ContainerLayer* container = aLayer->AsContainerLayer();
 
   const FrameMetrics& metrics = container->GetFrameMetrics();
   // We must apply the resolution scale before a pan/zoom transform, so we call
   // GetTransform here.
-  const gfx3DMatrix& currentTransform = aLayer->GetTransform();
+  gfx3DMatrix currentTransform;
+  To3DMatrix(aLayer->GetTransform(), currentTransform);
   gfx3DMatrix oldTransform = currentTransform;
 
   gfx3DMatrix treeTransform;
 
   CSSToLayerScale geckoZoom = metrics.LayersPixelsPerCSSPixel();
 
   LayerIntPoint scrollOffsetLayerPixels = RoundedToInt(metrics.mScrollOffset * geckoZoom);
 
--- a/gfx/tests/gtest/TestLayers.cpp
+++ b/gfx/tests/gtest/TestLayers.cpp
@@ -120,17 +120,17 @@ TEST(Layers, Defaults) {
   ASSERT_EQ(nullptr, layer.GetPrevSibling());
   ASSERT_EQ(nullptr, layer.GetFirstChild());
   ASSERT_EQ(nullptr, layer.GetLastChild());
 }
 
 TEST(Layers, Transform) {
   TestContainerLayer layer(nullptr);
 
-  gfx3DMatrix identity;
+  Matrix4x4 identity;
   ASSERT_EQ(true, identity.IsIdentity());
 
   ASSERT_EQ(identity, layer.GetTransform());
 }
 
 TEST(Layers, Type) {
   TestContainerLayer layer(nullptr);
   ASSERT_EQ(nullptr, layer.AsThebesLayer());
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1547,17 +1547,18 @@ AppUnitsPerDevPixel(nsDisplayItem* aItem
  * coordinate space
  * @param aRestrictToRect the rect to restrict the visible region to, in the
  * parent's coordinate system
  */
 static void
 SetVisibleRegionForLayer(Layer* aLayer, const nsIntRegion& aLayerVisibleRegion,
                          const nsIntRect& aRestrictToRect)
 {
-  gfx3DMatrix transform = aLayer->GetTransform();
+  gfx3DMatrix transform;
+  To3DMatrix(aLayer->GetTransform(), transform);
 
   // if 'transform' is not invertible, then nothing will be displayed
   // for the layer, so it doesn't really matter what we do here
   gfxRect itemVisible(aRestrictToRect.x, aRestrictToRect.y,
                       aRestrictToRect.width, aRestrictToRect.height);
   gfxRect layerVisible = transform.Inverse().ProjectRectBounds(itemVisible);
   layerVisible.RoundOut();
 
@@ -1709,21 +1710,23 @@ ContainerState::SetFixedPositionLayerDat
 
   nsLayoutUtils::SetFixedPositionLayerData(aLayer,
       viewportFrame, viewportSize, aFixedPosFrame, presContext, mParameters);
 }
 
 static gfx3DMatrix
 GetTransformToRoot(Layer* aLayer)
 {
-  gfx3DMatrix transform = aLayer->GetTransform();
+  Matrix4x4 transform = aLayer->GetTransform();
   for (Layer* l = aLayer->GetParent(); l; l = l->GetParent()) {
     transform = transform * l->GetTransform();
   }
-  return transform;
+  gfx3DMatrix result;
+  To3DMatrix(transform, result);
+  return result;
 }
 
 static void
 AddTransformedBoundsToRegion(const nsIntRegion& aRegion,
                              const gfx3DMatrix& aTransform,
                              nsIntRegion* aDest)
 {
   nsIntRect bounds = aRegion.GetBounds();
@@ -1804,17 +1807,17 @@ ContainerState::PopThebesLayerData()
     data->mLayer->SetVisibleRegion(nsIntRegion());
     data->mLayer->SetEventRegions(EventRegions());
   } else {
     layer = data->mLayer;
     imageContainer = nullptr;
     layer->SetClipRect(nullptr);
   }
 
-  gfxMatrix transform;
+  Matrix transform;
   if (!layer->GetTransform().Is2D(&transform)) {
     NS_ERROR("Only 2D transformations currently supported");
   }
 
   // ImageLayers are already configured with a visible region
   if (!imageContainer) {
     NS_ASSERTION(!transform.HasNonIntegerTranslation(),
                  "Matrix not just an integer translation?");
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -222,17 +222,19 @@ BuildListForLayer(Layer* aLayer,
     // Calculate transform for this layer.
     nsContentView* view =
       aRootFrameLoader->GetCurrentRemoteFrame()->GetContentView(scrollId);
     // XXX why don't we include aLayer->GetTransform() in the inverse-scale here?
     // This seems wrong, but it doesn't seem to cause bugs!
     gfx3DMatrix applyTransform = ComputeShadowTreeTransform(
       aSubdocFrame, aRootFrameLoader, metrics, view->GetViewConfig(),
       1 / GetXScale(aTransform), 1 / GetYScale(aTransform));
-    transform = applyTransform * aLayer->GetTransform() * aTransform;
+    gfx3DMatrix layerTransform;
+    To3DMatrix(aLayer->GetTransform(), layerTransform);
+    transform = applyTransform * layerTransform * aTransform;
 
     // As mentioned above, bounds calculation also depends on the scale
     // of this layer.
     gfx3DMatrix tmpTransform = aTransform;
     Scale(tmpTransform, GetXScale(applyTransform), GetYScale(applyTransform));
 
     // Calculate rect for this layer based on aTransform.
     nsRect bounds;
@@ -241,17 +243,19 @@ BuildListForLayer(Layer* aLayer,
       nscoord auPerDevPixel = aSubdocFrame->PresContext()->AppUnitsPerDevPixel();
       ApplyTransform(bounds, tmpTransform, auPerDevPixel);
     }
 
     aShadowTree.AppendToTop(
       new (aBuilder) nsDisplayRemoteShadow(aBuilder, aSubdocFrame, bounds, scrollId));
 
   } else {
-    transform = aLayer->GetTransform() * aTransform;
+    gfx3DMatrix layerTransform;
+    To3DMatrix(aLayer->GetTransform(), layerTransform);
+    transform = layerTransform * aTransform;
   }
 
   for (Layer* child = aLayer->GetFirstChild(); child;
        child = child->GetNextSibling()) {
     BuildListForLayer(child, aRootFrameLoader, transform,
                       aBuilder, aShadowTree, aSubdocFrame);
   }
 }
@@ -266,25 +270,27 @@ TransformShadowTree(nsDisplayListBuilder
 {
   LayerComposite* shadow = aLayer->AsLayerComposite();
   shadow->SetShadowClipRect(aLayer->GetClipRect());
   shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
   shadow->SetShadowOpacity(aLayer->GetOpacity());
 
   const FrameMetrics* metrics = GetFrameMetrics(aLayer);
 
-  gfx3DMatrix shadowTransform = aLayer->GetTransform();
+  gfx3DMatrix shadowTransform;
+  To3DMatrix(aLayer->GetTransform(), shadowTransform);
   ViewTransform layerTransform = aTransform;
 
   if (metrics && metrics->IsScrollable()) {
     const ViewID scrollId = metrics->mScrollId;
     const nsContentView* view =
       aFrameLoader->GetCurrentRemoteFrame()->GetContentView(scrollId);
     NS_ABORT_IF_FALSE(view, "Array of views should be consistent with layer tree");
-    const gfx3DMatrix& currentTransform = aLayer->GetTransform();
+    gfx3DMatrix currentTransform;
+    To3DMatrix(aLayer->GetTransform(), currentTransform);
 
     const ViewConfig& config = view->GetViewConfig();
     // With temporary scale we should compensate translation
     // using temporary scale value
     aTempScaleDiffX *= GetXScale(shadowTransform) * config.mXScale;
     aTempScaleDiffY *= GetYScale(shadowTransform) * config.mYScale;
     ViewTransform viewTransform = ComputeShadowTreeTransform(
       aFrame, aFrameLoader, metrics, view->GetViewConfig(),
@@ -370,17 +376,18 @@ BuildViewMap(ViewMap& oldContentViews, V
              float aXScale = 1, float aYScale = 1,
              float aAccConfigXScale = 1, float aAccConfigYScale = 1)
 {
   ContainerLayer* container = aLayer->AsContainerLayer();
   if (!container)
     return;
   const FrameMetrics metrics = container->GetFrameMetrics();
   const ViewID scrollId = metrics.mScrollId;
-  const gfx3DMatrix transform = aLayer->GetTransform();
+  gfx3DMatrix transform;
+  To3DMatrix(aLayer->GetTransform(), transform);
   aXScale *= GetXScale(transform);
   aYScale *= GetYScale(transform);
 
   if (metrics.IsScrollable()) {
     nscoord auPerDevPixel = aFrameLoader->GetPrimaryFrameOfOwningContent()
                                         ->PresContext()->AppUnitsPerDevPixel();
     nscoord auPerCSSPixel = auPerDevPixel * metrics.mDevPixelsPerCSSPixel.scale;
     nsContentView* view = FindViewForId(oldContentViews, scrollId);