Backed out changeset a96930f1e26b (bug 1055741)
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 13 Nov 2014 11:47:31 +0100
changeset 239807 208a6172cd5d5f37376b5b3b2a6e1e8828051985
parent 239806 622448fd70adf68d7d0f4b98a4e1ba7cca84454d
child 239808 aa714a6555a09552c714a546e82da8aea742097e
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1055741
milestone36.0a1
backs outa96930f1e26b8d4aa31e331df9493cce81a2e085
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
Backed out changeset a96930f1e26b (bug 1055741)
dom/ipc/TabChild.cpp
gfx/ipc/GfxMessageUtils.h
gfx/layers/FrameMetrics.h
gfx/layers/LayersLogging.cpp
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/APZCTreeManager.h
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/src/AsyncPanZoomController.h
gfx/layers/apz/src/Axis.cpp
gfx/layers/apz/src/Axis.h
gfx/layers/apz/src/GestureEventListener.cpp
gfx/layers/apz/src/GestureEventListener.h
gfx/layers/apz/util/APZCCallbackHelper.cpp
gfx/layers/client/ClientLayerManager.cpp
gfx/layers/client/ClientTiledPaintedLayer.cpp
gfx/layers/client/TiledContentClient.cpp
gfx/layers/composite/AsyncCompositionManager.cpp
gfx/layers/composite/AsyncCompositionManager.h
gfx/tests/gtest/TestAsyncPanZoomController.cpp
layout/base/UnitTransforms.h
layout/base/Units.h
layout/base/nsDisplayList.cpp
layout/base/nsLayoutUtils.cpp
widget/InputData.h
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/windows/winrt/APZController.cpp
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -236,26 +236,26 @@ void
 TabChildBase::InitializeRootMetrics()
 {
   // Calculate a really simple resolution that we probably won't
   // be keeping, as well as putting the scroll offset back to
   // the top-left of the page.
   mLastRootMetrics.SetViewport(CSSRect(CSSPoint(), kDefaultViewportSize));
   mLastRootMetrics.mCompositionBounds = ParentLayerRect(
       ParentLayerPoint(),
-      ParentLayerSize(ViewAs<ParentLayerPixel>(mInnerSize, PixelCastJustification::ScreenIsParentLayerForRoot)));
+      ParentLayerSize(ViewAs<ParentLayerPixel>(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot)));
   mLastRootMetrics.SetZoom(mLastRootMetrics.CalculateIntrinsicScale());
   mLastRootMetrics.mDevPixelsPerCSSPixel = WebWidget()->GetDefaultScale();
-  // We use ParentLayerToLayerScale(1) below in order to turn the
+  // We use ScreenToLayerScale(1) below in order to turn the
   // async zoom amount into the gecko zoom amount.
   mLastRootMetrics.mCumulativeResolution =
-    mLastRootMetrics.GetZoom() / mLastRootMetrics.mDevPixelsPerCSSPixel * ParentLayerToLayerScale(1);
+    mLastRootMetrics.GetZoom() / mLastRootMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
   // This is the root layer, so the cumulative resolution is the same
   // as the resolution.
-  mLastRootMetrics.mPresShellResolution = mLastRootMetrics.mCumulativeResolution.scale;
+  mLastRootMetrics.mPresShellResolution = mLastRootMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1);
   mLastRootMetrics.SetScrollOffset(CSSPoint(0, 0));
 
   TABC_LOG("After InitializeRootMetrics, mLastRootMetrics is %s\n",
     Stringify(mLastRootMetrics).c_str());
 }
 
 void
 TabChildBase::SetCSSViewport(const CSSSize& aSize)
@@ -289,30 +289,16 @@ TabChildBase::GetPageSize(nsCOMPtr<nsIDo
   if (bodyDOMElement) {
     bodyWidth = bodyDOMElement->ScrollWidth();
     bodyHeight = bodyDOMElement->ScrollHeight();
   }
   return CSSSize(std::max(htmlWidth, bodyWidth),
                  std::max(htmlHeight, bodyHeight));
 }
 
-// For the root frame, Screen and ParentLayer pixels are interchangeable.
-// nsViewportInfo stores zoom values as CSSToScreenScale (because it's a
-// data structure specific to the root frame), while FrameMetrics and
-// ZoomConstraints store zoom values as CSSToParentLayerScale (because they
-// are not specific to the root frame). We define convenience functions for
-// converting between the two. As the name suggests, they should only be used
-// when dealing with the root frame!
-CSSToScreenScale ConvertScaleForRoot(CSSToParentLayerScale aScale) {
-  return ViewTargetAs<ScreenPixel>(aScale, PixelCastJustification::ScreenIsParentLayerForRoot);
-}
-CSSToParentLayerScale ConvertScaleForRoot(CSSToScreenScale aScale) {
-  return ViewTargetAs<ParentLayerPixel>(aScale, PixelCastJustification::ScreenIsParentLayerForRoot);
-}
-
 bool
 TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize)
 {
   if (!IsAsyncPanZoomEnabled()) {
     return false;
   }
 
   TABC_LOG("HandlePossibleViewportChange aOldScreenSize=%s mInnerSize=%s\n",
@@ -325,18 +311,18 @@ TabChildBase::HandlePossibleViewportChan
   uint32_t presShellId = 0;
   mozilla::layers::FrameMetrics::ViewID viewId = FrameMetrics::NULL_SCROLL_ID;
   bool scrollIdentifiersValid = APZCCallbackHelper::GetOrCreateScrollIdentifiers(
         document->GetDocumentElement(), &presShellId, &viewId);
   if (scrollIdentifiersValid) {
     ZoomConstraints constraints(
       viewportInfo.IsZoomAllowed(),
       viewportInfo.IsDoubleTapZoomAllowed(),
-      ConvertScaleForRoot(viewportInfo.GetMinZoom()),
-      ConvertScaleForRoot(viewportInfo.GetMaxZoom()));
+      viewportInfo.GetMinZoom(),
+      viewportInfo.GetMaxZoom());
     DoUpdateZoomConstraints(presShellId,
                             viewId,
                             /* isRoot = */ true,
                             constraints);
   }
 
   float screenW = mInnerSize.width;
   float screenH = mInnerSize.height;
@@ -375,17 +361,17 @@ TabChildBase::HandlePossibleViewportChan
   if (oldScreenSize == ScreenIntSize()) {
     oldScreenSize = mInnerSize;
   }
 
   FrameMetrics metrics(mLastRootMetrics);
   metrics.SetViewport(CSSRect(CSSPoint(), viewport));
   metrics.mCompositionBounds = ParentLayerRect(
       ParentLayerPoint(),
-      ParentLayerSize(ViewAs<ParentLayerPixel>(mInnerSize, PixelCastJustification::ScreenIsParentLayerForRoot)));
+      ParentLayerSize(ViewAs<ParentLayerPixel>(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot)));
   metrics.SetRootCompositionSize(
       ScreenSize(mInnerSize) * ScreenToLayoutDeviceScale(1.0f) / metrics.mDevPixelsPerCSSPixel);
 
   // This change to the zoom accounts for all types of changes I can conceive:
   // 1. screen size changes, CSS viewport does not (pages with no meta viewport
   //    or a fixed size viewport)
   // 2. screen size changes, CSS viewport also does (pages with a device-width
   //    viewport)
@@ -405,41 +391,39 @@ TabChildBase::HandlePossibleViewportChan
   // by AsyncPanZoomController and causes a blurry flash.
   bool isFirstPaint;
   nsresult rv = utils->GetIsFirstPaint(&isFirstPaint);
   if (NS_FAILED(rv) || isFirstPaint) {
     // FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of
     // 0.0 to mean "did not calculate a zoom".  In that case, we default
     // it to the intrinsic scale.
     if (viewportInfo.GetDefaultZoom().scale < 0.01f) {
-      viewportInfo.SetDefaultZoom(ConvertScaleForRoot(metrics.CalculateIntrinsicScale()));
+      viewportInfo.SetDefaultZoom(metrics.CalculateIntrinsicScale());
     }
 
     CSSToScreenScale defaultZoom = viewportInfo.GetDefaultZoom();
     MOZ_ASSERT(viewportInfo.GetMinZoom() <= defaultZoom &&
                defaultZoom <= viewportInfo.GetMaxZoom());
-    metrics.SetZoom(ConvertScaleForRoot(defaultZoom));
+    metrics.SetZoom(defaultZoom);
 
     metrics.SetScrollId(viewId);
   }
 
   if (nsIPresShell* shell = document->GetShell()) {
     if (nsPresContext* context = shell->GetPresContext()) {
       metrics.mDevPixelsPerCSSPixel = CSSToLayoutDeviceScale(
         (float)nsPresContext::AppUnitsPerCSSPixel() / context->AppUnitsPerDevPixel());
     }
   }
 
-  metrics.mCumulativeResolution = metrics.GetZoom()
-                                / metrics.mDevPixelsPerCSSPixel
-                                * ParentLayerToLayerScale(1);
+  metrics.mCumulativeResolution = metrics.GetZoom() / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
   // This is the root layer, so the cumulative resolution is the same
   // as the resolution.
-  metrics.mPresShellResolution = metrics.mCumulativeResolution.scale;
-  utils->SetResolution(metrics.mPresShellResolution, metrics.mPresShellResolution);
+  metrics.mPresShellResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1);
+  utils->SetResolution(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale);
 
   CSSSize scrollPort = metrics.CalculateCompositedSizeInCssPixels();
   utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height);
 
   // The call to GetPageSize forces a resize event to content, so we need to
   // make sure that we have the right CSS viewport and
   // scrollPositionClampingScrollPortSize set up before that happens.
 
@@ -451,35 +435,35 @@ TabChildBase::HandlePossibleViewportChan
   metrics.mScrollableRect = CSSRect(CSSPoint(), pageSize);
 
   // Calculate a display port _after_ having a scrollable rect because the
   // display port is clamped to the scrollable rect.
   metrics.SetDisplayPortMargins(APZCTreeManager::CalculatePendingDisplayPort(
     // The page must have been refreshed in some way such as a new document or
     // new CSS viewport, so we know that there's no velocity, acceleration, and
     // we have no idea how long painting will take.
-    metrics, ParentLayerPoint(0.0f, 0.0f), 0.0));
+    metrics, ScreenPoint(0.0f, 0.0f), 0.0));
   metrics.SetUseDisplayPortMargins();
 
   // Force a repaint with these metrics. This, among other things, sets the
   // displayport, so we start with async painting.
   mLastRootMetrics = ProcessUpdateFrame(metrics);
 
   if (viewportInfo.IsZoomAllowed() && scrollIdentifiersValid) {
     // If the CSS viewport is narrower than the screen (i.e. width <= device-width)
     // then we disable double-tap-to-zoom behaviour.
     bool allowDoubleTapZoom = (viewport.width > screenW / metrics.mDevPixelsPerCSSPixel.scale);
     if (allowDoubleTapZoom != viewportInfo.IsDoubleTapZoomAllowed()) {
       viewportInfo.SetAllowDoubleTapZoom(allowDoubleTapZoom);
 
       ZoomConstraints constraints(
         viewportInfo.IsZoomAllowed(),
         viewportInfo.IsDoubleTapZoomAllowed(),
-        ConvertScaleForRoot(viewportInfo.GetMinZoom()),
-        ConvertScaleForRoot(viewportInfo.GetMaxZoom()));
+        viewportInfo.GetMinZoom(),
+        viewportInfo.GetMaxZoom());
       DoUpdateZoomConstraints(presShellId,
                               viewId,
                               /* isRoot = */ true,
                               constraints);
     }
   }
 
   return true;
@@ -918,18 +902,18 @@ TabChild::Observe(nsISupports *aSubject,
         mContentDocumentIsDisplayed = true;
 
         // In some cases before-first-paint gets called before
         // RecvUpdateDimensions is called and therefore before we have an
         // mInnerSize value set. In such cases defer initializing the viewport
         // until we we get an inner size.
         if (HasValidInnerSize()) {
           InitializeRootMetrics();
-          utils->SetResolution(mLastRootMetrics.mPresShellResolution,
-                               mLastRootMetrics.mPresShellResolution);
+          utils->SetResolution(mLastRootMetrics.mPresShellResolution.scale,
+                               mLastRootMetrics.mPresShellResolution.scale);
           HandlePossibleViewportChange(mInnerSize);
         }
       }
     }
   }
 
   return NS_OK;
 }
--- a/gfx/ipc/GfxMessageUtils.h
+++ b/gfx/ipc/GfxMessageUtils.h
@@ -747,16 +747,17 @@ struct ParamTraits<mozilla::layers::Fram
     WriteParam(aMsg, aParam.mDevPixelsPerCSSPixel);
     WriteParam(aMsg, aParam.mMayHaveTouchListeners);
     WriteParam(aMsg, aParam.mMayHaveTouchCaret);
     WriteParam(aMsg, aParam.mPresShellId);
     WriteParam(aMsg, aParam.mIsRoot);
     WriteParam(aMsg, aParam.mHasScrollgrab);
     WriteParam(aMsg, aParam.mUpdateScrollOffset);
     WriteParam(aMsg, aParam.mScrollGeneration);
+    WriteParam(aMsg, aParam.mTransformScale);
     WriteParam(aMsg, aParam.mExtraResolution);
     WriteParam(aMsg, aParam.mBackgroundColor);
     WriteParam(aMsg, aParam.mDoSmoothScroll);
     WriteParam(aMsg, aParam.mSmoothScrollOffset);
     WriteParam(aMsg, aParam.GetContentDescription());
   }
 
   static bool ReadContentDescription(const Message* aMsg, void** aIter, paramType* aResult)
@@ -788,16 +789,17 @@ struct ParamTraits<mozilla::layers::Fram
             ReadParam(aMsg, aIter, &aResult->mDevPixelsPerCSSPixel) &&
             ReadParam(aMsg, aIter, &aResult->mMayHaveTouchListeners) &&
             ReadParam(aMsg, aIter, &aResult->mMayHaveTouchCaret) &&
             ReadParam(aMsg, aIter, &aResult->mPresShellId) &&
             ReadParam(aMsg, aIter, &aResult->mIsRoot) &&
             ReadParam(aMsg, aIter, &aResult->mHasScrollgrab) &&
             ReadParam(aMsg, aIter, &aResult->mUpdateScrollOffset) &&
             ReadParam(aMsg, aIter, &aResult->mScrollGeneration) &&
+            ReadParam(aMsg, aIter, &aResult->mTransformScale) &&
             ReadParam(aMsg, aIter, &aResult->mExtraResolution) &&
             ReadParam(aMsg, aIter, &aResult->mBackgroundColor) &&
             ReadParam(aMsg, aIter, &aResult->mDoSmoothScroll) &&
             ReadParam(aMsg, aIter, &aResult->mSmoothScrollOffset) &&
             ReadContentDescription(aMsg, aIter, aResult));
   }
 };
 
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -16,16 +16,48 @@
 #include "nsString.h"
 
 namespace IPC {
 template <typename T> struct ParamTraits;
 } // namespace IPC
 
 namespace mozilla {
 
+// The layer coordinates of the parent layer.
+// This can be arrived at in two ways:
+//   - Start with the CSS coordinates of the parent layer (note: NOT the
+//     CSS coordinates of the current layer, that will give you the wrong
+//     answer), multiply by the device scale and the resolutions of all
+//     layers from the root down to and including the parent.
+//   - Start with global screen coordinates and unapply all CSS and async
+//     transforms from the root down to and including the parent.
+// It's helpful to look at https://wiki.mozilla.org/Platform/GFX/APZ#Coordinate_systems
+// to get a picture of how the various coordinate systems relate to each other.
+struct ParentLayerPixel {};
+
+template<> struct IsPixel<ParentLayerPixel> : TrueType {};
+
+typedef gfx::MarginTyped<ParentLayerPixel> ParentLayerMargin;
+typedef gfx::PointTyped<ParentLayerPixel> ParentLayerPoint;
+typedef gfx::RectTyped<ParentLayerPixel> ParentLayerRect;
+typedef gfx::SizeTyped<ParentLayerPixel> ParentLayerSize;
+
+typedef gfx::IntMarginTyped<ParentLayerPixel> ParentLayerIntMargin;
+typedef gfx::IntPointTyped<ParentLayerPixel> ParentLayerIntPoint;
+typedef gfx::IntRectTyped<ParentLayerPixel> ParentLayerIntRect;
+typedef gfx::IntSizeTyped<ParentLayerPixel> ParentLayerIntSize;
+
+typedef gfx::ScaleFactor<CSSPixel, ParentLayerPixel> CSSToParentLayerScale;
+typedef gfx::ScaleFactor<LayoutDevicePixel, ParentLayerPixel> LayoutDeviceToParentLayerScale;
+typedef gfx::ScaleFactor<ScreenPixel, ParentLayerPixel> ScreenToParentLayerScale;
+
+typedef gfx::ScaleFactor<ParentLayerPixel, LayerPixel> ParentLayerToLayerScale;
+typedef gfx::ScaleFactor<ParentLayerPixel, ScreenPixel> ParentLayerToScreenScale;
+
+
 namespace layers {
 
 /**
  * The viewport and displayport metrics for the painted frame at the
  * time of a layer-tree transaction.  These metrics are especially
  * useful for shadow layers, because the metrics values are updated
  * atomically with new pixels.
  */
@@ -41,16 +73,17 @@ public:
 
   FrameMetrics()
     : mCompositionBounds(0, 0, 0, 0)
     , mDisplayPort(0, 0, 0, 0)
     , mCriticalDisplayPort(0, 0, 0, 0)
     , mScrollableRect(0, 0, 0, 0)
     , mPresShellResolution(1)
     , mCumulativeResolution(1)
+    , mTransformScale(1)
     , mDevPixelsPerCSSPixel(1)
     , mMayHaveTouchListeners(false)
     , mMayHaveTouchCaret(false)
     , mIsRoot(false)
     , mHasScrollgrab(false)
     , mScrollId(NULL_SCROLL_ID)
     , mScrollParentId(NULL_SCROLL_ID)
     , mScrollOffset(0, 0)
@@ -118,33 +151,33 @@ public:
 
   bool IsScrollable() const
   {
     return mScrollId != NULL_SCROLL_ID;
   }
 
   CSSToScreenScale DisplayportPixelsPerCSSPixel() const
   {
-    // Note: use 'mZoom * ParentLayerToLayerScale(1.0f)' as the CSS-to-Layer scale
+    // Note: use 'mZoom * ScreenToLayerScale(1.0f)' as the CSS-to-Layer scale
     // instead of LayersPixelsPerCSSPixel(), because displayport calculations
     // are done in the context of a repaint request, where we ask Layout to
     // repaint at a new resolution that includes any async zoom. Until this
     // repaint request is processed, LayersPixelsPerCSSPixel() does not yet
     // include the async zoom, but it will when the displayport is interpreted
     // for the repaint.
-    return mZoom * ParentLayerToLayerScale(1.0f) / mExtraResolution;
+    return mZoom * ScreenToLayerScale(1.0f) / mExtraResolution;
   }
 
   CSSToLayerScale LayersPixelsPerCSSPixel() const
   {
     return mCumulativeResolution * mDevPixelsPerCSSPixel;
   }
 
   // Get the amount by which this frame has been zoomed since the last repaint.
-  LayerToParentLayerScale GetAsyncZoom() const
+  LayerToScreenScale GetAsyncZoom() const
   {
     return mZoom / LayersPixelsPerCSSPixel();
   }
 
   // Ensure the scrollableRect is at least as big as the compositionBounds
   // because the scrollableRect can be smaller if the content is not large
   // and the scrollableRect hasn't been updated yet.
   // We move the scrollableRect up because we don't know if we can move it
@@ -166,31 +199,41 @@ public:
       scrollableRect.height = compSize.height;
     }
 
     return scrollableRect;
   }
 
   // Return the scale factor needed to fit the viewport
   // into its composition bounds.
-  CSSToParentLayerScale CalculateIntrinsicScale() const
+  CSSToScreenScale CalculateIntrinsicScale() const
   {
-    return CSSToParentLayerScale(
+    return CSSToScreenScale(
         std::max(mCompositionBounds.width / mViewport.width,
                  mCompositionBounds.height / mViewport.height));
   }
 
+  // Return the scale factor for converting from CSS pixels (for this layer)
+  // to layer pixels of our parent layer. Much as mZoom is used to interface
+  // between inputs we get in screen pixels and quantities in CSS pixels,
+  // this is used to interface between mCompositionBounds and quantities
+  // in CSS pixels.
+  CSSToParentLayerScale GetZoomToParent() const
+  {
+    return mZoom * mTransformScale;
+  }
+
   CSSSize CalculateCompositedSizeInCssPixels() const
   {
-    return mCompositionBounds.Size() / GetZoom();
+    return mCompositionBounds.Size() / GetZoomToParent();
   }
 
   CSSRect CalculateCompositedRectInCssPixels() const
   {
-    return mCompositionBounds / GetZoom();
+    return mCompositionBounds / GetZoomToParent();
   }
 
   CSSSize CalculateBoundedCompositedSizeInCssPixels() const
   {
     CSSSize size = CalculateCompositedSizeInCssPixels();
     size.width = std::min(size.width, mRootCompositionSize.width);
     size.height = std::min(size.height, mRootCompositionSize.height);
     return size;
@@ -296,26 +339,27 @@ public:
   // The following metrics are dimensionless.
   //
 
   // The pres-shell resolution that has been induced on the document containing
   // this scroll frame as a result of zooming this scroll frame (whether via
   // user action, or choosing an initial zoom level on page load). This can
   // only be different from 1.0 for frames that are zoomable, which currently
   // is just the root content document's root scroll frame (mIsRoot = true).
-  // This is a plain float rather than a ScaleFactor because in and of itself
-  // it does not convert between any coordinate spaces for which we have names.
-  float mPresShellResolution;
+  ParentLayerToLayerScale mPresShellResolution;
 
   // The cumulative resolution that the current frame has been painted at.
   // This is the product of the pres-shell resolutions of the document
   // containing this scroll frame and its ancestors, and any css-driven
   // resolution. This information is provided by Gecko at layout/paint time.
   LayoutDeviceToLayerScale mCumulativeResolution;
 
+  // TODO(botond): This is now always 1 and should be removed (see bug 1055741).
+  ScreenToParentLayerScale mTransformScale;
+
   // The conversion factor between CSS pixels and device pixels for this frame.
   // This can vary based on a variety of things, such as reflowing-zoom. The
   // conversion factor for device pixels to layers pixels is just the
   // resolution.
   CSSToLayoutDeviceScale mDevPixelsPerCSSPixel;
 
 public:
   void SetIsRoot(bool aIsRoot)
@@ -353,22 +397,22 @@ public:
     mSmoothScrollOffset = aSmoothScrollDestination;
   }
 
   const CSSPoint& GetSmoothScrollOffset() const
   {
     return mSmoothScrollOffset;
   }
 
-  void SetZoom(const CSSToParentLayerScale& aZoom)
+  void SetZoom(const CSSToScreenScale& aZoom)
   {
     mZoom = aZoom;
   }
 
-  CSSToParentLayerScale GetZoom() const
+  CSSToScreenScale GetZoom() const
   {
     return mZoom;
   }
 
   void SetScrollOffsetUpdated(uint32_t aScrollGeneration)
   {
     mUpdateScrollOffset = true;
     mScrollGeneration = aScrollGeneration;
@@ -553,17 +597,17 @@ private:
   // This is valid for any layer, but is always relative to this frame and
   // not any parents, regardless of parent transforms.
   CSSPoint mScrollOffset;
 
   // The "user zoom". Content is painted by gecko at mResolution * mDevPixelsPerCSSPixel,
   // but will be drawn to the screen at mZoom. In the steady state, the
   // two will be the same, but during an async zoom action the two may
   // diverge. This information is initialized in Gecko but updated in the APZC.
-  CSSToParentLayerScale mZoom;
+  CSSToScreenScale mZoom;
 
   // Whether mScrollOffset was updated by something other than the APZ code, and
   // if the APZC receiving this metrics should update its local copy.
   bool mUpdateScrollOffset;
   // The scroll generation counter used to acknowledge the scroll offset update.
   uint32_t mScrollGeneration;
 
   // When mDoSmoothScroll, the scroll offset should be animated to
@@ -691,30 +735,30 @@ struct ScrollableLayerGuid {
 template <int LogLevel>
 gfx::Log<LogLevel>& operator<<(gfx::Log<LogLevel>& log, const ScrollableLayerGuid& aGuid) {
   return log << '(' << aGuid.mLayersId << ',' << aGuid.mPresShellId << ',' << aGuid.mScrollId << ')';
 }
 
 struct ZoomConstraints {
   bool mAllowZoom;
   bool mAllowDoubleTapZoom;
-  CSSToParentLayerScale mMinZoom;
-  CSSToParentLayerScale mMaxZoom;
+  CSSToScreenScale mMinZoom;
+  CSSToScreenScale mMaxZoom;
 
   ZoomConstraints()
     : mAllowZoom(true)
     , mAllowDoubleTapZoom(true)
   {
     MOZ_COUNT_CTOR(ZoomConstraints);
   }
 
   ZoomConstraints(bool aAllowZoom,
                   bool aAllowDoubleTapZoom,
-                  const CSSToParentLayerScale& aMinZoom,
-                  const CSSToParentLayerScale& aMaxZoom)
+                  const CSSToScreenScale& aMinZoom,
+                  const CSSToScreenScale& aMaxZoom)
     : mAllowZoom(aAllowZoom)
     , mAllowDoubleTapZoom(aAllowDoubleTapZoom)
     , mMinZoom(aMinZoom)
     , mMaxZoom(aMaxZoom)
   {
     MOZ_COUNT_CTOR(ZoomConstraints);
   }
 
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -153,20 +153,20 @@ AppendToString(std::stringstream& aStrea
       AppendToString(aStream, m.GetScrollParentId(), " scrollParent=");
     }
     aStream << nsPrintfCString(" z=%.3f }", m.GetZoom().scale).get();
   } else {
     AppendToString(aStream, m.GetDisplayPortMargins(), " dpm=");
     aStream << nsPrintfCString(" um=%d", m.GetUseDisplayPortMargins()).get();
     AppendToString(aStream, m.GetRootCompositionSize(), " rcs=");
     AppendToString(aStream, m.GetViewport(), " v=");
-    aStream << nsPrintfCString(" z=(ld=%.3f r=%.3f cr=%.3f z=%.3f er=%.3f)",
-            m.mDevPixelsPerCSSPixel.scale, m.mPresShellResolution,
+    aStream << nsPrintfCString(" z=(ld=%.3f r=%.3f cr=%.3f z=%.3f ts=%.3f)",
+            m.mDevPixelsPerCSSPixel.scale, m.mPresShellResolution.scale,
             m.mCumulativeResolution.scale, m.GetZoom().scale,
-            m.GetExtraResolution().scale).get();
+            m.mTransformScale.scale).get();
     aStream << nsPrintfCString(" u=(%d %d %lu)",
             m.GetScrollOffsetUpdated(), m.GetDoSmoothScroll(),
             m.GetScrollGeneration()).get();
     AppendToString(aStream, m.GetScrollParentId(), " p=");
     aStream << nsPrintfCString(" i=(%ld %lld) }",
             m.GetPresShellId(), m.GetScrollId()).get();
   }
   aStream << sfx;
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -59,17 +59,17 @@ struct APZCTreeManager::TreeBuildingStat
   // State that is updated as we perform the tree build
   nsTArray< nsRefPtr<AsyncPanZoomController> > mApzcsToDestroy;
   std::map<ScrollableLayerGuid, AsyncPanZoomController*> mApzcMap;
 };
 
 /*static*/ const ScreenMargin
 APZCTreeManager::CalculatePendingDisplayPort(
   const FrameMetrics& aFrameMetrics,
-  const ParentLayerPoint& aVelocity,
+  const ScreenPoint& aVelocity,
   double aEstimatedPaintDuration)
 {
   return AsyncPanZoomController::CalculatePendingDisplayPort(
     aFrameMetrics, aVelocity, aEstimatedPaintDuration);
 }
 
 APZCTreeManager::APZCTreeManager()
     : mInputQueue(new InputQueue()),
@@ -199,18 +199,17 @@ ComputeTouchSensitiveRegion(GeckoContent
   if (aController->GetTouchSensitiveRegion(&touchSensitiveRegion)) {
     // Here we assume 'touchSensitiveRegion' is in the CSS pixels of the
     // parent frame. To convert it to ParentLayer pixels, we therefore need
     // the cumulative resolution of the parent frame. We approximate this as
     // the quotient of our cumulative resolution and our pres shell resolution;
     // this approximation may not be accurate in the presence of a css-driven
     // resolution.
     LayoutDeviceToParentLayerScale parentCumulativeResolution =
-          aMetrics.mCumulativeResolution
-        / ParentLayerToLayerScale(aMetrics.mPresShellResolution);
+        aMetrics.mCumulativeResolution / aMetrics.mPresShellResolution;
     visible = visible.Intersect(touchSensitiveRegion
                                 * aMetrics.mDevPixelsPerCSSPixel
                                 * parentCumulativeResolution);
   }
 
   // Not sure what rounding option is the most correct here, but if we ever
   // figure it out we can change this. For now I'm rounding in to minimize
   // the chances of getting a complex region.
@@ -485,16 +484,46 @@ APZCTreeManager::UpdatePanZoomController
     return apzc;
   }
   if (next) {
     return next;
   }
   return aNextSibling;
 }
 
+/*static*/ template<class T> void
+ApplyTransform(gfx::PointTyped<T>* aPoint, const Matrix4x4& aMatrix)
+{
+  Point result = aMatrix * aPoint->ToUnknownPoint();
+  *aPoint = ViewAs<T>(result);
+}
+
+/*static*/ template<class T> void
+ApplyTransform(gfx::IntPointTyped<T>* aPoint, const Matrix4x4& aMatrix)
+{
+  Point result = aMatrix * aPoint->ToUnknownPoint();
+  *aPoint = TruncatedToInt(ViewAs<T>(result));
+}
+
+/*static*/ void
+ApplyTransform(nsIntPoint* aPoint, const Matrix4x4& aMatrix)
+{
+  Point result = aMatrix * Point(aPoint->x, aPoint->y);
+  aPoint->x = NS_lround(result.x);
+  aPoint->y = NS_lround(result.y);
+}
+
+/*static*/ template<class T> void
+TransformScreenToGecko(T* aPoint, AsyncPanZoomController* aApzc, APZCTreeManager* aApzcTm)
+{
+  Matrix4x4 transformToApzc = aApzcTm->GetScreenToApzcTransform(aApzc);
+  Matrix4x4 transformToGecko = aApzcTm->GetApzcToGeckoTransform(aApzc);
+  ApplyTransform(aPoint, transformToApzc * transformToGecko);
+}
+
 nsEventStatus
 APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
                                    ScrollableLayerGuid* aOutTargetGuid,
                                    uint64_t* aOutInputBlockId)
 {
   // Initialize aOutInputBlockId to a sane value, and then later we overwrite
   // it if the input event goes into a block.
   if (aOutInputBlockId) {
@@ -508,63 +537,63 @@ APZCTreeManager::ReceiveInputEvent(Input
       MultiTouchInput& touchInput = aEvent.AsMultiTouchInput();
       result = ProcessTouchInput(touchInput, aOutTargetGuid, aOutInputBlockId);
       break;
     } case PANGESTURE_INPUT: {
       PanGestureInput& panInput = aEvent.AsPanGestureInput();
       nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(panInput.mPanStartPoint,
                                                             &inOverscrolledApzc);
       if (apzc) {
+        // When passing the event to the APZC, we need to apply a different
+        // transform than the one in TransformScreenToGecko, so we need to
+        // make a copy of the event.
+        PanGestureInput inputForApzc(panInput);
         transformToApzc = GetScreenToApzcTransform(apzc);
-        panInput.mLocalPanStartPoint = TransformTo<ParentLayerPixel>(
-            transformToApzc, panInput.mPanStartPoint);
-        panInput.mLocalPanDisplacement = TransformVector<ParentLayerPixel>(
-            transformToApzc, panInput.mPanDisplacement, panInput.mPanStartPoint);
-        result = mInputQueue->ReceiveInputEvent(apzc, panInput, aOutInputBlockId);
+        ApplyTransform(&(inputForApzc.mPanStartPoint), transformToApzc);
+        result = mInputQueue->ReceiveInputEvent(apzc, inputForApzc, aOutInputBlockId);
 
         // Update the out-parameters so they are what the caller expects.
         apzc->GetGuid(aOutTargetGuid);
-        Matrix4x4 transformToGecko = transformToApzc * GetApzcToGeckoTransform(apzc);
-        panInput.mPanStartPoint = TransformTo<ScreenPixel>(
-            transformToGecko, panInput.mPanStartPoint);
-        panInput.mPanDisplacement = TransformVector<ScreenPixel>(
-            transformToGecko, panInput.mPanDisplacement, panInput.mPanStartPoint);
+        TransformScreenToGecko(&(panInput.mPanStartPoint), apzc, this);
       }
       break;
-    } case PINCHGESTURE_INPUT: {  // note: no one currently sends these
+    } case PINCHGESTURE_INPUT: {
       PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput();
       nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(pinchInput.mFocusPoint,
                                                             &inOverscrolledApzc);
       if (apzc) {
+        // When passing the event to the APZC, we need to apply a different
+        // transform than the one in TransformScreenToGecko, so we need to
+        // make a copy of the event.
+        PinchGestureInput inputForApzc(pinchInput);
         transformToApzc = GetScreenToApzcTransform(apzc);
-        pinchInput.mLocalFocusPoint = TransformTo<ParentLayerPixel>(
-            transformToApzc, pinchInput.mFocusPoint);
-        result = mInputQueue->ReceiveInputEvent(apzc, pinchInput, aOutInputBlockId);
+        ApplyTransform(&(inputForApzc.mFocusPoint), transformToApzc);
+        result = mInputQueue->ReceiveInputEvent(apzc, inputForApzc, aOutInputBlockId);
 
         // Update the out-parameters so they are what the caller expects.
         apzc->GetGuid(aOutTargetGuid);
-        Matrix4x4 outTransform = transformToApzc * GetApzcToGeckoTransform(apzc);
-        pinchInput.mFocusPoint = TransformTo<ScreenPixel>(
-            outTransform, pinchInput.mFocusPoint);
+        TransformScreenToGecko(&(pinchInput.mFocusPoint), apzc, this);
       }
       break;
-    } case TAPGESTURE_INPUT: {  // note: no one currently sends these
+    } case TAPGESTURE_INPUT: {
       TapGestureInput& tapInput = aEvent.AsTapGestureInput();
-      nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(tapInput.mPoint,
+      nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(ScreenPoint(tapInput.mPoint),
                                                             &inOverscrolledApzc);
       if (apzc) {
+        // When passing the event to the APZC, we need to apply a different
+        // transform than the one in TransformScreenToGecko, so we need to
+        // make a copy of the event.
+        TapGestureInput inputForApzc(tapInput);
         transformToApzc = GetScreenToApzcTransform(apzc);
-        tapInput.mLocalPoint = TransformTo<ParentLayerPixel>(
-            transformToApzc, tapInput.mPoint);
-        result = mInputQueue->ReceiveInputEvent(apzc, tapInput, aOutInputBlockId);
+        ApplyTransform(&(inputForApzc.mPoint), transformToApzc);
+        result = mInputQueue->ReceiveInputEvent(apzc, inputForApzc, aOutInputBlockId);
 
         // Update the out-parameters so they are what the caller expects.
         apzc->GetGuid(aOutTargetGuid);
-        Matrix4x4 outTransform = transformToApzc * GetApzcToGeckoTransform(apzc);
-        tapInput.mPoint = TransformTo<ScreenPixel>(outTransform, tapInput.mPoint);
+        TransformScreenToGecko(&(tapInput.mPoint), apzc, this);
       }
       break;
     }
   }
   if (inOverscrolledApzc) {
     result = nsEventStatus_eConsumeNoDefault;
   }
   return result;
@@ -675,33 +704,30 @@ APZCTreeManager::ProcessTouchInput(Multi
 
   nsEventStatus result = nsEventStatus_eIgnore;
   if (mApzcForInputBlock) {
     mApzcForInputBlock->GetGuid(aOutTargetGuid);
     // For computing the input for the APZC, used the cached transform.
     // This ensures that the sequence of touch points an APZC sees in an
     // input block are all in the same coordinate space.
     Matrix4x4 transformToApzc = mCachedTransformToApzcForInputBlock;
-    for (size_t i = 0; i < aInput.mTouches.Length(); i++) {
-      SingleTouchData& touchData = aInput.mTouches[i];
-      touchData.mLocalScreenPoint = TransformTo<ParentLayerPixel>(
-          transformToApzc, ScreenPoint(touchData.mScreenPoint));
+    MultiTouchInput inputForApzc(aInput);
+    for (size_t i = 0; i < inputForApzc.mTouches.Length(); i++) {
+      ApplyTransform(&(inputForApzc.mTouches[i].mScreenPoint), transformToApzc);
     }
-    result = mInputQueue->ReceiveInputEvent(mApzcForInputBlock, aInput, aOutInputBlockId);
+    result = mInputQueue->ReceiveInputEvent(mApzcForInputBlock, inputForApzc, aOutInputBlockId);
 
     // For computing the event to pass back to Gecko, use the up-to-date transforms.
     // This ensures that transformToApzc and transformToGecko are in sync
     // (note that transformToGecko isn't cached).
     transformToApzc = GetScreenToApzcTransform(mApzcForInputBlock);
     Matrix4x4 transformToGecko = GetApzcToGeckoTransform(mApzcForInputBlock);
     Matrix4x4 outTransform = transformToApzc * transformToGecko;
     for (size_t i = 0; i < aInput.mTouches.Length(); i++) {
-      SingleTouchData& touchData = aInput.mTouches[i];
-      touchData.mScreenPoint = TransformTo<ScreenPixel>(
-          outTransform, touchData.mScreenPoint);
+      ApplyTransform(&(aInput.mTouches[i].mScreenPoint), outTransform);
     }
   }
   if (mInOverscrolledApzc) {
     result = nsEventStatus_eConsumeNoDefault;
   }
 
   if (aInput.mType == MultiTouchInput::MULTITOUCH_END) {
     if (mTouchCount >= aInput.mTouches.Length()) {
@@ -753,17 +779,17 @@ APZCTreeManager::ProcessEvent(WidgetInpu
   bool inOverscrolledApzc = false;
   nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(ScreenPoint(aEvent.refPoint.x, aEvent.refPoint.y),
                                                         &inOverscrolledApzc);
   if (apzc) {
     apzc->GetGuid(aOutTargetGuid);
     Matrix4x4 transformToApzc = GetScreenToApzcTransform(apzc);
     Matrix4x4 transformToGecko = GetApzcToGeckoTransform(apzc);
     Matrix4x4 outTransform = transformToApzc * transformToGecko;
-    aEvent.refPoint = TransformTo<LayoutDevicePixel>(outTransform, aEvent.refPoint);
+    ApplyTransform(&(aEvent.refPoint), outTransform);
   }
   if (inOverscrolledApzc) {
     result = nsEventStatus_eConsumeNoDefault;
   }
   return result;
 }
 
 nsEventStatus
@@ -882,46 +908,46 @@ APZCTreeManager::ClearTree()
   Collect(mRootApzc, &apzcsToDestroy);
   for (size_t i = 0; i < apzcsToDestroy.Length(); i++) {
     apzcsToDestroy[i]->Destroy();
   }
   mRootApzc = nullptr;
 }
 
 /**
- * Transform a displacement from the ParentLayer coordinates of a source APZC
- * to the ParentLayer coordinates of a target APZC.
+ * Transform a displacement from the screen coordinates of a source APZC to
+ * the screen coordinates of a target APZC.
  * @param aTreeManager the tree manager for the APZC tree containing |aSource|
  *                     and |aTarget|
  * @param aSource the source APZC
  * @param aTarget the target APZC
  * @param aStartPoint the start point of the displacement
  * @param aEndPoint the end point of the displacement
  */
 static void
 TransformDisplacement(APZCTreeManager* aTreeManager,
                       AsyncPanZoomController* aSource,
                       AsyncPanZoomController* aTarget,
-                      ParentLayerPoint& aStartPoint,
-                      ParentLayerPoint& aEndPoint) {
-  // Convert start and end points to Screen coordinates.
+                      ScreenPoint& aStartPoint,
+                      ScreenPoint& aEndPoint) {
+  // Convert start and end points to untransformed screen coordinates.
   Matrix4x4 untransformToApzc = aTreeManager->GetScreenToApzcTransform(aSource).Inverse();
-  ScreenPoint screenStart = TransformTo<ScreenPixel>(untransformToApzc, aStartPoint);
-  ScreenPoint screenEnd = TransformTo<ScreenPixel>(untransformToApzc, aEndPoint);
+  ApplyTransform(&aStartPoint, untransformToApzc);
+  ApplyTransform(&aEndPoint, untransformToApzc);
 
-  // Convert start and end points to aTarget's ParentLayer coordinates.
+  // Convert start and end points to aTarget's transformed screen coordinates.
   Matrix4x4 transformToApzc = aTreeManager->GetScreenToApzcTransform(aTarget);
-  aStartPoint = TransformTo<ParentLayerPixel>(transformToApzc, screenStart);
-  aEndPoint = TransformTo<ParentLayerPixel>(transformToApzc, screenEnd);
+  ApplyTransform(&aStartPoint, transformToApzc);
+  ApplyTransform(&aEndPoint, transformToApzc);
 }
 
 bool
 APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev,
-                                ParentLayerPoint aStartPoint,
-                                ParentLayerPoint aEndPoint,
+                                ScreenPoint aStartPoint,
+                                ScreenPoint aEndPoint,
                                 OverscrollHandoffState& aOverscrollHandoffState)
 {
   const OverscrollHandoffChain& overscrollHandoffChain = aOverscrollHandoffState.mChain;
   uint32_t overscrollHandoffChainIndex = aOverscrollHandoffState.mChainIndex;
   nsRefPtr<AsyncPanZoomController> next;
   // If we have reached the end of the overscroll handoff chain, there is
   // nothing more to scroll, so we ignore the rest of the pan gesture.
   if (overscrollHandoffChainIndex >= overscrollHandoffChain.Length()) {
@@ -946,76 +972,76 @@ APZCTreeManager::DispatchScroll(AsyncPan
 
   // Scroll |next|. If this causes overscroll, it will call DispatchScroll()
   // again with an incremented index.
   return next->AttemptScroll(aStartPoint, aEndPoint, aOverscrollHandoffState);
 }
 
 bool
 APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev,
-                               ParentLayerPoint aVelocity,
+                               ScreenPoint aVelocity,
                                nsRefPtr<const OverscrollHandoffChain> aOverscrollHandoffChain,
                                bool aHandoff)
 {
   nsRefPtr<AsyncPanZoomController> current;
   uint32_t aOverscrollHandoffChainLength = aOverscrollHandoffChain->Length();
   uint32_t startIndex;
-
+  
   // The fling's velocity needs to be transformed from the screen coordinates
   // of |aPrev| to the screen coordinates of |next|. To transform a velocity
   // correctly, we need to convert it to a displacement. For now, we do this
   // by anchoring it to a start point of (0, 0).
   // TODO: For this to be correct in the presence of 3D transforms, we should
   // use the end point of the touch that started the fling as the start point
   // rather than (0, 0).
-  ParentLayerPoint startPoint;  // (0, 0)
-  ParentLayerPoint endPoint;
-  ParentLayerPoint transformedVelocity = aVelocity;
-
+  ScreenPoint startPoint;  // (0, 0)
+  ScreenPoint endPoint;
+  ScreenPoint transformedVelocity = aVelocity;
+  
   if (aHandoff) {
     startIndex = aOverscrollHandoffChain->IndexOf(aPrev) + 1;
-
+    
     // IndexOf will return aOverscrollHandoffChain->Length() if
     // |aPrev| is not found.
     if (startIndex >= aOverscrollHandoffChainLength) {
       return false;
     }
   } else {
     startIndex = 0;
   }
-
+  
   for (; startIndex < aOverscrollHandoffChainLength; startIndex++) {
     current = aOverscrollHandoffChain->GetApzcAtIndex(startIndex);
-
+    
     // Make sure the apcz about to be handled can be handled
     if (current == nullptr || current->IsDestroyed()) {
       return false;
     }
-
+    
     endPoint = startPoint + transformedVelocity;
-
+    
     // Only transform when current apcz can be transformed with previous
     if (startIndex > 0) {
       TransformDisplacement(this,
                             aOverscrollHandoffChain->GetApzcAtIndex(startIndex - 1),
                             current,
                             startPoint,
                             endPoint);
     }
-
+    
     transformedVelocity = endPoint - startPoint;
-
+    
     bool handoff = (startIndex < 1) ? aHandoff : true;
     if (current->AttemptFling(transformedVelocity,
                               aOverscrollHandoffChain,
                               handoff)) {
       return true;
     }
   }
-
+  
   return false;
 }
 
 bool
 APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint)
 {
   nsRefPtr<AsyncPanZoomController> target = GetTargetAPZC(aPoint, nullptr);
   return target != nullptr;
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -242,17 +242,17 @@ public:
 
   /**
    * See AsyncPanZoomController::CalculatePendingDisplayPort. This
    * function simply delegates to that one, so that non-layers code
    * never needs to include AsyncPanZoomController.h
    */
   static const ScreenMargin CalculatePendingDisplayPort(
     const FrameMetrics& aFrameMetrics,
-    const ParentLayerPoint& aVelocity,
+    const ScreenPoint& aVelocity,
     double aEstimatedPaintDuration);
 
   /**
    * Set the dpi value used by all AsyncPanZoomControllers.
    * DPI defaults to 72 if not set using SetDPI() at any point.
    */
   static void SetDPI(float aDpiValue) { sDPI = aDpiValue; }
 
@@ -322,18 +322,18 @@ public:
    *   - TM.DispatchScroll() calls A.AttemptScroll() (since A is at index 2 in the chain)
    *   - A.AttemptScroll() scrolls A. If there is overscroll, it calls TM.DispatchScroll() with index = 3.
    *   - TM.DispatchScroll() discards the rest of the scroll as there are no more elements in the chain.
    *
    * Note: this should be used for panning only. For handing off overscroll for
    *       a fling, use DispatchFling().
    */
   bool DispatchScroll(AsyncPanZoomController* aApzc,
-                      ParentLayerPoint aStartPoint,
-                      ParentLayerPoint aEndPoint,
+                      ScreenPoint aStartPoint,
+                      ScreenPoint aEndPoint,
                       OverscrollHandoffState& aOverscrollHandoffState);
 
   /**
    * This is a callback for AsyncPanZoomController to call when it wants to
    * start a fling in response to a touch-end event, or when it needs to hand
    * off a fling to the next APZC. Note that because of scroll grabbing, the
    * first APZC to fling may not be the one that is receiving the touch events.
    *
@@ -348,17 +348,17 @@ public:
    *                 start a fling (in this case the fling is given to the
    *                 first APZC in the chain)
    *
    * Returns true iff. an APZC accepted the fling. In the case of fling handoff,
    * the caller uses this return value to determine whether it should consume
    * the excess fling itself by going into an overscroll fling.
    */
   bool DispatchFling(AsyncPanZoomController* aApzc,
-                     ParentLayerPoint aVelocity,
+                     ScreenPoint aVelocity,
                      nsRefPtr<const OverscrollHandoffChain> aOverscrollHandoffChain,
                      bool aHandoff);
 
   /*
    * Build the chain of APZCs that will handle overscroll for a pan starting at |aInitialTarget|.
    */
   nsRefPtr<const OverscrollHandoffChain> BuildOverscrollHandoffChain(const nsRefPtr<AsyncPanZoomController>& aInitialTarget);
 
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -130,17 +130,16 @@ WidgetModifiersToDOMModifiers(mozilla::M
 
 namespace mozilla {
 namespace layers {
 
 typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior;
 typedef GeckoContentController::APZStateChange APZStateChange;
 typedef mozilla::gfx::Point Point;
 typedef mozilla::gfx::Matrix4x4 Matrix4x4;
-using mozilla::gfx::PointTyped;
 
 /**
  * \page APZCPrefs APZ preferences
  *
  * The following prefs are used to control the behaviour of the APZC.
  * The default values are provided in gfxPrefs.h.
  *
  * \li\b apz.allow_checkerboarding
@@ -385,22 +384,22 @@ StaticAutoPtr<ComputedTimingFunction> gZ
 /**
  * Computed time function used for curving up velocity when it gets high.
  */
 StaticAutoPtr<ComputedTimingFunction> gVelocityCurveFunction;
 
 /**
  * Maximum zoom amount, always used, even if a page asks for higher.
  */
-static const CSSToParentLayerScale MAX_ZOOM(8.0f);
+static const CSSToScreenScale MAX_ZOOM(8.0f);
 
 /**
  * Minimum zoom amount, always used, even if a page asks for lower.
  */
-static const CSSToParentLayerScale MIN_ZOOM(0.125f);
+static const CSSToScreenScale MIN_ZOOM(0.125f);
 
 /**
  * Is aAngle within the given threshold of the horizontal axis?
  * @param aAngle an angle in radians in the range [0, pi]
  * @param aThreshold an angle in radians in the range [0, pi/2]
  */
 static bool IsCloseToHorizontal(float aAngle, float aThreshold)
 {
@@ -493,17 +492,17 @@ public:
       if (!mApzc.mX.CanScroll()) {
         mApzc.mX.SetVelocity(0);
       }
       if (!mApzc.mY.CanScroll()) {
         mApzc.mY.SetVelocity(0);
       }
     }
 
-    ParentLayerPoint velocity = mApzc.GetVelocityVector();
+    ScreenPoint velocity(mApzc.mX.GetVelocity(), mApzc.mY.GetVelocity());
 
     // If the last fling was very recent and in the same direction as this one,
     // boost the velocity to be the sum of the two. Check separate axes separately
     // because we could have two vertical flings with small horizontal components
     // on the opposite side of zero, and we still want the y-fling to get accelerated.
     // Note that the acceleration code is only applied on the APZC that initiates
     // the fling; the accelerated velocities are then handed off using the
     // normal DispatchFling codepath.
@@ -566,28 +565,28 @@ public:
       mDeferredTasks.append(NewRunnableMethod(mOverscrollHandoffChain.get(),
                                               &OverscrollHandoffChain::SnapBackOverscrolledApzc,
                                               &mApzc));
       return false;
     }
 
     // AdjustDisplacement() zeroes out the Axis velocity if we're in overscroll.
     // Since we need to hand off the velocity to the tree manager in such a case,
-    // we save it here. Would be ParentLayerVector instead of ParentLayerPoint
-    // if we had vector classes.
-    ParentLayerPoint velocity = mApzc.GetVelocityVector();
-
-    ParentLayerPoint offset = velocity * aDelta.ToMilliseconds();
+    // we save it here. Would be ScreenVector instead of ScreenPoint if we had
+    // vector classes.
+    ScreenPoint velocity(mApzc.mX.GetVelocity(), mApzc.mY.GetVelocity());
+
+    ScreenPoint offset = velocity * aDelta.ToMilliseconds();
 
     // Ordinarily we might need to do a ScheduleComposite if either of
     // the following AdjustDisplacement calls returns true, but this
     // is already running as part of a FlingAnimation, so we'll be compositing
     // per frame of animation anyway.
-    ParentLayerPoint overscroll;
-    ParentLayerPoint adjustedOffset;
+    ScreenPoint overscroll;
+    ScreenPoint adjustedOffset;
     mApzc.mX.AdjustDisplacement(offset.x, adjustedOffset.x, overscroll.x);
     mApzc.mY.AdjustDisplacement(offset.y, adjustedOffset.y, overscroll.y);
 
     aFrameMetrics.ScrollBy(adjustedOffset / aFrameMetrics.GetZoom());
 
     // The fling may have caused us to reach the end of our scroll range.
     if (!IsZero(overscroll)) {
       // Hand off the fling to the next APZC in the overscroll handoff chain.
@@ -641,18 +640,18 @@ private:
   }
 
   AsyncPanZoomController& mApzc;
   nsRefPtr<const OverscrollHandoffChain> mOverscrollHandoffChain;
 };
 
 class ZoomAnimation: public AsyncPanZoomAnimation {
 public:
-  ZoomAnimation(CSSPoint aStartOffset, CSSToParentLayerScale aStartZoom,
-                CSSPoint aEndOffset, CSSToParentLayerScale aEndZoom)
+  ZoomAnimation(CSSPoint aStartOffset, CSSToScreenScale aStartZoom,
+                CSSPoint aEndOffset, CSSToScreenScale aEndZoom)
     : mTotalDuration(TimeDuration::FromMilliseconds(gfxPrefs::APZZoomAnimationDuration()))
     , mStartOffset(aStartOffset)
     , mStartZoom(aStartZoom)
     , mEndOffset(aEndOffset)
     , mEndZoom(aEndZoom)
   {}
 
   virtual bool Sample(FrameMetrics& aFrameMetrics,
@@ -668,17 +667,17 @@ public:
     }
 
     // Sample the zoom at the current time point.  The sampled zoom
     // will affect the final computed resolution.
     float sampledPosition = gZoomAnimationFunction->GetValue(animPosition);
 
     // We scale the scrollOffset linearly with sampledPosition, so the zoom
     // needs to scale inversely to match.
-    aFrameMetrics.SetZoom(CSSToParentLayerScale(1 /
+    aFrameMetrics.SetZoom(CSSToScreenScale(1 /
       (sampledPosition / mEndZoom.scale +
       (1 - sampledPosition) / mStartZoom.scale)));
 
     aFrameMetrics.SetScrollOffset(CSSPoint::FromUnknownPoint(gfx::Point(
       mEndOffset.x * sampledPosition + mStartOffset.x * (1 - sampledPosition),
       mEndOffset.y * sampledPosition + mStartOffset.y * (1 - sampledPosition)
     )));
 
@@ -689,28 +688,28 @@ private:
   TimeDuration mDuration;
   const TimeDuration mTotalDuration;
 
   // Old metrics from before we started a zoom animation. This is only valid
   // when we are in the "ANIMATED_ZOOM" state. This is used so that we can
   // interpolate between the start and end frames. We only use the
   // |mViewportScrollOffset| and |mResolution| fields on this.
   CSSPoint mStartOffset;
-  CSSToParentLayerScale mStartZoom;
+  CSSToScreenScale mStartZoom;
 
   // Target metrics for a zoom to animation. This is only valid when we are in
   // the "ANIMATED_ZOOM" state. We only use the |mViewportScrollOffset| and
   // |mResolution| fields on this.
   CSSPoint mEndOffset;
-  CSSToParentLayerScale mEndZoom;
+  CSSToScreenScale mEndZoom;
 };
 
 class OverscrollAnimation: public AsyncPanZoomAnimation {
 public:
-  explicit OverscrollAnimation(AsyncPanZoomController& aApzc, const ParentLayerPoint& aVelocity)
+  explicit OverscrollAnimation(AsyncPanZoomController& aApzc, const ScreenPoint& aVelocity)
     : mApzc(aApzc)
   {
     mApzc.mX.SetVelocity(aVelocity.x);
     mApzc.mY.SetVelocity(aVelocity.y);
   }
 
   virtual bool Sample(FrameMetrics& aFrameMetrics,
                       const TimeDuration& aDelta) MOZ_OVERRIDE
@@ -761,37 +760,37 @@ public:
     mYAxisModel.Simulate(aDelta);
 
     CSSPoint position = CSSPoint::FromAppUnits(nsPoint(mXAxisModel.GetPosition(),
                                                        mYAxisModel.GetPosition()));
     CSSPoint css_velocity = CSSPoint::FromAppUnits(nsPoint(mXAxisModel.GetVelocity(),
                                                            mYAxisModel.GetVelocity()));
 
     // Convert from points/second to points/ms
-    ParentLayerPoint velocity = ParentLayerPoint(css_velocity.x, css_velocity.y) / 1000.0f;
+    ScreenPoint velocity = ScreenPoint(css_velocity.x, css_velocity.y) / 1000.0f;
 
     // Keep the velocity updated for the Axis class so that any animations
     // chained off of the smooth scroll will inherit it.
     if (mXAxisModel.IsFinished()) {
       mApzc.mX.SetVelocity(0);
     } else {
       mApzc.mX.SetVelocity(velocity.x);
     }
     if (mYAxisModel.IsFinished()) {
       mApzc.mY.SetVelocity(0);
     } else {
       mApzc.mY.SetVelocity(velocity.y);
     }
     // If we overscroll, hand off to a fling animation that will complete the
     // spring back.
-    CSSToParentLayerScale zoom = aFrameMetrics.GetZoom();
-    ParentLayerPoint displacement = (position - aFrameMetrics.GetScrollOffset()) * zoom;
-
-    ParentLayerPoint overscroll;
-    ParentLayerPoint adjustedOffset;
+    CSSToScreenScale zoom = aFrameMetrics.GetZoom();
+    ScreenPoint displacement = (position - aFrameMetrics.GetScrollOffset()) * zoom;
+
+    ScreenPoint overscroll;
+    ScreenPoint adjustedOffset;
     mApzc.mX.AdjustDisplacement(displacement.x, adjustedOffset.x, overscroll.x);
     mApzc.mY.AdjustDisplacement(displacement.y, adjustedOffset.y, overscroll.y);
 
     aFrameMetrics.ScrollBy(adjustedOffset / zoom);
 
     // The smooth scroll may have caused us to reach the end of our scroll range.
     // This can happen if either the layout.css.scroll-behavior.damping-ratio
     // preference is set to less than 1 (underdamped) or if a smooth scroll
@@ -1000,17 +999,17 @@ AsyncPanZoomController::Destroy()
 }
 
 bool
 AsyncPanZoomController::IsDestroyed() const
 {
   return mTreeManager == nullptr;
 }
 
-/* static */ScreenCoord
+/* static */float
 AsyncPanZoomController::GetTouchStartTolerance()
 {
   return (gfxPrefs::APZTouchStartTolerance() * APZCTreeManager::GetDPI());
 }
 
 /* static */AsyncPanZoomController::AxisLockMode AsyncPanZoomController::GetAxisLockMode()
 {
   return static_cast<AxisLockMode>(gfxPrefs::APZAxisLockMode());
@@ -1127,17 +1126,17 @@ nsEventStatus AsyncPanZoomController::Ha
   }
 
   return rv;
 }
 
 nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent) {
   APZC_LOG("%p got a touch-start in state %d\n", this, mState);
   mPanDirRestricted = false;
-  ParentLayerPoint point = GetFirstTouchPoint(aEvent);
+  ScreenPoint point = GetFirstTouchScreenPoint(aEvent);
 
   switch (mState) {
     case FLING:
     case ANIMATING_ZOOM:
     case SMOOTH_SCROLL:
       CurrentTouchBlock()->GetOverscrollHandoffChain()->CancelAnimations();
       // Fall through.
     case NOTHING: {
@@ -1181,17 +1180,17 @@ nsEventStatus AsyncPanZoomController::On
 
     case CROSS_SLIDING_X:
     case CROSS_SLIDING_Y:
       // While cross-sliding, we don't want to consume any touchmove events for
       // panning or zooming, and let the caller handle them instead.
       return nsEventStatus_eIgnore;
 
     case TOUCHING: {
-      ScreenCoord panThreshold = GetTouchStartTolerance();
+      float panThreshold = GetTouchStartTolerance();
       UpdateWithTouchAtDevicePoint(aEvent);
 
       if (PanDistance() < panThreshold) {
         return nsEventStatus_eIgnore;
       }
 
       if (gfxPrefs::TouchActionEnabled() && CurrentTouchBlock()->TouchActionAllowsPanningXY()) {
         // User tries to trigger a touch behavior. If allowed touch behavior is vertical pan
@@ -1266,17 +1265,17 @@ nsEventStatus AsyncPanZoomController::On
 
   case PANNING:
   case PANNING_LOCKED_X:
   case PANNING_LOCKED_Y:
   {
     CurrentTouchBlock()->GetOverscrollHandoffChain()->FlushRepaints();
     mX.EndTouch(aEvent.mTime);
     mY.EndTouch(aEvent.mTime);
-    ParentLayerPoint flingVelocity = GetVelocityVector();
+    ScreenPoint flingVelocity(mX.GetVelocity(), mY.GetVelocity());
     // Clear our velocities; if DispatchFling() gives the fling to us,
     // the fling velocity gets *added* to our existing velocity in
     // AcceptFling().
     mX.SetVelocity(0);
     mY.SetVelocity(0);
     // Clear our state so that we don't stay in the PANNING state
     // if DispatchFling() gives the fling to somone else. However,
     // don't send the state change notification until we've determined
@@ -1330,17 +1329,17 @@ nsEventStatus AsyncPanZoomController::On
     return nsEventStatus_eIgnore;
   }
 
   if (!mZoomConstraints.mAllowZoom) {
     return nsEventStatus_eConsumeNoDefault;
   }
 
   SetState(PINCHING);
-  mLastZoomFocus = aEvent.mLocalFocusPoint - mFrameMetrics.mCompositionBounds.TopLeft();
+  mLastZoomFocus = ToParentLayerCoords(aEvent.mFocusPoint) - mFrameMetrics.mCompositionBounds.TopLeft();
 
   return nsEventStatus_eConsumeNoDefault;
 }
 
 nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
   APZC_LOG("%p got a scale in state %d\n", this, mState);
 
   if (HasReadyTouchBlock() && !CurrentTouchBlock()->TouchActionAllowsPinchZoom()) {
@@ -1357,34 +1356,34 @@ nsEventStatus AsyncPanZoomController::On
     return nsEventStatus_eConsumeNoDefault;
   }
 
   float spanRatio = aEvent.mCurrentSpan / aEvent.mPreviousSpan;
 
   {
     ReentrantMonitorAutoEnter lock(mMonitor);
 
-    CSSToParentLayerScale userZoom = mFrameMetrics.GetZoom();
-    ParentLayerPoint focusPoint = aEvent.mLocalFocusPoint - mFrameMetrics.mCompositionBounds.TopLeft();
-    CSSPoint cssFocusPoint = focusPoint / mFrameMetrics.GetZoom();
+    CSSToParentLayerScale userZoom = mFrameMetrics.GetZoomToParent();
+    ParentLayerPoint focusPoint = ToParentLayerCoords(aEvent.mFocusPoint) - mFrameMetrics.mCompositionBounds.TopLeft();
+    CSSPoint cssFocusPoint = focusPoint / mFrameMetrics.GetZoomToParent();
 
     CSSPoint focusChange = (mLastZoomFocus - focusPoint) / userZoom;
     // If displacing by the change in focus point will take us off page bounds,
     // then reduce the displacement such that it doesn't.
     focusChange.x -= mX.DisplacementWillOverscrollAmount(focusChange.x);
     focusChange.y -= mY.DisplacementWillOverscrollAmount(focusChange.y);
     ScrollBy(focusChange);
 
     // When we zoom in with focus, we can zoom too much towards the boundaries
     // that we actually go over them. These are the needed displacements along
     // either axis such that we don't overscroll the boundaries when zooming.
     CSSPoint neededDisplacement;
 
-    CSSToParentLayerScale realMinZoom = mZoomConstraints.mMinZoom;
-    CSSToParentLayerScale realMaxZoom = mZoomConstraints.mMaxZoom;
+    CSSToParentLayerScale realMinZoom = mZoomConstraints.mMinZoom * mFrameMetrics.mTransformScale;
+    CSSToParentLayerScale realMaxZoom = mZoomConstraints.mMaxZoom * mFrameMetrics.mTransformScale;
     realMinZoom.scale = std::max(realMinZoom.scale,
                                  mFrameMetrics.mCompositionBounds.width / mFrameMetrics.mScrollableRect.width);
     realMinZoom.scale = std::max(realMinZoom.scale,
                                  mFrameMetrics.mCompositionBounds.height / mFrameMetrics.mScrollableRect.height);
     if (realMaxZoom < realMinZoom) {
       realMaxZoom = realMinZoom;
     }
 
@@ -1449,37 +1448,38 @@ nsEventStatus AsyncPanZoomController::On
     RequestContentRepaint();
     UpdateSharedCompositorFrameMetrics();
   }
 
   return nsEventStatus_eConsumeNoDefault;
 }
 
 bool
-AsyncPanZoomController::ConvertToGecko(const ParentLayerPoint& aPoint, CSSPoint* aOut)
+AsyncPanZoomController::ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut)
 {
   if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) {
     Matrix4x4 transformToGecko = treeManagerLocal->GetApzcToGeckoTransform(this);
+    Point result = transformToGecko * Point(aPoint.x, aPoint.y);
     // NOTE: This isn't *quite* LayoutDevicePoint, we just don't have a name
     // for this coordinate space and it maps the closest to LayoutDevicePoint.
-    LayoutDevicePoint layoutPoint = TransformTo<LayoutDevicePixel>(transformToGecko, aPoint);
+    LayoutDevicePoint layoutPoint = LayoutDevicePoint(result.x, result.y);
     { // scoped lock to access mFrameMetrics
       ReentrantMonitorAutoEnter lock(mMonitor);
       *aOut = layoutPoint / mFrameMetrics.mDevPixelsPerCSSPixel;
     }
     return true;
   }
   return false;
 }
 
 nsEventStatus AsyncPanZoomController::OnPanMayBegin(const PanGestureInput& aEvent) {
   APZC_LOG("%p got a pan-maybegin in state %d\n", this, mState);
 
-  mX.StartTouch(aEvent.mLocalPanStartPoint.x, aEvent.mTime);
-  mY.StartTouch(aEvent.mLocalPanStartPoint.y, aEvent.mTime);
+  mX.StartTouch(aEvent.mPanStartPoint.x, aEvent.mTime);
+  mY.StartTouch(aEvent.mPanStartPoint.y, aEvent.mTime);
   if (mPanGestureState) {
     mPanGestureState->GetOverscrollHandoffChain()->CancelAnimations();
   } else {
     CancelAnimation();
   }
 
   return nsEventStatus_eConsumeNoDefault;
 }
@@ -1499,18 +1499,18 @@ nsEventStatus AsyncPanZoomController::On
 
   if (mState == SMOOTH_SCROLL) {
     // SMOOTH_SCROLL scrolls are cancelled by pan gestures.
     CancelAnimation();
   }
 
   mPanGestureState = MakeUnique<InputBlockState>(this);
 
-  mX.StartTouch(aEvent.mLocalPanStartPoint.x, aEvent.mTime);
-  mY.StartTouch(aEvent.mLocalPanStartPoint.y, aEvent.mTime);
+  mX.StartTouch(aEvent.mPanStartPoint.x, aEvent.mTime);
+  mY.StartTouch(aEvent.mPanStartPoint.y, aEvent.mTime);
 
   if (GetAxisLockMode() == FREE) {
     SetState(PANNING);
     return nsEventStatus_eConsumeNoDefault;
   }
 
   float dx = aEvent.mPanDisplacement.x, dy = aEvent.mPanDisplacement.y;
   double angle = atan2(dy, dx); // range [-pi, pi]
@@ -1537,28 +1537,29 @@ nsEventStatus AsyncPanZoomController::On
       CancelAnimation();
     }
   }
 
   // We need to update the axis velocity in order to get a useful display port
   // size and position. We need to do so even if this is a momentum pan (i.e.
   // aFingersOnTouchpad == false); in that case the "with touch" part is not
   // really appropriate, so we may want to rethink this at some point.
-  mX.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.x, aEvent.mTime);
-  mY.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.y, aEvent.mTime);
-
-  HandlePanningUpdate(aEvent.mPanDisplacement);
+  mX.UpdateWithTouchAtDevicePoint(aEvent.mPanStartPoint.x, aEvent.mTime);
+  mY.UpdateWithTouchAtDevicePoint(aEvent.mPanStartPoint.y, aEvent.mTime);
+
+  ScreenPoint panDisplacement = aEvent.mPanDisplacement;
+  ToGlobalScreenCoordinates(&panDisplacement, aEvent.mPanStartPoint);
+  HandlePanningUpdate(panDisplacement);
 
   // TODO: Handle pan events sent without pan begin / pan end events properly.
   if (mPanGestureState) {
-    ScreenPoint panDistance(fabs(aEvent.mPanDisplacement.x), fabs(aEvent.mPanDisplacement.y));
+    ScreenPoint panDistance(fabs(panDisplacement.x), fabs(panDisplacement.y));
     OverscrollHandoffState handoffState(
         *mPanGestureState->GetOverscrollHandoffChain(), panDistance);
-    CallDispatchScroll(aEvent.mLocalPanStartPoint,
-                       aEvent.mLocalPanStartPoint + aEvent.mLocalPanDisplacement,
+    CallDispatchScroll(aEvent.mPanStartPoint, aEvent.mPanStartPoint + aEvent.mPanDisplacement,
                        handoffState);
   }
 
   return nsEventStatus_eConsumeNoDefault;
 }
 
 nsEventStatus AsyncPanZoomController::OnPanEnd(const PanGestureInput& aEvent) {
   APZC_LOG("%p got a pan-end in state %d\n", this, mState);
@@ -1602,40 +1603,40 @@ nsEventStatus AsyncPanZoomController::On
 }
 
 nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) {
   APZC_LOG("%p got a long-press in state %d\n", this, mState);
   nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (controller) {
     int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
     CSSPoint geckoScreenPoint;
-    if (ConvertToGecko(aEvent.mLocalPoint, &geckoScreenPoint)) {
+    if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
       uint64_t blockId = GetInputQueue()->InjectNewTouchBlock(this);
       controller->HandleLongTap(geckoScreenPoint, modifiers, GetGuid(), blockId);
       return nsEventStatus_eConsumeNoDefault;
     }
   }
   return nsEventStatus_eIgnore;
 }
 
 nsEventStatus AsyncPanZoomController::OnLongPressUp(const TapGestureInput& aEvent) {
   APZC_LOG("%p got a long-tap-up in state %d\n", this, mState);
   nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (controller) {
     int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
     CSSPoint geckoScreenPoint;
-    if (ConvertToGecko(aEvent.mLocalPoint, &geckoScreenPoint)) {
+    if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
       controller->HandleLongTapUp(geckoScreenPoint, modifiers, GetGuid());
       return nsEventStatus_eConsumeNoDefault;
     }
   }
   return nsEventStatus_eIgnore;
 }
 
-nsEventStatus AsyncPanZoomController::GenerateSingleTap(const ParentLayerPoint& aPoint, mozilla::Modifiers aModifiers) {
+nsEventStatus AsyncPanZoomController::GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers) {
   nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (controller) {
     CSSPoint geckoScreenPoint;
     if (ConvertToGecko(aPoint, &geckoScreenPoint)) {
       if (!CurrentTouchBlock()->SetSingleTapOccurred()) {
         return nsEventStatus_eIgnore;
       }
       // Because this may be being running as part of APZCTreeManager::ReceiveInputEvent,
@@ -1661,84 +1662,94 @@ void AsyncPanZoomController::OnTouchEndO
   }
 }
 
 nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEvent) {
   APZC_LOG("%p got a single-tap-up in state %d\n", this, mState);
   // If mZoomConstraints.mAllowDoubleTapZoom is true we wait for a call to OnSingleTapConfirmed before
   // sending event to content
   if (!(mZoomConstraints.mAllowDoubleTapZoom && CurrentTouchBlock()->TouchActionAllowsDoubleTapZoom())) {
-    return GenerateSingleTap(aEvent.mLocalPoint, aEvent.modifiers);
+    return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers);
   }
   return nsEventStatus_eIgnore;
 }
 
 nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput& aEvent) {
   APZC_LOG("%p got a single-tap-confirmed in state %d\n", this, mState);
-  return GenerateSingleTap(aEvent.mLocalPoint, aEvent.modifiers);
+  return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers);
 }
 
 nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) {
   APZC_LOG("%p got a double-tap in state %d\n", this, mState);
   nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (controller) {
     if (mZoomConstraints.mAllowDoubleTapZoom && CurrentTouchBlock()->TouchActionAllowsDoubleTapZoom()) {
       int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
       CSSPoint geckoScreenPoint;
-      if (ConvertToGecko(aEvent.mLocalPoint, &geckoScreenPoint)) {
+      if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
         controller->HandleDoubleTap(geckoScreenPoint, modifiers, GetGuid());
       }
     }
     return nsEventStatus_eConsumeNoDefault;
   }
   return nsEventStatus_eIgnore;
 }
 
 nsEventStatus AsyncPanZoomController::OnCancelTap(const TapGestureInput& aEvent) {
   APZC_LOG("%p got a cancel-tap in state %d\n", this, mState);
   // XXX: Implement this.
   return nsEventStatus_eIgnore;
 }
 
-
-ScreenPoint AsyncPanZoomController::ToScreenCoordinates(const ParentLayerPoint& aVector,
-                                                        const ParentLayerPoint& aAnchor) const {
+// Helper function for To[Global|Local]ScreenCoordinates().
+// TODO(botond): Generalize this into a template function in UnitTransforms.h.
+static void TransformVector(const Matrix4x4& aTransform,
+                            ScreenPoint* aVector,
+                            const ScreenPoint& aAnchor) {
+  ScreenPoint start = aAnchor;
+  ScreenPoint end = aAnchor + *aVector;
+  start = TransformTo<ScreenPixel>(aTransform, start);
+  end = TransformTo<ScreenPixel>(aTransform, end);
+  *aVector = end - start;
+}
+
+void AsyncPanZoomController::ToGlobalScreenCoordinates(ScreenPoint* aVector,
+                                                       const ScreenPoint& aAnchor) const {
   if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) {
     Matrix4x4 apzcToScreen = treeManagerLocal->GetScreenToApzcTransform(this).Inverse();
-    return TransformVector<ScreenPixel>(apzcToScreen, aVector, aAnchor);
+    TransformVector(apzcToScreen, aVector, aAnchor);
   }
-  return ViewAs<ScreenPixel>(aVector, PixelCastJustification::TransformNotAvailable);
 }
 
-ParentLayerPoint AsyncPanZoomController::ToParentLayerCoordinates(const ScreenPoint& aVector,
-                                                                  const ScreenPoint& aAnchor) const {
+void AsyncPanZoomController::ToLocalScreenCoordinates(ScreenPoint* aVector,
+                                                      const ScreenPoint& aAnchor) const {
   if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) {
     Matrix4x4 transform = treeManagerLocal->GetScreenToApzcTransform(this);
-    return TransformVector<ParentLayerPixel>(transform, aVector, aAnchor);
+    TransformVector(transform, aVector, aAnchor);
   }
-  return ViewAs<ParentLayerPixel>(aVector, PixelCastJustification::TransformNotAvailable);
 }
 
-ScreenCoord AsyncPanZoomController::PanDistance() const {
-  ParentLayerPoint panVector;
-  ParentLayerPoint panStart;
+float AsyncPanZoomController::PanDistance() const {
+  ScreenPoint panVector;
+  ScreenPoint panStart;
   {
     ReentrantMonitorAutoEnter lock(mMonitor);
-    panVector = ParentLayerPoint(mX.PanDistance(), mY.PanDistance());
+    panVector = ScreenPoint(mX.PanDistance(), mY.PanDistance());
     panStart = PanStart();
   }
-  return ToScreenCoordinates(panVector, panStart).Length();
+  ToGlobalScreenCoordinates(&panVector, panStart);
+  return NS_hypot(panVector.x, panVector.y);
 }
 
-ParentLayerPoint AsyncPanZoomController::PanStart() const {
-  return ParentLayerPoint(mX.PanStart(), mY.PanStart());
+ScreenPoint AsyncPanZoomController::PanStart() const {
+  return ScreenPoint(mX.PanStart(), mY.PanStart());
 }
 
-const ParentLayerPoint AsyncPanZoomController::GetVelocityVector() const {
-  return ParentLayerPoint(mX.GetVelocity(), mY.GetVelocity());
+const ScreenPoint AsyncPanZoomController::GetVelocityVector() const {
+  return ScreenPoint(mX.GetVelocity(), mY.GetVelocity());
 }
 
 void AsyncPanZoomController::HandlePanningWithTouchAction(double aAngle) {
   // Handling of cross sliding will need to be added in this method after touch-action released
   // enabled by default.
   if (CurrentTouchBlock()->TouchActionAllowsPanningXY()) {
     if (mX.CanScrollNow() && mY.CanScrollNow()) {
       if (IsCloseToHorizontal(aAngle, gfxPrefs::APZAxisLockAngle())) {
@@ -1828,17 +1839,17 @@ void AsyncPanZoomController::HandlePanni
       }
     }
   }
 }
 
 nsEventStatus AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) {
   ReentrantMonitorAutoEnter lock(mMonitor);
 
-  ParentLayerPoint point = GetFirstTouchPoint(aEvent);
+  ScreenPoint point = GetFirstTouchScreenPoint(aEvent);
   float dx = mX.PanDistance(point.x);
   float dy = mY.PanDistance(point.y);
 
   // When the touch move breaks through the pan threshold, reposition the touch down origin
   // so the page won't jump when we start panning.
   mX.StartTouch(point.x, aEvent.mTime);
   mY.StartTouch(point.y, aEvent.mTime);
 
@@ -1861,35 +1872,35 @@ nsEventStatus AsyncPanZoomController::St
     }
     return nsEventStatus_eConsumeNoDefault;
   }
   // Don't consume an event that didn't trigger a panning.
   return nsEventStatus_eIgnore;
 }
 
 void AsyncPanZoomController::UpdateWithTouchAtDevicePoint(const MultiTouchInput& aEvent) {
-  ParentLayerPoint point = GetFirstTouchPoint(aEvent);
+  ScreenPoint point = GetFirstTouchScreenPoint(aEvent);
   mX.UpdateWithTouchAtDevicePoint(point.x, aEvent.mTime);
   mY.UpdateWithTouchAtDevicePoint(point.y, aEvent.mTime);
 }
 
-bool AsyncPanZoomController::AttemptScroll(const ParentLayerPoint& aStartPoint,
-                                           const ParentLayerPoint& aEndPoint,
+bool AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint,
+                                           const ScreenPoint& aEndPoint,
                                            OverscrollHandoffState& aOverscrollHandoffState) {
 
   // "start - end" rather than "end - start" because e.g. moving your finger
   // down (*positive* direction along y axis) causes the vertical scroll offset
   // to *decrease* as the page follows your finger.
-  ParentLayerPoint displacement = aStartPoint - aEndPoint;
-
-  ParentLayerPoint overscroll;  // will be used outside monitor block
+  ScreenPoint displacement = aStartPoint - aEndPoint;
+
+  ScreenPoint overscroll;  // will be used outside monitor block
   {
     ReentrantMonitorAutoEnter lock(mMonitor);
 
-    ParentLayerPoint adjustedDisplacement;
+    ScreenPoint adjustedDisplacement;
     bool xChanged = mX.AdjustDisplacement(displacement.x, adjustedDisplacement.x, overscroll.x);
     bool yChanged = mY.AdjustDisplacement(displacement.y, adjustedDisplacement.y, overscroll.y);
     if (xChanged || yChanged) {
       ScheduleComposite();
     }
 
     if (!IsZero(adjustedDisplacement)) {
       ScrollBy(adjustedDisplacement / mFrameMetrics.GetZoom());
@@ -1916,34 +1927,34 @@ bool AsyncPanZoomController::AttemptScro
 
   // If there is no APZC later in the handoff chain that accepted the
   // overscroll, try to accept it ourselves. We only accept it if we
   // are pannable.
   APZC_LOG("%p taking overscroll during panning\n", this);
   return OverscrollForPanning(overscroll, aOverscrollHandoffState.mPanDistance);
 }
 
-bool AsyncPanZoomController::OverscrollForPanning(ParentLayerPoint aOverscroll,
+bool AsyncPanZoomController::OverscrollForPanning(ScreenPoint aOverscroll,
                                                   const ScreenPoint& aPanDistance) {
   // Only allow entering overscroll along an axis if the pan distance along
   // that axis is greater than the pan distance along the other axis by a
   // configurable factor. If we are already overscrolled, don't check this.
   if (!IsOverscrolled()) {
     if (aPanDistance.x < gfxPrefs::APZMinPanDistanceRatio() * aPanDistance.y) {
       aOverscroll.x = 0;
     }
     if (aPanDistance.y < gfxPrefs::APZMinPanDistanceRatio() * aPanDistance.x) {
       aOverscroll.y = 0;
     }
   }
 
   return OverscrollBy(aOverscroll);
 }
 
-bool AsyncPanZoomController::OverscrollBy(const ParentLayerPoint& aOverscroll) {
+bool AsyncPanZoomController::OverscrollBy(const ScreenPoint& aOverscroll) {
   if (!gfxPrefs::APZOverscrollEnabled()) {
     return false;
   }
 
   ReentrantMonitorAutoEnter lock(mMonitor);
   // Do not go into overscroll in a direction in which we have no room to
   // scroll to begin with.
   bool xCanScroll = mX.CanScroll();
@@ -1970,118 +1981,118 @@ nsRefPtr<const OverscrollHandoffChain> A
 
   // This APZC IsDestroyed(). To avoid callers having to special-case this
   // scenario, just build a 1-element chain containing ourselves.
   OverscrollHandoffChain* result = new OverscrollHandoffChain;
   result->Add(this);
   return result;
 }
 
-void AsyncPanZoomController::AcceptFling(const ParentLayerPoint& aVelocity,
+void AsyncPanZoomController::AcceptFling(const ScreenPoint& aVelocity,
                                          const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
                                          bool aHandoff) {
   // We may have a pre-existing velocity for whatever reason (for example,
   // a previously handed off fling). We don't want to clobber that.
   mX.SetVelocity(mX.GetVelocity() + aVelocity.x);
   mY.SetVelocity(mY.GetVelocity() + aVelocity.y);
   SetState(FLING);
   StartAnimation(new FlingAnimation(*this,
       aOverscrollHandoffChain,
       !aHandoff));  // only apply acceleration if this is an initial fling
 }
 
-bool AsyncPanZoomController::AttemptFling(ParentLayerPoint aVelocity,
+bool AsyncPanZoomController::AttemptFling(ScreenPoint aVelocity,
                                           const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
                                           bool aHandoff) {
   // If we are pannable, take over the fling ourselves.
   if (IsPannable()) {
     AcceptFling(aVelocity,
                 aOverscrollHandoffChain,
                 aHandoff);
     return true;
   }
 
   return false;
 }
 
-void AsyncPanZoomController::HandleFlingOverscroll(const ParentLayerPoint& aVelocity,
+void AsyncPanZoomController::HandleFlingOverscroll(const ScreenPoint& aVelocity,
                                                    const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain) {
   APZCTreeManager* treeManagerLocal = GetApzcTreeManager();
   if (!(treeManagerLocal && treeManagerLocal->DispatchFling(this,
                                                             aVelocity,
                                                             aOverscrollHandoffChain,
                                                             true /* handoff */))) {
     // No one wanted the fling, so we "take it" ourselves by entering an
     // overscroll animation starting with the fling's velocity.
     if (IsPannable()) {
       StartOverscrollAnimation(aVelocity);
     }
   }
 }
 
-void AsyncPanZoomController::HandleSmoothScrollOverscroll(const ParentLayerPoint& aVelocity) {
+void AsyncPanZoomController::HandleSmoothScrollOverscroll(const ScreenPoint& aVelocity) {
   // We must call BuildOverscrollHandoffChain from this deferred callback
   // function in order to avoid a deadlock when acquiring the tree lock.
   HandleFlingOverscroll(aVelocity, BuildOverscrollHandoffChain());
 }
 
 void AsyncPanZoomController::StartSmoothScroll() {
   SetState(SMOOTH_SCROLL);
   nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset());
-  // Cast velocity from ParentLayerPoints/ms to CSSPoints/ms then convert to
+  // Cast velocity from ScreenPoints/ms to CSSPoints/ms then convert to
   // appunits/second
   nsPoint initialVelocity = CSSPoint::ToAppUnits(CSSPoint(mX.GetVelocity(),
                                                           mY.GetVelocity())) * 1000.0f;
   nsPoint destination = CSSPoint::ToAppUnits(mFrameMetrics.GetSmoothScrollOffset());
 
   StartAnimation(new SmoothScrollAnimation(*this,
                                            initialPosition, initialVelocity,
                                            destination,
                                            gfxPrefs::ScrollBehaviorSpringConstant(),
                                            gfxPrefs::ScrollBehaviorDampingRatio()));
 }
 
-void AsyncPanZoomController::StartOverscrollAnimation(const ParentLayerPoint& aVelocity) {
+void AsyncPanZoomController::StartOverscrollAnimation(const ScreenPoint& aVelocity) {
   SetState(OVERSCROLL_ANIMATION);
   StartAnimation(new OverscrollAnimation(*this, aVelocity));
 }
 
-bool AsyncPanZoomController::CallDispatchScroll(const ParentLayerPoint& aStartPoint,
-                                                const ParentLayerPoint& aEndPoint,
+bool AsyncPanZoomController::CallDispatchScroll(const ScreenPoint& aStartPoint,
+                                                const ScreenPoint& aEndPoint,
                                                 OverscrollHandoffState& aOverscrollHandoffState) {
   // Make a local copy of the tree manager pointer and check if it's not
   // null before calling DispatchScroll(). This is necessary because
   // Destroy(), which nulls out mTreeManager, could be called concurrently.
   APZCTreeManager* treeManagerLocal = GetApzcTreeManager();
   return treeManagerLocal
       && treeManagerLocal->DispatchScroll(this, aStartPoint, aEndPoint,
                                           aOverscrollHandoffState);
 }
 
 void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
-  ParentLayerPoint prevTouchPoint(mX.GetPos(), mY.GetPos());
-  ParentLayerPoint touchPoint = GetFirstTouchPoint(aEvent);
-
-  ScreenPoint panDistance = ToScreenCoordinates(
-      ParentLayerPoint(mX.PanDistance(touchPoint.x),
-                       mY.PanDistance(touchPoint.y)),
-      PanStart());
+  ScreenPoint prevTouchPoint(mX.GetPos(), mY.GetPos());
+  ScreenPoint touchPoint = GetFirstTouchScreenPoint(aEvent);
+
+  ScreenPoint panDistance(mX.PanDistance(touchPoint.x),
+                          mY.PanDistance(touchPoint.y));
+  const ScreenPoint panStart = PanStart();
+  ToGlobalScreenCoordinates(&panDistance, panStart);
   HandlePanningUpdate(panDistance);
 
   UpdateWithTouchAtDevicePoint(aEvent);
 
   if (prevTouchPoint != touchPoint) {
     OverscrollHandoffState handoffState(
         *CurrentTouchBlock()->GetOverscrollHandoffChain(), panDistance);
     CallDispatchScroll(prevTouchPoint, touchPoint, handoffState);
   }
 }
 
-ParentLayerPoint AsyncPanZoomController::GetFirstTouchPoint(const MultiTouchInput& aEvent) {
-  return ((SingleTouchData&)aEvent.mTouches[0]).mLocalScreenPoint;
+ScreenPoint AsyncPanZoomController::GetFirstTouchScreenPoint(const MultiTouchInput& aEvent) {
+  return ((SingleTouchData&)aEvent.mTouches[0]).mScreenPoint;
 }
 
 void AsyncPanZoomController::StartAnimation(AsyncPanZoomAnimation* aAnimation)
 {
   ReentrantMonitorAutoEnter lock(mMonitor);
   mAnimation = aAnimation;
   mLastSampleTime = GetFrameTime();
   ScheduleComposite();
@@ -2184,17 +2195,17 @@ RedistributeDisplayPortExcess(CSSSize& a
     float yExtra = xSlack * aDisplayPortSize.height / aDisplayPortSize.width;
     aDisplayPortSize.height += yExtra;
   }
 }
 
 /* static */
 const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort(
   const FrameMetrics& aFrameMetrics,
-  const ParentLayerPoint& aVelocity,
+  const ScreenPoint& aVelocity,
   double aEstimatedPaintDuration)
 {
   CSSSize compositionSize = aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels();
   CSSPoint velocity = aVelocity / aFrameMetrics.GetZoom();
   CSSPoint scrollOffset = aFrameMetrics.GetScrollOffset();
   CSSRect scrollableRect = aFrameMetrics.GetExpandedScrollableRect();
 
   // Calculate the displayport size based on how fast we're moving along each axis.
@@ -2268,17 +2279,17 @@ void AsyncPanZoomController::FlushRepain
   RequestContentRepaint(mFrameMetrics, false /* not throttled */);
   UpdateSharedCompositorFrameMetrics();
 }
 
 bool AsyncPanZoomController::SnapBackIfOverscrolled() {
   ReentrantMonitorAutoEnter lock(mMonitor);
   if (IsOverscrolled()) {
     APZC_LOG("%p is overscrolled, starting snap-back\n", this);
-    StartOverscrollAnimation(ParentLayerPoint(0, 0));
+    StartOverscrollAnimation(ScreenPoint(0, 0));
     return true;
   }
   return false;
 }
 
 bool AsyncPanZoomController::IsMovingFast() const {
   ReentrantMonitorAutoEnter lock(mMonitor);
   return (GetVelocityVector().Length() > gfxPrefs::APZFlingStopOnTapThreshold());
@@ -2423,17 +2434,17 @@ Matrix4x4 AsyncPanZoomController::GetOve
   // scrollable area pinned into place.
 
   // The kStretchFactor parameter determines how much overscroll can stretch the
   // content.
   const float kStretchFactor = gfxPrefs::APZOverscrollStretchFactor();
 
   // Compute the amount of the stretch along each axis. The stretch is
   // proportional to the amount by which we are overscrolled along that axis.
-  ParentLayerSize compositionSize(mX.GetCompositionLength(), mY.GetCompositionLength());
+  ScreenSize compositionSize(mX.GetCompositionLength(), mY.GetCompositionLength());
   float scaleX = 1 + kStretchFactor * fabsf(mX.GetOverscroll()) / mX.GetCompositionLength();
   float scaleY = 1 + kStretchFactor * fabsf(mY.GetOverscroll()) / mY.GetCompositionLength();
 
   // If an axis is in underscroll, the interpretation of its overscroll
   // amount changes: instead of stretching along that axis, we compress.
   if (mX.IsInUnderscroll()) {
     scaleX = 1 / scaleX;
   }
@@ -2441,29 +2452,29 @@ Matrix4x4 AsyncPanZoomController::GetOve
     scaleY = 1 / scaleY;
   }
 
   // The scale is applied relative to the origin of the composition bounds, i.e.
   // it keeps the top-left corner of the content in place. This is fine if we
   // are overscrolling at the top or on the left, but if we are overscrolling
   // at the bottom or on the right, we want the bottom or right edge of the
   // content to stay in place instead, so we add a translation to compensate.
-  ParentLayerPoint translation;
+  ScreenPoint translation;
   bool overscrolledOnRight = (mX.GetOverscroll() > 0 && !mX.IsInUnderscroll())
                           || (mX.GetOverscroll() < 0 && mX.IsInUnderscroll());
   if (overscrolledOnRight) {
-    ParentLayerCoord overscrolledCompositionWidth = scaleX * compositionSize.width;
-    ParentLayerCoord extraCompositionWidth = overscrolledCompositionWidth - compositionSize.width;
+    ScreenCoord overscrolledCompositionWidth = scaleX * compositionSize.width;
+    ScreenCoord extraCompositionWidth = overscrolledCompositionWidth - compositionSize.width;
     translation.x = -extraCompositionWidth;
   }
   bool overscrolledAtBottom = (mY.GetOverscroll() > 0 && !mY.IsInUnderscroll())
                            || (mY.GetOverscroll() < 0 && mY.IsInUnderscroll());
   if (overscrolledAtBottom) {
-    ParentLayerCoord overscrolledCompositionHeight = scaleY * compositionSize.height;
-    ParentLayerCoord extraCompositionHeight = overscrolledCompositionHeight - compositionSize.height;
+    ScreenCoord overscrolledCompositionHeight = scaleY * compositionSize.height;
+    ScreenCoord extraCompositionHeight = overscrolledCompositionHeight - compositionSize.height;
     translation.y = -extraCompositionHeight;
   }
 
   // Combine the transformations into a matrix.
   return Matrix4x4::Scaling(scaleX, scaleY, 1)
                     .PostTranslate(translation.x, translation.y, 0);
 }
 
@@ -2535,17 +2546,17 @@ bool AsyncPanZoomController::AdvanceAnim
                                             mAsyncScrollTimeoutTask,
                                             gfxPrefs::APZAsyncScrollTimeout());
   }
 
   return requestAnimationFrame;
 }
 
 void AsyncPanZoomController::SampleContentTransformForFrame(ViewTransform* aOutTransform,
-                                                            ParentLayerPoint& aScrollOffset)
+                                                            ScreenPoint& aScrollOffset)
 {
   ReentrantMonitorAutoEnter lock(mMonitor);
 
   aScrollOffset = mFrameMetrics.GetScrollOffset() * mFrameMetrics.GetZoom();
   *aOutTransform = GetCurrentAsyncTransform();
 }
 
 ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() const {
@@ -2572,35 +2583,35 @@ ViewTransform AsyncPanZoomController::Ge
     if (minScrollOffset.x < maxScrollOffset.x) {
       currentScrollOffset.x = clamped(currentScrollOffset.x, minScrollOffset.x, maxScrollOffset.x);
     }
     if (minScrollOffset.y < maxScrollOffset.y) {
       currentScrollOffset.y = clamped(currentScrollOffset.y, minScrollOffset.y, maxScrollOffset.y);
     }
   }
 
-  LayerToParentLayerScale scale(mFrameMetrics.mPresShellResolution      // non-transient portion
-                                * mFrameMetrics.GetAsyncZoom().scale);  // transient portion
-  ParentLayerPoint translation = (currentScrollOffset - lastPaintScrollOffset)
-                               * mFrameMetrics.GetZoom();
+  ParentLayerToScreenScale scale = mFrameMetrics.mPresShellResolution  // non-transient portion
+                                 * mFrameMetrics.GetAsyncZoom();       // transient portion
+  ScreenPoint translation = (currentScrollOffset - lastPaintScrollOffset)
+                          * mFrameMetrics.GetZoom();
 
   return ViewTransform(scale, -translation);
 }
 
 Matrix4x4 AsyncPanZoomController::GetNontransientAsyncTransform() const {
   ReentrantMonitorAutoEnter lock(mMonitor);
-  return Matrix4x4::Scaling(mLastContentPaintMetrics.mPresShellResolution,
-                            mLastContentPaintMetrics.mPresShellResolution,
+  return Matrix4x4::Scaling(mLastContentPaintMetrics.mPresShellResolution.scale,
+                            mLastContentPaintMetrics.mPresShellResolution.scale,
                             1.0f);
 }
 
 Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const {
   ReentrantMonitorAutoEnter lock(mMonitor);
 
-  LayerPoint scrollChange =
+  ParentLayerPoint scrollChange =
     (mLastContentPaintMetrics.GetScrollOffset() - mLastDispatchedPaintMetrics.GetScrollOffset())
     * mLastContentPaintMetrics.mDevPixelsPerCSSPixel
     * mLastContentPaintMetrics.mCumulativeResolution
       // This transform ("LD" in the terminology of the comment above
       // GetScreenToApzcTransform() in APZCTreeManager.h) is applied in a
       // coordinate space that includes the APZC's CSS transform ("LC").
       // This CSS transform is the identity unless this APZC sets a pres-shell
       // resolution, in which case the transform has a post-scale that cancels
@@ -2631,16 +2642,17 @@ bool AsyncPanZoomController::IsCurrently
 
 void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint) {
   AssertOnCompositorThread();
 
   ReentrantMonitorAutoEnter lock(mMonitor);
   bool isDefault = mFrameMetrics.IsDefault();
 
   mLastContentPaintMetrics = aLayerMetrics;
+  UpdateTransformScale();
 
   mFrameMetrics.SetMayHaveTouchListeners(aLayerMetrics.GetMayHaveTouchListeners());
   mFrameMetrics.SetMayHaveTouchCaret(aLayerMetrics.GetMayHaveTouchCaret());
   mFrameMetrics.SetScrollParentId(aLayerMetrics.GetScrollParentId());
   APZC_LOG_FM(aLayerMetrics, "%p got a NotifyLayersUpdated with aIsFirstPaint=%d", this, aIsFirstPaint);
 
   LogRendertraceRect(GetGuid(), "page", "brown", aLayerMetrics.mScrollableRect);
   LogRendertraceRect(GetGuid(), "painted displayport", "lightgreen",
@@ -2704,18 +2716,18 @@ void AsyncPanZoomController::NotifyLayer
       // already included in our zoom; however, other components of the
       // cumulative resolution (a parent document's pres-shell resolution, or
       // the css-driven resolution) may have changed, and we need to update
       // our zoom to reflect that. Note that we can't just take
       // aLayerMetrics.mZoom because the APZ may have additional async zoom
       // since the repaint request.
       float totalResolutionChange = aLayerMetrics.mCumulativeResolution.scale
                                   / mFrameMetrics.mCumulativeResolution.scale;
-      float presShellResolutionChange = aLayerMetrics.mPresShellResolution
-                                      / mFrameMetrics.mPresShellResolution;
+      float presShellResolutionChange = aLayerMetrics.mPresShellResolution.scale
+                                      / mFrameMetrics.mPresShellResolution.scale;
       mFrameMetrics.ZoomBy(totalResolutionChange / presShellResolutionChange);
     } else {
       // Take the new zoom as either device scale or composition width or both
       // got changed (e.g. due to orientation change).
       mFrameMetrics.SetZoom(aLayerMetrics.GetZoom());
       mFrameMetrics.mDevPixelsPerCSSPixel.scale = aLayerMetrics.mDevPixelsPerCSSPixel.scale;
     }
     if (!mFrameMetrics.mScrollableRect.IsEqualEdges(aLayerMetrics.mScrollableRect)) {
@@ -2804,28 +2816,28 @@ void AsyncPanZoomController::ZoomToRect(
   SetState(ANIMATING_ZOOM);
 
   {
     ReentrantMonitorAutoEnter lock(mMonitor);
 
     ParentLayerRect compositionBounds = mFrameMetrics.mCompositionBounds;
     CSSRect cssPageRect = mFrameMetrics.mScrollableRect;
     CSSPoint scrollOffset = mFrameMetrics.GetScrollOffset();
-    CSSToParentLayerScale currentZoom = mFrameMetrics.GetZoom();
+    CSSToParentLayerScale currentZoom = mFrameMetrics.GetZoomToParent();
     CSSToParentLayerScale targetZoom;
 
     // The minimum zoom to prevent over-zoom-out.
     // If the zoom factor is lower than this (i.e. we are zoomed more into the page),
     // then the CSS content rect, in layers pixels, will be smaller than the
     // composition bounds. If this happens, we can't fill the target composited
     // area with this frame.
-    CSSToParentLayerScale localMinZoom(std::max(mZoomConstraints.mMinZoom.scale,
+    CSSToParentLayerScale localMinZoom(std::max((mZoomConstraints.mMinZoom * mFrameMetrics.mTransformScale).scale,
                                        std::max(compositionBounds.width / cssPageRect.width,
                                                 compositionBounds.height / cssPageRect.height)));
-    CSSToParentLayerScale localMaxZoom = mZoomConstraints.mMaxZoom;
+    CSSToParentLayerScale localMaxZoom = mZoomConstraints.mMaxZoom * mFrameMetrics.mTransformScale;
 
     if (!aRect.IsEmpty()) {
       // Intersect the zoom-to-rect to the CSS rect to make sure it fits.
       aRect = aRect.Intersect(cssPageRect);
       targetZoom = CSSToParentLayerScale(std::min(compositionBounds.width / aRect.width,
                                                   compositionBounds.height / aRect.height));
     }
     // 1. If the rect is empty, request received from browserElementScrolling.js
@@ -2847,17 +2859,17 @@ void AsyncPanZoomController::ZoomToRect(
                       newHeight);
       aRect = aRect.Intersect(cssPageRect);
       targetZoom = CSSToParentLayerScale(std::min(compositionBounds.width / aRect.width,
                                                   compositionBounds.height / aRect.height));
     }
 
     targetZoom.scale = clamped(targetZoom.scale, localMinZoom.scale, localMaxZoom.scale);
     FrameMetrics endZoomToMetrics = mFrameMetrics;
-    endZoomToMetrics.SetZoom(targetZoom);
+    endZoomToMetrics.SetZoom(targetZoom / mFrameMetrics.mTransformScale);
 
     // Adjust the zoomToRect to a sensible position to prevent overscrolling.
     CSSSize sizeAfterZoom = endZoomToMetrics.CalculateCompositedSizeInCssPixels();
 
     // If either of these conditions are met, the page will be
     // overscrolled after zoomed
     if (aRect.y + sizeAfterZoom.height > cssPageRect.height) {
       aRect.y = cssPageRect.height - sizeAfterZoom.height;
@@ -2866,17 +2878,17 @@ void AsyncPanZoomController::ZoomToRect(
     if (aRect.x + sizeAfterZoom.width > cssPageRect.width) {
       aRect.x = cssPageRect.width - sizeAfterZoom.width;
       aRect.x = aRect.x > 0 ? aRect.x : 0;
     }
 
     endZoomToMetrics.SetScrollOffset(aRect.TopLeft());
     endZoomToMetrics.SetDisplayPortMargins(
       CalculatePendingDisplayPort(endZoomToMetrics,
-                                  ParentLayerPoint(0,0),
+                                  ScreenPoint(0,0),
                                   0));
     endZoomToMetrics.SetUseDisplayPortMargins();
 
     StartAnimation(new ZoomAnimation(
         mFrameMetrics.GetScrollOffset(),
         mFrameMetrics.GetZoom(),
         endZoomToMetrics.GetScrollOffset(),
         endZoomToMetrics.GetZoom()));
@@ -3091,10 +3103,24 @@ void AsyncPanZoomController::ShareCompos
       // so the content process know which APZC sent this shared FrameMetrics.
       if (!compositor->SendSharedCompositorFrameMetrics(mem, handle, mAPZCId)) {
         APZC_LOG("%p failed to share FrameMetrics with content process.", this);
       }
     }
   }
 }
 
+ParentLayerPoint AsyncPanZoomController::ToParentLayerCoords(const ScreenPoint& aPoint)
+{
+  // The parent layer pixel space and the screen space for a given layer are the
+  // same as of bug 1052063. FIXME: Unify these two coordinate systems.
+  return ParentLayerPoint(aPoint.x, aPoint.y);
+}
+
+void AsyncPanZoomController::UpdateTransformScale()
+{
+  // The parent layer pixel space and the screen space for a given layer are the
+  // same as of bug 1052063. FIXME: Unify these two coordinate systems.
+  mFrameMetrics.mTransformScale.scale = 1;
+}
+
 }
 }
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -85,20 +85,19 @@ public:
     USE_GESTURE_DETECTOR
   };
 
   /**
    * Constant describing the tolerance in distance we use, multiplied by the
    * device DPI, before we start panning the screen. This is to prevent us from
    * accidentally processing taps as touch moves, and from very short/accidental
    * touches moving the screen.
-   * Note: It's an abuse of the 'Coord' class to use it to represent a 2D
-   *       distance, but it's the closest thing we currently have.
+   * Note: this distance is in global screen coordinates.
    */
-  static ScreenCoord GetTouchStartTolerance();
+  static float GetTouchStartTolerance();
 
   AsyncPanZoomController(uint64_t aLayersId,
                          APZCTreeManager* aTreeManager,
                          const nsRefPtr<InputQueue>& aInputQueue,
                          GeckoContentController* aController,
                          GestureBehavior aGestures = DEFAULT_GESTURES);
 
   // --------------------------------------------------------------------------
@@ -158,17 +157,17 @@ public:
 
   /**
    * Query the transforms that should be applied to the layer corresponding
    * to this APZC due to asynchronous panning and zooming.
    * This function returns the async transform via the |aOutTransform|
    * out parameter.
    */
   void SampleContentTransformForFrame(ViewTransform* aOutTransform,
-                                      ParentLayerPoint& aScrollOffset);
+                                      ScreenPoint& aScrollOffset);
 
   /**
    * Return a visual effect that reflects this apzc's
    * overscrolled state, if any.
    */
   Matrix4x4 GetOverscrollTransform() const;
 
   /**
@@ -243,17 +242,17 @@ public:
   /**
    * Recalculates the displayport. Ideally, this should paint an area bigger
    * than the composite-to dimensions so that when you scroll down, you don't
    * checkerboard immediately. This includes a bunch of logic, including
    * algorithms to bias painting in the direction of the velocity.
    */
   static const ScreenMargin CalculatePendingDisplayPort(
     const FrameMetrics& aFrameMetrics,
-    const ParentLayerPoint& aVelocity,
+    const ScreenPoint& aVelocity,
     double aEstimatedPaintDuration);
 
   /**
    * Send an mozbrowserasyncscroll event.
    * *** The monitor must be held while calling this.
    */
   void SendAsyncScrollEvent();
 
@@ -331,35 +330,35 @@ public:
    * Returns the identifier of the touch in the last touch event processed by
    * this APZC. This should only be called when the last touch event contained
    * only one touch.
    */
   int32_t GetLastTouchIdentifier() const;
 
   /**
    * Convert the vector |aVector|, rooted at the point |aAnchor|, from
-   * this APZC's ParentLayer coordinates into screen coordinates.
+   * this APZC's local screen coordinates into global screen coordinates.
    * The anchor is necessary because with 3D tranforms, the location of the
    * vector can affect the result of the transform.
    * To respect the lock ordering, mMonitor must NOT be held when calling
    * this function (since this function acquires the tree lock).
    */
-  ScreenPoint ToScreenCoordinates(const ParentLayerPoint& aVector,
-                                  const ParentLayerPoint& aAnchor) const;
+  void ToGlobalScreenCoordinates(ScreenPoint* aVector,
+                                 const ScreenPoint& aAnchor) const;
 
   /**
    * Convert the vector |aVector|, rooted at the point |aAnchor|, from
-   * screen coordinates into this APZC's ParentLayer coordinates.
+   * global screen coordinates into this APZC's local screen coordinates .
    * The anchor is necessary because with 3D tranforms, the location of the
    * vector can affect the result of the transform.
    * To respect the lock ordering, mMonitor must NOT be held when calling
    * this function (since this function acquires the tree lock).
    */
-  ParentLayerPoint ToParentLayerCoordinates(const ScreenPoint& aVector,
-                                            const ScreenPoint& aAnchor) const;
+  void ToLocalScreenCoordinates(ScreenPoint* aVector,
+                                const ScreenPoint& aAnchor) const;
 
 protected:
   // Protected destructor, to discourage deletion outside of Release():
   ~AsyncPanZoomController();
 
   /**
    * Helper method for touches beginning. Sets everything up for panning and any
    * multitouch gestures.
@@ -467,52 +466,55 @@ protected:
    */
   void ScheduleCompositeAndMaybeRepaint();
 
   /**
    * Gets the displacement of the current touch since it began. That is, it is
    * the distance between the current position and the initial position of the
    * current touch (this only makes sense if a touch is currently happening and
    * OnTouchMove() or the equivalent for pan gestures is being invoked).
-   * Note: It's an abuse of the 'Coord' class to use it to represent a 2D
-   *       distance, but it's the closest thing we currently have.
+   * Note: This function returns a distance in global screen coordinates,
+   *       not the local screen coordinates of this APZC.
    */
-  ScreenCoord PanDistance() const;
+  float PanDistance() const;
 
   /**
    * Gets the start point of the current touch.
    * Like PanDistance(), this only makes sense if a touch is currently
    * happening and OnTouchMove() or the equivalent for pan gestures is
    * being invoked.
+   * Unlikely PanDistance(), this function returns a point in local screen
+   * coordinates.
    */
-  ParentLayerPoint PanStart() const;
+  ScreenPoint PanStart() const;
 
   /**
    * Gets a vector of the velocities of each axis.
    */
-  const ParentLayerPoint GetVelocityVector() const;
+  const ScreenPoint GetVelocityVector() const;
 
   /**
    * Gets the first touch point from a MultiTouchInput.  This gets only
    * the first one and assumes the rest are either missing or not relevant.
    */
-  ParentLayerPoint GetFirstTouchPoint(const MultiTouchInput& aEvent);
+  ScreenPoint GetFirstTouchScreenPoint(const MultiTouchInput& aEvent);
 
   /**
    * Sets the panning state basing on the pan direction angle and current touch-action value.
    */
   void HandlePanningWithTouchAction(double angle);
 
   /**
    * Sets the panning state ignoring the touch action value.
    */
   void HandlePanning(double angle);
 
   /**
    * Update the panning state and axis locks.
+   * Note: |aDelta| is expected to be in global screen coordinates.
    */
   void HandlePanningUpdate(const ScreenPoint& aDelta);
 
   /**
    * Sets up anything needed for panning. This takes us out of the "TOUCHING"
    * state and starts actually panning us.
    */
   nsEventStatus StartPanning(const MultiTouchInput& aStartPoint);
@@ -579,28 +581,38 @@ protected:
   void FireAsyncScrollOnTimeout();
 
   /**
    * Convert ScreenPoint relative to this APZC to CSSPoint relative
    * to the parent document. This excludes the transient compositor transform.
    * NOTE: This must be converted to CSSPoint relative to the child
    * document before sending over IPC.
    */
-  bool ConvertToGecko(const ParentLayerPoint& aPoint, CSSPoint* aOut);
+  bool ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut);
 
   enum AxisLockMode {
     FREE,     /* No locking at all */
     STANDARD, /* Default axis locking mode that remains locked until pan ends*/
     STICKY,   /* Allow lock to be broken, with hysteresis */
   };
 
   static AxisLockMode GetAxisLockMode();
 
+  // Convert a point from local screen coordinates to parent layer coordinates.
+  // This is a common operation as inputs from the tree manager are in screen
+  // coordinates but the composition bounds is in parent layer coordinates.
+  ParentLayerPoint ToParentLayerCoords(const ScreenPoint& aPoint);
+
+  // Update mFrameMetrics.mTransformScale. This should be called whenever
+  // our CSS transform or the non-transient part of our async transform
+  // changes, as it corresponds to the scale portion of those transforms.
+  void UpdateTransformScale();
+
   // Helper function for OnSingleTapUp() and OnSingleTapConfirmed().
-  nsEventStatus GenerateSingleTap(const ParentLayerPoint& aPoint, mozilla::Modifiers aModifiers);
+  nsEventStatus GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers);
 
   // Common processing at the end of a touch block.
   void OnTouchEndOrCancel();
 
   uint64_t mLayersId;
   nsRefPtr<CompositorParent> mCompositorParent;
   TaskThrottler mPaintThrottler;
 
@@ -807,46 +819,46 @@ public:
    * Attempt a fling with the given velocity. If we are not pannable, tehe fling
    * is handed off to the next APZC in the handoff chain via
    * mTreeManager->DspatchFling(). Returns true iff. any APZC (whether this
    * one or one further in the handoff chain) accepted the fling.
    * |aHandoff| should be true iff. the fling was handed off from a previous
    *            APZC, and determines whether acceleration is applied to the
    *            fling.
    */
-  bool AttemptFling(ParentLayerPoint aVelocity,
+  bool AttemptFling(ScreenPoint aVelocity,
                     const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
                     bool aHandoff);
 
 private:
   friend class FlingAnimation;
   friend class OverscrollAnimation;
   friend class SmoothScrollAnimation;
   // The initial velocity of the most recent fling.
-  ParentLayerPoint mLastFlingVelocity;
+  ScreenPoint mLastFlingVelocity;
   // The time at which the most recent fling started.
   TimeStamp mLastFlingTime;
 
   // Deal with overscroll resulting from a fling animation. This is only ever
   // called on APZC instances that were actually performing a fling.
   // The overscroll is handled by trying to hand the fling off to an APZC
   // later in the handoff chain, or if there are no takers, continuing the
   // fling and entering an overscrolled state.
-  void HandleFlingOverscroll(const ParentLayerPoint& aVelocity,
+  void HandleFlingOverscroll(const ScreenPoint& aVelocity,
                              const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain);
 
-  void HandleSmoothScrollOverscroll(const ParentLayerPoint& aVelocity);
+  void HandleSmoothScrollOverscroll(const ScreenPoint& aVelocity);
 
   // Helper function used by TakeOverFling() and HandleFlingOverscroll().
-  void AcceptFling(const ParentLayerPoint& aVelocity,
+  void AcceptFling(const ScreenPoint& aVelocity,
                    const nsRefPtr<const OverscrollHandoffChain>& aOverscrollHandoffChain,
                    bool aHandoff);
 
   // Start an overscroll animation with the given initial velocity.
-  void StartOverscrollAnimation(const ParentLayerPoint& aVelocity);
+  void StartOverscrollAnimation(const ScreenPoint& aVelocity);
 
   void StartSmoothScroll();
 
   /* ===================================================================
    * The functions and members in this section are used to build a tree
    * structure out of APZC instances. This tree can only be walked or
    * manipulated while holding the lock in the associated APZCTreeManager
    * instance.
@@ -927,17 +939,17 @@ public:
    * the tree manager to keep track of which APZC to hand off the overscroll
    * to; this function increments the chain and the index and passes it on to
    * APZCTreeManager::DispatchScroll() in the event of overscroll.
    * Returns true iff. this APZC, or an APZC further down the
    * handoff chain, accepted the scroll (possibly entering an overscrolled
    * state). If this returns false, the caller APZC knows that it should enter
    * an overscrolled state itself if it can.
    */
-  bool AttemptScroll(const ParentLayerPoint& aStartPoint, const ParentLayerPoint& aEndPoint,
+  bool AttemptScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint,
                      OverscrollHandoffState& aOverscrollHandoffState);
 
   void FlushRepaintForOverscrollHandoff();
 
   /**
    * If overscrolled, start a snap-back animation and return true.
    * Otherwise return false.
    */
@@ -965,35 +977,35 @@ public:
   nsRefPtr<const OverscrollHandoffChain> BuildOverscrollHandoffChain();
 
 private:
   /**
    * A helper function for calling APZCTreeManager::DispatchScroll().
    * Guards against the case where the APZC is being concurrently destroyed
    * (and thus mTreeManager is being nulled out).
    */
-  bool CallDispatchScroll(const ParentLayerPoint& aStartPoint,
-                          const ParentLayerPoint& aEndPoint,
+  bool CallDispatchScroll(const ScreenPoint& aStartPoint,
+                          const ScreenPoint& aEndPoint,
                           OverscrollHandoffState& aOverscrollHandoffState);
 
   /**
    * A helper function for overscrolling during panning. This is a wrapper
    * around OverscrollBy() that also implements restrictions on entering
    * overscroll based on the pan angle.
    */
-  bool OverscrollForPanning(ParentLayerPoint aOverscroll,
+  bool OverscrollForPanning(ScreenPoint aOverscroll,
                             const ScreenPoint& aPanDistance);
 
   /**
    * Try to overscroll by 'aOverscroll'.
    * If we are pannable, 'aOverscroll' is added to any existing overscroll,
    * and the function returns true.
    * Otherwise, nothing happens and the function return false.
    */
-  bool OverscrollBy(const ParentLayerPoint& aOverscroll);
+  bool OverscrollBy(const ScreenPoint& aOverscroll);
 
 
   /* ===================================================================
    * The functions and members in this section are used to maintain the
    * area that this APZC instance is responsible for. This is used when
    * hit-testing to see which APZC instance should handle touch events.
    */
 public:
--- a/gfx/layers/apz/src/Axis.cpp
+++ b/gfx/layers/apz/src/Axis.cpp
@@ -37,29 +37,23 @@ Axis::Axis(AsyncPanZoomController* aAsyn
     mVelocity(0.0f),
     mAxisLocked(false),
     mAsyncPanZoomController(aAsyncPanZoomController),
     mOverscroll(0),
     mInUnderscroll(false)
 {
 }
 
-float Axis::ToLocalVelocity(float aVelocityInchesPerMs) const {
-  ScreenPoint velocity = MakePoint(aVelocityInchesPerMs * APZCTreeManager::GetDPI());
-  // Use ToScreenCoordinates() to convert a point rather than a vector by
-  // treating the point as a vector, and using (0, 0) as the anchor.
-  ScreenPoint panStart = mAsyncPanZoomController->ToScreenCoordinates(
-      mAsyncPanZoomController->PanStart(),
-      ParentLayerPoint());
-  ParentLayerPoint localVelocity =
-      mAsyncPanZoomController->ToParentLayerCoordinates(velocity, panStart);
-  return localVelocity.Length();
+float Axis::ToLocalVelocity(float aVelocityInchesPerMs) {
+  ScreenPoint aVelocityPoint = MakePoint(aVelocityInchesPerMs * APZCTreeManager::GetDPI());
+  mAsyncPanZoomController->ToLocalScreenCoordinates(&aVelocityPoint, mAsyncPanZoomController->PanStart());
+  return aVelocityPoint.Length();
 }
 
-void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, uint32_t aTimestampMs) {
+void Axis::UpdateWithTouchAtDevicePoint(ScreenCoord aPos, uint32_t aTimestampMs) {
   // mVelocityQueue is controller-thread only
   AsyncPanZoomController::AssertOnControllerThread();
 
   if (aTimestampMs == mPosTimeMs) {
     // This could be a duplicate event, or it could be a legitimate event
     // on some platforms that generate events really fast. As a compromise
     // update mPos so we don't run into problems like bug 1042734, even though
     // that means the velocity will be stale. Better than doing a divide-by-zero.
@@ -99,37 +93,37 @@ void Axis::UpdateWithTouchAtDevicePoint(
 
   // Limit queue size pased on pref
   mVelocityQueue.AppendElement(std::make_pair(aTimestampMs, mVelocity));
   if (mVelocityQueue.Length() > gfxPrefs::APZMaxVelocityQueueSize()) {
     mVelocityQueue.RemoveElementAt(0);
   }
 }
 
-void Axis::StartTouch(ParentLayerCoord aPos, uint32_t aTimestampMs) {
+void Axis::StartTouch(ScreenCoord aPos, uint32_t aTimestampMs) {
   mStartPos = aPos;
   mPos = aPos;
   mPosTimeMs = aTimestampMs;
   mAxisLocked = false;
 }
 
-bool Axis::AdjustDisplacement(ParentLayerCoord aDisplacement,
-                              /* ParentLayerCoord */ float& aDisplacementOut,
-                              /* ParentLayerCoord */ float& aOverscrollAmountOut)
+bool Axis::AdjustDisplacement(ScreenCoord aDisplacement,
+                              /* ScreenCoord */ float& aDisplacementOut,
+                              /* ScreenCoord */ float& aOverscrollAmountOut)
 {
   if (mAxisLocked) {
     aOverscrollAmountOut = 0;
     aDisplacementOut = 0;
     return false;
   }
 
-  ParentLayerCoord displacement = aDisplacement;
+  ScreenCoord displacement = aDisplacement;
 
   // First consume any overscroll in the opposite direction along this axis.
-  ParentLayerCoord consumedOverscroll = 0;
+  ScreenCoord consumedOverscroll = 0;
   if (mOverscroll > 0 && aDisplacement < 0) {
     consumedOverscroll = std::min(mOverscroll, -aDisplacement);
   } else if (mOverscroll < 0 && aDisplacement > 0) {
     consumedOverscroll = 0.f - std::min(-mOverscroll, aDisplacement);
   }
   mOverscroll -= consumedOverscroll;
   displacement += consumedOverscroll;
 
@@ -141,28 +135,28 @@ bool Axis::AdjustDisplacement(ParentLaye
     // anywhere, so we're just spinning needlessly.
     mVelocity = 0.0f;
     displacement -= aOverscrollAmountOut;
   }
   aDisplacementOut = displacement;
   return fabsf(consumedOverscroll) > EPSILON;
 }
 
-ParentLayerCoord Axis::ApplyResistance(ParentLayerCoord aRequestedOverscroll) const {
+ScreenCoord Axis::ApplyResistance(ScreenCoord aRequestedOverscroll) const {
   // 'resistanceFactor' is a value between 0 and 1, which:
   //   - tends to 1 as the existing overscroll tends to 0
   //   - tends to 0 as the existing overscroll tends to the composition length
   // The actual overscroll is the requested overscroll multiplied by this
   // factor; this should prevent overscrolling by more than the composition
   // length.
   float resistanceFactor = 1 - fabsf(mOverscroll) / GetCompositionLength();
-  return resistanceFactor < 0 ? ParentLayerCoord(0) : aRequestedOverscroll * resistanceFactor;
+  return resistanceFactor < 0 ? ScreenCoord(0) : aRequestedOverscroll * resistanceFactor;
 }
 
-void Axis::OverscrollBy(ParentLayerCoord aOverscroll) {
+void Axis::OverscrollBy(ScreenCoord aOverscroll) {
   MOZ_ASSERT(CanScroll());
   aOverscroll = ApplyResistance(aOverscroll);
   if (aOverscroll > 0) {
 #ifdef DEBUG
     if (!FuzzyEqualsAdditive(GetCompositionEnd().value, GetPageEnd().value, COORDINATE_EPSILON)) {
       nsPrintfCString message("composition end (%f) is not within COORDINATE_EPISLON of page end (%f)\n",
                               GetCompositionEnd().value, GetPageEnd().value);
       NS_ASSERTION(false, message.get());
@@ -179,17 +173,17 @@ void Axis::OverscrollBy(ParentLayerCoord
       MOZ_CRASH();
     }
 #endif
     MOZ_ASSERT(mOverscroll <= 0);
   }
   mOverscroll += aOverscroll;
 }
 
-ParentLayerCoord Axis::GetOverscroll() const {
+ScreenCoord Axis::GetOverscroll() const {
   return mOverscroll;
 }
 
 bool Axis::IsInUnderscroll() const {
   return mInUnderscroll;
 }
 
 bool Axis::SampleOverscrollAnimation(const TimeDuration& aDelta) {
@@ -251,25 +245,25 @@ bool Axis::SampleOverscrollAnimation(con
 bool Axis::IsOverscrolled() const {
   return mOverscroll != 0.f;
 }
 
 void Axis::ClearOverscroll() {
   mOverscroll = 0;
 }
 
-ParentLayerCoord Axis::PanStart() const {
+ScreenCoord Axis::PanStart() const {
   return mStartPos;
 }
 
-ParentLayerCoord Axis::PanDistance() const {
+ScreenCoord Axis::PanDistance() const {
   return fabs(mPos - mStartPos);
 }
 
-ParentLayerCoord Axis::PanDistance(ParentLayerCoord aPos) const {
+ScreenCoord Axis::PanDistance(ScreenCoord aPos) const {
   return fabs(aPos - mStartPos);
 }
 
 void Axis::EndTouch(uint32_t aTimestampMs) {
   // mVelocityQueue is controller-thread only
   AsyncPanZoomController::AssertOnControllerThread();
 
   mVelocity = 0;
@@ -315,19 +309,19 @@ bool Axis::FlingApplyFrictionOrCancel(co
     mVelocity = 0.0f;
     return false;
   } else {
     mVelocity *= pow(1.0f - aFriction, float(aDelta.ToMilliseconds()));
   }
   return true;
 }
 
-ParentLayerCoord Axis::DisplacementWillOverscrollAmount(ParentLayerCoord aDisplacement) const {
-  ParentLayerCoord newOrigin = GetOrigin() + aDisplacement;
-  ParentLayerCoord newCompositionEnd = GetCompositionEnd() + aDisplacement;
+ScreenCoord Axis::DisplacementWillOverscrollAmount(ScreenCoord aDisplacement) const {
+  ScreenCoord newOrigin = GetOrigin() + aDisplacement;
+  ScreenCoord newCompositionEnd = GetCompositionEnd() + aDisplacement;
   // If the current pan plus a displacement takes the window to the left of or
   // above the current page rect.
   bool minus = newOrigin < GetPageStart();
   // If the current pan plus a displacement takes the window to the right of or
   // below the current page rect.
   bool plus = newCompositionEnd > GetPageEnd();
   if (minus && plus) {
     // Don't handle overscrolled in both directions; a displacement can't cause
@@ -339,21 +333,21 @@ ParentLayerCoord Axis::DisplacementWillO
   }
   if (plus) {
     return newCompositionEnd - GetPageEnd();
   }
   return 0;
 }
 
 CSSCoord Axis::ScaleWillOverscrollAmount(float aScale, CSSCoord aFocus) const {
-  // Internally, do computations in ParentLayer coordinates *before* the scale
-  // is applied.
-  CSSToParentLayerScale zoom = GetFrameMetrics().GetZoom();
-  ParentLayerCoord focus = aFocus * zoom;
-  ParentLayerCoord originAfterScale = (GetOrigin() + focus) - (focus / aScale);
+  // Internally, do computations in Screen coordinates *before* the scale is
+  // applied.
+  CSSToScreenScale zoom = GetFrameMetrics().GetZoom();
+  ScreenCoord focus = aFocus * zoom;
+  ScreenCoord originAfterScale = (GetOrigin() + focus) - (focus / aScale);
 
   bool both = ScaleWillOverscrollBothSides(aScale);
   bool minus = GetPageStart() - originAfterScale > COORDINATE_EPSILON;
   bool plus = (originAfterScale + (GetCompositionLength() / aScale)) - GetPageEnd() > COORDINATE_EPSILON;
 
   if ((minus && plus) || both) {
     // If we ever reach here it's a bug in the client code.
     MOZ_ASSERT(false, "In an OVERSCROLL_BOTH condition in ScaleWillOverscrollAmount");
@@ -371,98 +365,100 @@ CSSCoord Axis::ScaleWillOverscrollAmount
 float Axis::GetVelocity() const {
   return mAxisLocked ? 0 : mVelocity;
 }
 
 void Axis::SetVelocity(float aVelocity) {
   mVelocity = aVelocity;
 }
 
-ParentLayerCoord Axis::GetCompositionEnd() const {
+ScreenCoord Axis::GetCompositionEnd() const {
   return GetOrigin() + GetCompositionLength();
 }
 
-ParentLayerCoord Axis::GetPageEnd() const {
+ScreenCoord Axis::GetPageEnd() const {
   return GetPageStart() + GetPageLength();
 }
 
-ParentLayerCoord Axis::GetOrigin() const {
-  ParentLayerPoint origin = GetFrameMetrics().GetScrollOffset() * GetFrameMetrics().GetZoom();
+ScreenCoord Axis::GetOrigin() const {
+  ScreenPoint origin = GetFrameMetrics().GetScrollOffset() * GetFrameMetrics().GetZoom();
   return GetPointOffset(origin);
 }
 
-ParentLayerCoord Axis::GetCompositionLength() const {
-  return GetRectLength(GetFrameMetrics().mCompositionBounds);
+ScreenCoord Axis::GetCompositionLength() const {
+  return GetRectLength(GetFrameMetrics().mCompositionBounds / GetFrameMetrics().mTransformScale);
 }
 
-ParentLayerCoord Axis::GetPageStart() const {
-  ParentLayerRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom();
+ScreenCoord Axis::GetPageStart() const {
+  ScreenRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom();
   return GetRectOffset(pageRect);
 }
 
-ParentLayerCoord Axis::GetPageLength() const {
-  ParentLayerRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom();
+ScreenCoord Axis::GetPageLength() const {
+  ScreenRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom();
   return GetRectLength(pageRect);
 }
 
 bool Axis::ScaleWillOverscrollBothSides(float aScale) const {
   const FrameMetrics& metrics = GetFrameMetrics();
-  ParentLayerRect screenCompositionBounds = metrics.mCompositionBounds
-                                          / ParentLayerToParentLayerScale(aScale);
+
+  ScreenToParentLayerScale scale(metrics.mTransformScale.scale * aScale);
+  ScreenRect screenCompositionBounds = metrics.mCompositionBounds / scale;
+
   return GetRectLength(screenCompositionBounds) - GetPageLength() > COORDINATE_EPSILON;
 }
 
 const FrameMetrics& Axis::GetFrameMetrics() const {
   return mAsyncPanZoomController->GetFrameMetrics();
 }
 
 
 AxisX::AxisX(AsyncPanZoomController* aAsyncPanZoomController)
   : Axis(aAsyncPanZoomController)
 {
 
 }
 
-ParentLayerCoord AxisX::GetPointOffset(const ParentLayerPoint& aPoint) const
+ScreenCoord AxisX::GetPointOffset(const ScreenPoint& aPoint) const
 {
   return aPoint.x;
 }
 
-ParentLayerCoord AxisX::GetRectLength(const ParentLayerRect& aRect) const
+ScreenCoord AxisX::GetRectLength(const ScreenRect& aRect) const
 {
   return aRect.width;
 }
 
-ParentLayerCoord AxisX::GetRectOffset(const ParentLayerRect& aRect) const
+ScreenCoord AxisX::GetRectOffset(const ScreenRect& aRect) const
 {
   return aRect.x;
 }
 
 ScreenPoint AxisX::MakePoint(ScreenCoord aCoord) const
 {
   return ScreenPoint(aCoord, 0);
 }
 
 AxisY::AxisY(AsyncPanZoomController* aAsyncPanZoomController)
   : Axis(aAsyncPanZoomController)
 {
 
 }
 
-ParentLayerCoord AxisY::GetPointOffset(const ParentLayerPoint& aPoint) const
+ScreenCoord AxisY::GetPointOffset(const ScreenPoint& aPoint) const
 {
   return aPoint.y;
 }
 
-ParentLayerCoord AxisY::GetRectLength(const ParentLayerRect& aRect) const
+ScreenCoord AxisY::GetRectLength(const ScreenRect& aRect) const
 {
   return aRect.height;
 }
 
-ParentLayerCoord AxisY::GetRectOffset(const ParentLayerRect& aRect) const
+ScreenCoord AxisY::GetRectOffset(const ScreenRect& aRect) const
 {
   return aRect.y;
 }
 
 ScreenPoint AxisY::MakePoint(ScreenCoord aCoord) const
 {
   return ScreenPoint(0, aCoord);
 }
--- a/gfx/layers/apz/src/Axis.h
+++ b/gfx/layers/apz/src/Axis.h
@@ -36,23 +36,23 @@ class AsyncPanZoomController;
 class Axis {
 public:
   explicit Axis(AsyncPanZoomController* aAsyncPanZoomController);
 
   /**
    * Notify this Axis that a new touch has been received, including a timestamp
    * for when the touch was received. This triggers a recalculation of velocity.
    */
-  void UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, uint32_t aTimestampMs);
+  void UpdateWithTouchAtDevicePoint(ScreenCoord aPos, uint32_t aTimestampMs);
 
   /**
    * Notify this Axis that a touch has begun, i.e. the user has put their finger
    * on the screen but has not yet tried to pan.
    */
-  void StartTouch(ParentLayerCoord aPos, uint32_t aTimestampMs);
+  void StartTouch(ScreenCoord aPos, uint32_t aTimestampMs);
 
   /**
    * Notify this Axis that a touch has ended gracefully. This may perform
    * recalculations of the axis velocity.
    */
   void EndTouch(uint32_t aTimestampMs);
 
   /**
@@ -68,38 +68,38 @@ public:
    * to account for overscroll (which might decrease the displacement; this is
    * to prevent the viewport from overscrolling the page rect), and axis locking
    * (which might prevent any displacement from happening). If overscroll
    * ocurred, its amount is written to |aOverscrollAmountOut|.
    * The |aDisplacementOut| parameter is set to the adjusted
    * displacement, and the function returns true iff internal overscroll amounts
    * were changed.
    */
-  bool AdjustDisplacement(ParentLayerCoord aDisplacement,
-                          /* ParentLayerCoord */ float& aDisplacementOut,
-                          /* ParentLayerCoord */ float& aOverscrollAmountOut);
+  bool AdjustDisplacement(ScreenCoord aDisplacement,
+                          /* ScreenCoord */ float& aDisplacementOut,
+                          /* ScreenCoord */ float& aOverscrollAmountOut);
 
   /**
    * Overscrolls this axis by the requested amount in the requested direction.
    * The axis must be at the end of its scroll range in this direction.
    */
-  void OverscrollBy(ParentLayerCoord aOverscroll);
+  void OverscrollBy(ScreenCoord aOverscroll);
 
   /**
-   * Return the amount of overscroll on this axis, in ParentLayer pixels.
+   * Return the amount of overscroll on this axis, in Screen pixels.
    *
    * If this amount is nonzero, the relevant component of
    * mAsyncPanZoomController->mFrameMetrics.mScrollOffset must be at its
    * extreme allowed value in the relevant direction (that is, it must be at
    * its maximum value if we are overscrolled at our composition length, and
    * at its minimum value if we are overscrolled at the origin).
    * Note that if |mInUnderscroll| is true, the interpretation of this field
    * changes slightly (see below).
    */
-  ParentLayerCoord GetOverscroll() const;
+  ScreenCoord GetOverscroll() const;
 
   /**
    * Return whether the axis is in underscroll.
    *
    * This flag is set when an overscroll animation is in a state where the
    * spring physics caused a snap-back movement to "overshoot" its target and
    * as a result the spring is stretched in a direction opposite to the one
    * when we were in overscroll. We call this situation "underscroll". When in
@@ -133,30 +133,30 @@ public:
   /**
    * Clear any overscroll amount on this axis.
    */
   void ClearOverscroll();
 
   /**
    * Gets the starting position of the touch supplied in StartTouch().
    */
-  ParentLayerCoord PanStart() const;
+  ScreenCoord PanStart() const;
 
   /**
    * Gets the distance between the starting position of the touch supplied in
    * StartTouch() and the current touch from the last
    * UpdateWithTouchAtDevicePoint().
    */
-  ParentLayerCoord PanDistance() const;
+  ScreenCoord PanDistance() const;
 
   /**
    * Gets the distance between the starting position of the touch supplied in
    * StartTouch() and the supplied position.
    */
-  ParentLayerCoord PanDistance(ParentLayerCoord aPos) const;
+  ScreenCoord PanDistance(ScreenCoord aPos) const;
 
   /**
    * Applies friction during a fling, or cancels the fling if the velocity is
    * too low. Returns true if the fling should continue to another frame, or
    * false if it should end.
    * |aDelta| is the amount of time that has passed since the last time
    * friction was applied.
    * |aFriction| is the amount of friction to apply.
@@ -193,95 +193,95 @@ public:
    * there.
    */
   void SetVelocity(float aVelocity);
 
   /**
    * If a displacement will overscroll the axis, this returns the amount and in
    * what direction.
    */
-  ParentLayerCoord DisplacementWillOverscrollAmount(ParentLayerCoord aDisplacement) const;
+  ScreenCoord DisplacementWillOverscrollAmount(ScreenCoord aDisplacement) const;
 
   /**
    * If a scale will overscroll the axis, this returns the amount and in what
    * direction.
    *
    * |aFocus| is the point at which the scale is focused at. We will offset the
    * scroll offset in such a way that it remains in the same place on the page
    * relative.
    *
    * Note: Unlike most other functions in Axis, this functions operates in
-   *       CSS coordinates so there is no confusion as to whether the ParentLayer
+   *       CSS coordinates so there is no confusion as to whether the Screen
    *       coordinates it operates in are before or after the scale is applied.
    */
   CSSCoord ScaleWillOverscrollAmount(float aScale, CSSCoord aFocus) const;
 
   /**
    * Checks if an axis will overscroll in both directions by computing the
    * content rect and checking that its height/width (depending on the axis)
    * does not overextend past the viewport.
    *
    * This gets called by ScaleWillOverscroll().
    */
   bool ScaleWillOverscrollBothSides(float aScale) const;
 
-  ParentLayerCoord GetOrigin() const;
-  ParentLayerCoord GetCompositionLength() const;
-  ParentLayerCoord GetPageStart() const;
-  ParentLayerCoord GetPageLength() const;
-  ParentLayerCoord GetCompositionEnd() const;
-  ParentLayerCoord GetPageEnd() const;
+  ScreenCoord GetOrigin() const;
+  ScreenCoord GetCompositionLength() const;
+  ScreenCoord GetPageStart() const;
+  ScreenCoord GetPageLength() const;
+  ScreenCoord GetCompositionEnd() const;
+  ScreenCoord GetPageEnd() const;
 
-  ParentLayerCoord GetPos() const { return mPos; }
+  ScreenCoord GetPos() const { return mPos; }
 
-  virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const = 0;
-  virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const = 0;
-  virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const = 0;
+  virtual ScreenCoord GetPointOffset(const ScreenPoint& aPoint) const = 0;
+  virtual ScreenCoord GetRectLength(const ScreenRect& aRect) const = 0;
+  virtual ScreenCoord GetRectOffset(const ScreenRect& aRect) const = 0;
 
   virtual ScreenPoint MakePoint(ScreenCoord aCoord) const = 0;
 
 protected:
-  ParentLayerCoord mPos;
+  ScreenCoord mPos;
   uint32_t mPosTimeMs;
-  ParentLayerCoord mStartPos;
-  float mVelocity;      // Units: ParentLayerCoords per millisecond
+  ScreenCoord mStartPos;
+  float mVelocity;      // Units: ScreenCoords per millisecond
   bool mAxisLocked;     // Whether movement on this axis is locked.
   AsyncPanZoomController* mAsyncPanZoomController;
-  ParentLayerCoord mOverscroll;  // See GetOverscroll().
-  bool mInUnderscroll;           // See IsInUnderscroll().
+  ScreenCoord mOverscroll;  // See GetOverscroll().
+  bool mInUnderscroll;      // See IsInUnderscroll().
   // A queue of (timestamp, velocity) pairs; these are the historical
   // velocities at the given timestamps. Timestamps are in milliseconds,
   // velocities are in screen pixels per ms. This member can only be
   // accessed on the controller/UI thread.
   nsTArray<std::pair<uint32_t, float> > mVelocityQueue;
 
   const FrameMetrics& GetFrameMetrics() const;
 
   // Adjust a requested overscroll amount for resistance, yielding a smaller
   // actual overscroll amount.
-  ParentLayerCoord ApplyResistance(ParentLayerCoord aOverscroll) const;
+  ScreenCoord ApplyResistance(ScreenCoord aOverscroll) const;
 
-  // Convert a velocity from global inches/ms into ParentLayerCoords/ms.
-  float ToLocalVelocity(float aVelocityInchesPerMs) const;
+  // Convert a velocity from global inches/ms into local ScreenCoords per ms
+  float ToLocalVelocity(float aVelocityInchesPerMs);
 };
 
 class AxisX : public Axis {
 public:
   explicit AxisX(AsyncPanZoomController* mAsyncPanZoomController);
-  virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const MOZ_OVERRIDE;
-  virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const MOZ_OVERRIDE;
-  virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const MOZ_OVERRIDE;
+  virtual ScreenCoord GetPointOffset(const ScreenPoint& aPoint) const MOZ_OVERRIDE;
+  virtual ScreenCoord GetRectLength(const ScreenRect& aRect) const MOZ_OVERRIDE;
+  virtual ScreenCoord GetRectOffset(const ScreenRect& aRect) const MOZ_OVERRIDE;
   virtual ScreenPoint MakePoint(ScreenCoord aCoord) const MOZ_OVERRIDE;
 };
 
 class AxisY : public Axis {
 public:
   explicit AxisY(AsyncPanZoomController* mAsyncPanZoomController);
-  virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const MOZ_OVERRIDE;
-  virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const MOZ_OVERRIDE;
-  virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const MOZ_OVERRIDE;
+  virtual ScreenCoord GetPointOffset(const ScreenPoint& aPoint) const MOZ_OVERRIDE;
+  virtual ScreenCoord GetRectLength(const ScreenRect& aRect) const MOZ_OVERRIDE;
+  virtual ScreenCoord GetRectOffset(const ScreenRect& aRect) const MOZ_OVERRIDE;
   virtual ScreenPoint MakePoint(ScreenCoord aCoord) const MOZ_OVERRIDE;
 };
 
 }
 }
 
 #endif
--- a/gfx/layers/apz/src/GestureEventListener.cpp
+++ b/gfx/layers/apz/src/GestureEventListener.cpp
@@ -29,40 +29,29 @@ static const uint32_t MAX_TAP_TIME = 300
 /**
  * Amount of change in span needed to take us from the GESTURE_WAITING_PINCH
  * state to the GESTURE_PINCH state. This is measured as a change in distance
  * between the fingers used to compute the span ratio. Note that it is a
  * distance, not a displacement.
  */
 static const float PINCH_START_THRESHOLD = 35.0f;
 
-ParentLayerPoint GetCurrentFocus(const MultiTouchInput& aEvent)
+ScreenPoint GetCurrentFocus(const MultiTouchInput& aEvent)
 {
-  const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint;
-  const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint;
-  return (firstTouch + secondTouch) / 2;
+  const ScreenIntPoint& firstTouch = aEvent.mTouches[0].mScreenPoint,
+                       secondTouch = aEvent.mTouches[1].mScreenPoint;
+  return ScreenPoint(firstTouch + secondTouch) / 2;
 }
 
 float GetCurrentSpan(const MultiTouchInput& aEvent)
 {
-  const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint;
-  const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint;
-  ParentLayerPoint delta = secondTouch - firstTouch;
-  return delta.Length();
-}
-
-TapGestureInput CreateTapEvent(const MultiTouchInput& aTouch, TapGestureInput::TapGestureType aType)
-{
-  return TapGestureInput(aType,
-                         aTouch.mTime,
-                         aTouch.mTimeStamp,
-                         // Use mLocalScreenPoint as this goes directly to APZC
-                         // without being transformed in APZCTreeManager.
-                         aTouch.mTouches[0].mLocalScreenPoint,
-                         aTouch.modifiers);
+  const ScreenIntPoint& firstTouch = aEvent.mTouches[0].mScreenPoint,
+                       secondTouch = aEvent.mTouches[1].mScreenPoint;
+  ScreenIntPoint delta = secondTouch - firstTouch;
+  return float(NS_hypot(delta.x, delta.y));
 }
 
 GestureEventListener::GestureEventListener(AsyncPanZoomController* aAsyncPanZoomController)
   : mAsyncPanZoomController(aAsyncPanZoomController),
     mState(GESTURE_NONE),
     mSpanChange(0.0f),
     mPreviousSpan(0.0f),
     mLastTouchInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0),
@@ -133,17 +122,17 @@ int32_t GestureEventListener::GetLastTou
 }
 
 
 nsEventStatus GestureEventListener::HandleInputTouchSingleStart()
 {
   switch (mState) {
   case GESTURE_NONE:
     SetState(GESTURE_FIRST_SINGLE_TOUCH_DOWN);
-    mTouchStartPosition = mLastTouchInput.mTouches[0].mLocalScreenPoint;
+    mTouchStartPosition = mLastTouchInput.mTouches[0].mScreenPoint;
 
     CreateLongTapTimeoutTask();
     CreateMaxTapTimeoutTask();
     break;
   case GESTURE_FIRST_SINGLE_TOUCH_UP:
     SetState(GESTURE_SECOND_SINGLE_TOUCH_DOWN);
     break;
   default:
@@ -206,20 +195,20 @@ nsEventStatus GestureEventListener::Hand
     break;
   }
 
   return rv;
 }
 
 bool GestureEventListener::MoveDistanceIsLarge()
 {
-  const ParentLayerPoint start = mLastTouchInput.mTouches[0].mLocalScreenPoint;
-  ParentLayerPoint delta = start - mTouchStartPosition;
-  ScreenPoint screenDelta = mAsyncPanZoomController->ToScreenCoordinates(delta, start);
-  return (screenDelta.Length() > AsyncPanZoomController::GetTouchStartTolerance());
+  const ScreenPoint start = mLastTouchInput.mTouches[0].mScreenPoint;
+  ScreenPoint delta = start - mTouchStartPosition;
+  mAsyncPanZoomController->ToGlobalScreenCoordinates(&delta, start);
+  return (delta.Length() > AsyncPanZoomController::GetTouchStartTolerance());
 }
 
 nsEventStatus GestureEventListener::HandleInputTouchMove()
 {
   nsEventStatus rv = nsEventStatus_eIgnore;
 
   switch (mState) {
   case GESTURE_NONE:
@@ -320,46 +309,58 @@ nsEventStatus GestureEventListener::Hand
   switch (mState) {
   case GESTURE_NONE:
     // GEL doesn't have a dedicated state for PANNING handled in APZC thus ignore.
     break;
 
   case GESTURE_FIRST_SINGLE_TOUCH_DOWN: {
     CancelLongTapTimeoutTask();
     CancelMaxTapTimeoutTask();
-    nsEventStatus tapupStatus = mAsyncPanZoomController->HandleGestureEvent(
-        CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_UP));
+    TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_UP,
+                             mLastTouchInput.mTime,
+                             mLastTouchInput.mTimeStamp,
+                             mLastTouchInput.mTouches[0].mScreenPoint,
+                             mLastTouchInput.modifiers);
+    nsEventStatus tapupStatus = mAsyncPanZoomController->HandleGestureEvent(tapEvent);
     if (tapupStatus == nsEventStatus_eIgnore) {
       SetState(GESTURE_FIRST_SINGLE_TOUCH_UP);
       CreateMaxTapTimeoutTask();
     } else {
       // We sent the tapup into content without waiting for a double tap
       SetState(GESTURE_NONE);
     }
     break;
   }
 
   case GESTURE_SECOND_SINGLE_TOUCH_DOWN: {
     CancelMaxTapTimeoutTask();
     SetState(GESTURE_NONE);
-    mAsyncPanZoomController->HandleGestureEvent(
-        CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_DOUBLE));
+    TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_DOUBLE,
+                             mLastTouchInput.mTime,
+                             mLastTouchInput.mTimeStamp,
+                             mLastTouchInput.mTouches[0].mScreenPoint,
+                             mLastTouchInput.modifiers);
+    mAsyncPanZoomController->HandleGestureEvent(tapEvent);
     break;
   }
 
   case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN:
     CancelLongTapTimeoutTask();
     SetState(GESTURE_NONE);
     TriggerSingleTapConfirmedEvent();
     break;
 
   case GESTURE_LONG_TOUCH_DOWN: {
     SetState(GESTURE_NONE);
-    mAsyncPanZoomController->HandleGestureEvent(
-        CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_LONG_UP));
+    TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_LONG_UP,
+                             mLastTouchInput.mTime,
+                             mLastTouchInput.mTimeStamp,
+                             mLastTouchInput.mTouches[0].mScreenPoint,
+                             mLastTouchInput.modifiers);
+    mAsyncPanZoomController->HandleGestureEvent(tapEvent);
     break;
   }
 
   case GESTURE_MULTI_TOUCH_DOWN:
     if (mTouches.Length() < 2) {
       SetState(GESTURE_NONE);
     }
     break;
@@ -406,18 +407,22 @@ void GestureEventListener::HandleInputTi
 
   switch (mState) {
   case GESTURE_FIRST_SINGLE_TOUCH_DOWN:
     // just in case MAX_TAP_TIME > ContextMenuDelay cancel MAX_TAP timer
     // and fall through
     CancelMaxTapTimeoutTask();
   case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN: {
     SetState(GESTURE_LONG_TOUCH_DOWN);
-    mAsyncPanZoomController->HandleGestureEvent(
-        CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_LONG));
+    TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_LONG,
+                             mLastTouchInput.mTime,
+                             mLastTouchInput.mTimeStamp,
+                             mLastTouchInput.mTouches[0].mScreenPoint,
+                             mLastTouchInput.modifiers);
+    mAsyncPanZoomController->HandleGestureEvent(tapEvent);
     break;
   }
   default:
     NS_WARNING("Unhandled state upon long tap timeout");
     SetState(GESTURE_NONE);
     break;
   }
 }
@@ -437,18 +442,22 @@ void GestureEventListener::HandleInputTi
   } else {
     NS_WARNING("Unhandled state upon MAX_TAP timeout");
     SetState(GESTURE_NONE);
   }
 }
 
 void GestureEventListener::TriggerSingleTapConfirmedEvent()
 {
-  mAsyncPanZoomController->HandleGestureEvent(
-      CreateTapEvent(mLastTapInput, TapGestureInput::TAPGESTURE_CONFIRMED));
+  TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_CONFIRMED,
+                           mLastTapInput.mTime,
+                           mLastTapInput.mTimeStamp,
+                           mLastTapInput.mTouches[0].mScreenPoint,
+                           mLastTapInput.modifiers);
+  mAsyncPanZoomController->HandleGestureEvent(tapEvent);
 }
 
 void GestureEventListener::SetState(GestureState aState)
 {
   mState = aState;
 
   if (mState == GESTURE_NONE) {
     mSpanChange = 0.0f;
--- a/gfx/layers/apz/src/GestureEventListener.h
+++ b/gfx/layers/apz/src/GestureEventListener.h
@@ -3,17 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_GestureEventListener_h
 #define mozilla_layers_GestureEventListener_h
 
 #include "InputData.h"                  // for MultiTouchInput, etc
-#include "Units.h"
+#include "Units.h"                      // for ScreenIntPoint
 #include "mozilla/EventForwards.h"      // for nsEventStatus
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsISupportsImpl.h"
 #include "nsTArray.h"                   // for nsTArray
 
 class CancelableTask;
 
 namespace mozilla {
@@ -188,17 +188,17 @@ private:
    * Position of the last touch starting. This is only valid during an attempt
    * to determine if a touch is a tap. If a touch point moves away from
    * mTouchStartPosition to the distance greater than
    * AsyncPanZoomController::GetTouchStartTolerance() while in
    * GESTURE_FIRST_SINGLE_TOUCH_DOWN, GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN
    * or GESTURE_SECOND_SINGLE_TOUCH_DOWN then we're certain the gesture is
    * not tap.
    */
-  ParentLayerPoint mTouchStartPosition;
+  ScreenIntPoint mTouchStartPosition;
 
   /**
    * Task used to timeout a long tap. This gets posted to the UI thread such
    * that it runs a time when a single tap happens. We cache it so that
    * we can cancel it if any other touch event happens.
    *
    * The task is supposed to be non-null if in GESTURE_FIRST_SINGLE_TOUCH_DOWN
    * and GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN states.
--- a/gfx/layers/apz/util/APZCCallbackHelper.cpp
+++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp
@@ -138,20 +138,22 @@ APZCCallbackHelper::UpdateRootFrame(nsID
         // scroll position here is out of our control. See bug 966507 comment 21 for a
         // more detailed explanation.
         RecenterDisplayPort(aMetrics);
     }
 
     aMetrics.SetScrollOffset(actualScrollOffset);
 
     // The pres shell resolution is updated by the the async zoom since the
-    // last paint.
-    float presShellResolution = aMetrics.mPresShellResolution
-                              * aMetrics.GetAsyncZoom().scale;
-    aUtils->SetResolution(presShellResolution, presShellResolution);
+    // last paint. The ScreenToLayerScale(1.0f) reflects this async zoom being
+    // turned into a "sync" zoom during the repaint.
+    ParentLayerToLayerScale presShellResolution = aMetrics.mPresShellResolution
+                                                * aMetrics.GetAsyncZoom()
+                                                * ScreenToLayerScale(1.0f);
+    aUtils->SetResolution(presShellResolution.scale, presShellResolution.scale);
 
     // Finally, we set the displayport.
     nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId());
     if (!content) {
         return;
     }
     nsCOMPtr<nsIDOMElement> element = do_QueryInterface(content);
     if (!element) {
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -742,18 +742,18 @@ ClientLayerManager::ProgressiveUpdateCal
   // This is derived from the code in
   // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree.
   CSSToLayerScale paintScale = aMetrics.LayersPixelsPerCSSPixel();
   const CSSRect& metricsDisplayPort =
     (aDrawingCritical && !aMetrics.mCriticalDisplayPort.IsEmpty()) ?
       aMetrics.mCriticalDisplayPort : aMetrics.mDisplayPort;
   LayerRect displayPort = (metricsDisplayPort + aMetrics.GetScrollOffset()) * paintScale;
 
-  ParentLayerPoint scrollOffset;
-  CSSToParentLayerScale zoom;
+  ScreenPoint scrollOffset;
+  CSSToScreenScale zoom;
   bool ret = AndroidBridge::Bridge()->ProgressiveUpdateCallback(
     aHasPendingNewThebesContent, displayPort, paintScale.scale, aDrawingCritical,
     scrollOffset, zoom);
   aMetrics.SetScrollOffset(scrollOffset / zoom);
   aMetrics.SetZoom(zoom);
   return ret;
 #else
   return false;
--- a/gfx/layers/client/ClientTiledPaintedLayer.cpp
+++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp
@@ -70,17 +70,17 @@ GetTransformToAncestorsParentLayer(Layer
   const LayerMetricsWrapper& ancestorParent = aAncestor.GetParent();
   for (LayerMetricsWrapper iter(aStart, LayerMetricsWrapper::StartAt::BOTTOM);
        ancestorParent ? iter != ancestorParent : iter.IsValid();
        iter = iter.GetParent()) {
     transform = transform * iter.GetTransform();
     // If the layer has a non-transient async transform then we need to apply it here
     // because it will get applied by the APZ in the compositor as well
     const FrameMetrics& metrics = iter.Metrics();
-    transform.PostScale(metrics.mPresShellResolution, metrics.mPresShellResolution, 1.f);
+    transform.PostScale(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale, 1.f);
   }
   return transform;
 }
 
 void
 ClientTiledPaintedLayer::GetAncestorLayers(LayerMetricsWrapper* aOutScrollAncestor,
                                           LayerMetricsWrapper* aOutDisplayPortAncestor)
 {
@@ -144,41 +144,47 @@ ClientTiledPaintedLayer::BeginPaint()
   const FrameMetrics& displayportMetrics = displayPortAncestor.Metrics();
 
   // Calculate the transform required to convert ParentLayer space of our
   // display port ancestor to the Layer space of this layer.
   gfx::Matrix4x4 transformDisplayPortToLayer =
     GetTransformToAncestorsParentLayer(this, displayPortAncestor);
   transformDisplayPortToLayer.Invert();
 
+  // Note that below we use GetZoomToParent() in a number of places. Because this
+  // code runs on the client side, the mTransformScale field of the FrameMetrics
+  // will not have been set. This can result in incorrect values being returned
+  // by GetZoomToParent() when we have CSS transforms set on some of these layers.
+  // This code should be audited and updated as part of fixing bug 993525.
+
   // Compute the critical display port that applies to this layer in the
   // LayoutDevice space of this layer.
   ParentLayerRect criticalDisplayPort =
-    (displayportMetrics.mCriticalDisplayPort * displayportMetrics.GetZoom())
+    (displayportMetrics.mCriticalDisplayPort * displayportMetrics.GetZoomToParent())
     + displayportMetrics.mCompositionBounds.TopLeft();
   mPaintData.mCriticalDisplayPort = RoundedOut(
     ApplyParentLayerToLayerTransform(transformDisplayPortToLayer, criticalDisplayPort));
   TILING_LOG("TILING %p: Critical displayport %s\n", this, Stringify(mPaintData.mCriticalDisplayPort).c_str());
 
   // Store the resolution from the displayport ancestor layer. Because this is Gecko-side,
   // before any async transforms have occurred, we can use the zoom for this.
-  mPaintData.mResolution = displayportMetrics.GetZoom();
+  mPaintData.mResolution = displayportMetrics.GetZoomToParent();
   TILING_LOG("TILING %p: Resolution %f\n", this, mPaintData.mPresShellResolution.scale);
 
   // Store the applicable composition bounds in this layer's Layer units.
   mPaintData.mTransformToCompBounds =
     GetTransformToAncestorsParentLayer(this, scrollAncestor);
   gfx::Matrix4x4 transformToBounds = mPaintData.mTransformToCompBounds;
   transformToBounds.Invert();
   mPaintData.mCompositionBounds = ApplyParentLayerToLayerTransform(
     transformToBounds, scrollMetrics.mCompositionBounds);
   TILING_LOG("TILING %p: Composition bounds %s\n", this, Stringify(mPaintData.mCompositionBounds).c_str());
 
   // Calculate the scroll offset since the last transaction
-  mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoom();
+  mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoomToParent();
   TILING_LOG("TILING %p: Scroll offset %s\n", this, Stringify(mPaintData.mScrollOffset).c_str());
 }
 
 bool
 ClientTiledPaintedLayer::UseFastPath()
 {
   LayerMetricsWrapper scrollAncestor;
   GetAncestorLayers(&scrollAncestor, nullptr);
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -145,20 +145,20 @@ FuzzyEquals(float a, float b) {
 
 static ViewTransform
 ComputeViewTransform(const FrameMetrics& aContentMetrics, const FrameMetrics& aCompositorMetrics)
 {
   // This is basically the same code as AsyncPanZoomController::GetCurrentAsyncTransform
   // but with aContentMetrics used in place of mLastContentPaintMetrics, because they
   // should be equivalent, modulo race conditions while transactions are inflight.
 
-  LayerToParentLayerScale scale(aCompositorMetrics.mPresShellResolution
-                                * aCompositorMetrics.GetAsyncZoom().scale);
-  ParentLayerPoint translation = (aCompositorMetrics.GetScrollOffset() - aContentMetrics.GetScrollOffset())
-                               * aCompositorMetrics.GetZoom();
+  ParentLayerToScreenScale scale = aCompositorMetrics.mPresShellResolution
+                                 * aCompositorMetrics.GetAsyncZoom();
+  ScreenPoint translation = (aCompositorMetrics.GetScrollOffset() - aContentMetrics.GetScrollOffset())
+                         * aCompositorMetrics.GetZoom();
   return ViewTransform(scale, -translation);
 }
 
 bool
 SharedFrameMetricsHelper::UpdateFromCompositorFrameMetrics(
     const LayerMetricsWrapper& aLayer,
     bool aHasPendingNewThebesContent,
     bool aLowPrecision,
@@ -1361,18 +1361,18 @@ ClientTiledLayerBuffer::ValidateTile(Til
  * for the compositor state.
  */
 static LayerRect
 GetCompositorSideCompositionBounds(const LayerMetricsWrapper& aScrollAncestor,
                                    const Matrix4x4& aTransformToCompBounds,
                                    const ViewTransform& aAPZTransform)
 {
   Matrix4x4 nonTransientAPZUntransform = Matrix4x4::Scaling(
-    aScrollAncestor.Metrics().mPresShellResolution,
-    aScrollAncestor.Metrics().mPresShellResolution,
+    aScrollAncestor.Metrics().mPresShellResolution.scale,
+    aScrollAncestor.Metrics().mPresShellResolution.scale,
     1.f);
   nonTransientAPZUntransform.Invert();
 
   // Take off the last "term" of aTransformToCompBounds, which
   // is the APZ's nontransient async transform. Replace it with
   // the APZ's async transform (this includes the nontransient
   // component as well).
   Matrix4x4 transform = aTransformToCompBounds
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -583,17 +583,17 @@ AsyncCompositionManager::ApplyAsyncConte
     AsyncPanZoomController* controller = aLayer->GetAsyncPanZoomController(i);
     if (!controller) {
       continue;
     }
 
     hasAsyncTransform = true;
 
     ViewTransform asyncTransformWithoutOverscroll;
-    ParentLayerPoint scrollOffset;
+    ScreenPoint scrollOffset;
     controller->SampleContentTransformForFrame(&asyncTransformWithoutOverscroll,
                                                scrollOffset);
     Matrix4x4 overscrollTransform = controller->GetOverscrollTransform();
 
     if (!aLayer->IsScrollInfoLayer()) {
       controller->MarkAsyncTransformAppliedToContent();
     }
 
@@ -713,25 +713,25 @@ ApplyAsyncTransformToScrollbarForContent
     if (aScrollbarIsDescendant) {
       // In cases where the scrollbar is a descendant of the content, the
       // scrollbar gets painted at the same resolution as the content. Since the
       // coordinate space we apply this transform in includes the resolution, we
       // need to adjust for it as well here. Note that in another
       // aScrollbarIsDescendant hunk below we unapply the entire async
       // transform, which includes the nontransientasync transform and would
       // normally account for the resolution.
-      scale *= metrics.mPresShellResolution;
+      scale *= metrics.mPresShellResolution.scale;
     }
     scrollbarTransform.PostScale(1.f, 1.f / transientTransform._22, 1.f);
     scrollbarTransform.PostTranslate(0, -transientTransform._42 * scale, 0);
   }
   if (aScrollbar->GetScrollbarDirection() == Layer::HORIZONTAL) {
     float scale = metrics.CalculateCompositedSizeInCssPixels().width / metrics.mScrollableRect.width;
     if (aScrollbarIsDescendant) {
-      scale *= metrics.mPresShellResolution;
+      scale *= metrics.mPresShellResolution.scale;
     }
     scrollbarTransform.PostScale(1.f / transientTransform._11, 1.f, 1.f);
     scrollbarTransform.PostTranslate(-transientTransform._41 * scale, 0, 0);
   }
 
   Matrix4x4 transform = scrollbarTransform * aScrollbar->GetTransform();
 
   if (aScrollbarIsDescendant) {
@@ -863,57 +863,57 @@ AsyncCompositionManager::TransformScroll
   LayerMargin fixedLayerMargins(0, 0, 0, 0);
   ScreenPoint offset(0, 0);
 
   // Ideally we would initialize userZoom to AsyncPanZoomController::CalculateResolution(metrics)
   // but this causes a reftest-ipc test to fail (see bug 883646 comment 27). The reason for this
   // appears to be that metrics.mZoom is poorly initialized in some scenarios. In these scenarios,
   // however, we can assume there is no async zooming in progress and so the following statement
   // works fine.
-  CSSToParentLayerScale userZoom(metrics.mDevPixelsPerCSSPixel * metrics.mCumulativeResolution * LayerToParentLayerScale(1));
-  ParentLayerPoint userScroll = metrics.GetScrollOffset() * userZoom;
+  CSSToScreenScale userZoom(metrics.mDevPixelsPerCSSPixel * metrics.mCumulativeResolution * LayerToScreenScale(1));
+  ScreenPoint userScroll = metrics.GetScrollOffset() * userZoom;
   SyncViewportInfo(displayPort, geckoZoom, mLayersUpdated,
                    userScroll, userZoom, fixedLayerMargins,
                    offset);
   mLayersUpdated = false;
 
   // Apply the render offset
   mLayerManager->GetCompositor()->SetScreenRenderOffset(offset);
 
   // Handle transformations for asynchronous panning and zooming. We determine the
   // zoom used by Gecko from the transformation set on the root layer, and we
   // determine the scroll offset used by Gecko from the frame metrics of the
   // primary scrollable layer. We compare this to the user zoom and scroll
   // offset in the view transform we obtained from Java in order to compute the
   // transformation we need to apply.
-  ParentLayerPoint geckoScroll(0, 0);
+  ScreenPoint geckoScroll(0, 0);
   if (metrics.IsScrollable()) {
     geckoScroll = metrics.GetScrollOffset() * userZoom;
   }
 
-  LayerToParentLayerScale asyncZoom = userZoom / metrics.LayersPixelsPerCSSPixel();
-  LayerToParentLayerScale scale(metrics.mPresShellResolution
-                                * asyncZoom.scale);
-  ParentLayerPoint translation = userScroll - geckoScroll;
+  LayerToScreenScale asyncZoom = userZoom / metrics.LayersPixelsPerCSSPixel();
+  ParentLayerToScreenScale scale = metrics.mPresShellResolution
+                                 * asyncZoom;
+  ScreenPoint translation = userScroll - geckoScroll;
   Matrix4x4 treeTransform = ViewTransform(scale, -translation);
 
   SetShadowTransform(aLayer, oldTransform * treeTransform);
   NS_ASSERTION(!aLayer->AsLayerComposite()->GetShadowTransformSetByAnimation(),
                "overwriting animated transform!");
 
   // Apply resolution scaling to the old transform - the layer tree as it is
   // doesn't have the necessary transform to display correctly.
-  oldTransform.PreScale(metrics.mPresShellResolution, metrics.mPresShellResolution, 1);
+  oldTransform.PreScale(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale, 1);
 
   // Make sure that overscroll and under-zoom are represented in the old
   // transform so that fixed position content moves and scales accordingly.
   // These calculations will effectively scale and offset fixed position layers
   // in screen space when the compensatory transform is performed in
   // AlignFixedAndStickyLayers.
-  ParentLayerRect contentScreenRect = mContentRect * userZoom;
+  ScreenRect contentScreenRect = mContentRect * userZoom;
   Point3D overscrollTranslation;
   if (userScroll.x < contentScreenRect.x) {
     overscrollTranslation.x = contentScreenRect.x - userScroll.x;
   } else if (userScroll.x + metrics.mCompositionBounds.width > contentScreenRect.XMost()) {
     overscrollTranslation.x = contentScreenRect.XMost() -
       (userScroll.x + metrics.mCompositionBounds.width);
   }
   if (userScroll.y < contentScreenRect.y) {
@@ -1013,34 +1013,34 @@ AsyncCompositionManager::SetPageRect(con
   AndroidBridge::Bridge()->SetPageRect(aCssPageRect);
 #endif
 }
 
 void
 AsyncCompositionManager::SyncViewportInfo(const LayerIntRect& aDisplayPort,
                                           const CSSToLayerScale& aDisplayResolution,
                                           bool aLayersUpdated,
-                                          ParentLayerPoint& aScrollOffset,
-                                          CSSToParentLayerScale& aScale,
+                                          ScreenPoint& aScrollOffset,
+                                          CSSToScreenScale& aScale,
                                           LayerMargin& aFixedLayerMargins,
                                           ScreenPoint& aOffset)
 {
 #ifdef MOZ_WIDGET_ANDROID
   AndroidBridge::Bridge()->SyncViewportInfo(aDisplayPort,
                                             aDisplayResolution,
                                             aLayersUpdated,
                                             aScrollOffset,
                                             aScale,
                                             aFixedLayerMargins,
                                             aOffset);
 #endif
 }
 
 void
-AsyncCompositionManager::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset,
+AsyncCompositionManager::SyncFrameMetrics(const ScreenPoint& aScrollOffset,
                                           float aZoom,
                                           const CSSRect& aCssPageRect,
                                           bool aLayersUpdated,
                                           const CSSRect& aDisplayPort,
                                           const CSSToLayerScale& aDisplayResolution,
                                           bool aIsFirstPaint,
                                           LayerMargin& aFixedLayerMargins,
                                           ScreenPoint& aOffset)
--- a/gfx/layers/composite/AsyncCompositionManager.h
+++ b/gfx/layers/composite/AsyncCompositionManager.h
@@ -23,18 +23,18 @@ namespace layers {
 
 class AsyncPanZoomController;
 class Layer;
 class LayerManagerComposite;
 class AutoResolveRefLayers;
 
 // Represents (affine) transforms that are calculated from a content view.
 struct ViewTransform {
-  explicit ViewTransform(LayerToParentLayerScale aScale = LayerToParentLayerScale(),
-                         ParentLayerPoint aTranslation = ParentLayerPoint())
+  explicit ViewTransform(ParentLayerToScreenScale aScale = ParentLayerToScreenScale(),
+                         ScreenPoint aTranslation = ScreenPoint())
     : mScale(aScale)
     , mTranslation(aTranslation)
   {}
 
   operator gfx::Matrix4x4() const
   {
     return
       gfx::Matrix4x4::Scaling(mScale.scale, mScale.scale, 1)
@@ -50,18 +50,18 @@ struct ViewTransform {
   bool operator==(const ViewTransform& rhs) const {
     return mTranslation == rhs.mTranslation && mScale == rhs.mScale;
   }
 
   bool operator!=(const ViewTransform& rhs) const {
     return !(*this == rhs);
   }
 
-  LayerToParentLayerScale mScale;
-  ParentLayerPoint mTranslation;
+  ParentLayerToScreenScale mScale;
+  ScreenPoint mTranslation;
 };
 
 /**
  * Manage async composition effects. This class is only used with OMTC and only
  * lives on the compositor thread. It is a layer on top of the layer manager
  * (LayerManagerComposite) which deals with elements of composition which are
  * usually dealt with by dom or layout when main thread rendering, but which can
  * short circuit that stuff to directly affect layers as they are composited,
@@ -134,21 +134,21 @@ private:
 
   void SetFirstPaintViewport(const LayerIntPoint& aOffset,
                              const CSSToLayerScale& aZoom,
                              const CSSRect& aCssPageRect);
   void SetPageRect(const CSSRect& aCssPageRect);
   void SyncViewportInfo(const LayerIntRect& aDisplayPort,
                         const CSSToLayerScale& aDisplayResolution,
                         bool aLayersUpdated,
-                        ParentLayerPoint& aScrollOffset,
-                        CSSToParentLayerScale& aScale,
+                        ScreenPoint& aScrollOffset,
+                        CSSToScreenScale& aScale,
                         LayerMargin& aFixedLayerMargins,
                         ScreenPoint& aOffset);
-  void SyncFrameMetrics(const ParentLayerPoint& aScrollOffset,
+  void SyncFrameMetrics(const ScreenPoint& aScrollOffset,
                         float aZoom,
                         const CSSRect& aCssPageRect,
                         bool aLayersUpdated,
                         const CSSRect& aDisplayPort,
                         const CSSToLayerScale& aDisplayResolution,
                         bool aIsFirstPaint,
                         LayerMargin& aFixedLayerMargins,
                         ScreenPoint& aOffset);
--- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp
+++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp
@@ -183,17 +183,17 @@ public:
                                  const TimeDuration& aIncrement = TimeDuration::FromMilliseconds(10)) {
     while (AdvanceAnimations(aSampleTime)) {
       aSampleTime += aIncrement;
     }
   }
 
   bool SampleContentTransformForFrame(const TimeStamp& aSampleTime,
                                       ViewTransform* aOutTransform,
-                                      ParentLayerPoint& aScrollOffset) {
+                                      ScreenPoint& aScrollOffset) {
     bool ret = AdvanceAnimations(aSampleTime);
     AsyncPanZoomController::SampleContentTransformForFrame(
       aOutTransform, aScrollOffset);
     return ret;
   }
 };
 
 static FrameMetrics
@@ -238,22 +238,22 @@ protected:
 
   void SetMayHaveTouchListeners()
   {
     apzc->GetFrameMetrics().SetMayHaveTouchListeners(true);
   }
 
   void MakeApzcZoomable()
   {
-    apzc->UpdateZoomConstraints(ZoomConstraints(true, true, CSSToParentLayerScale(0.25f), CSSToParentLayerScale(4.0f)));
+    apzc->UpdateZoomConstraints(ZoomConstraints(true, true, CSSToScreenScale(0.25f), CSSToScreenScale(4.0f)));
   }
 
   void MakeApzcUnzoomable()
   {
-    apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToParentLayerScale(1.0f), CSSToParentLayerScale(1.0f)));
+    apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0f), CSSToScreenScale(1.0f)));
   }
 
   AsyncPanZoomController::GestureBehavior mGestureBehavior;
   TimeStamp testStartTime;
   nsRefPtr<MockContentControllerDelayed> mcc;
   nsRefPtr<TestAPZCTreeManager> tm;
   nsRefPtr<TestAsyncPanZoomController> apzc;
 };
@@ -272,59 +272,37 @@ public:
  *                                 ScrollableLayerGuid* aGuid,
  *                                 uint64_t* aOutInputBlockId);
  * The classes that currently implement this are APZCTreeManager and
  * TestAsyncPanZoomController. Using this template allows us to test individual
  * APZC instances in isolation and also an entire APZ tree, while using the same
  * code to dispatch input events.
  */
 
-// Some helper functions for constructing input event objects suitable to be
-// passed either to an APZC (which expects an transformed point), or to an APZTM
-// (which expects an untransformed point). We handle both cases by setting both
-// the transformed and untransformed fields to the same value.
-static SingleTouchData
-CreateSingleTouchData(int32_t aIdentifier, int aX, int aY)
-{
-  SingleTouchData touch(aIdentifier, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0);
-  touch.mLocalScreenPoint = ParentLayerPoint(aX, aY);
-  return touch;
-}
-static PinchGestureInput
-CreatePinchGestureInput(PinchGestureInput::PinchGestureType aType,
-                        int aFocusX, int aFocusY,
-                        float aCurrentSpan, float aPreviousSpan)
-{
-  PinchGestureInput result(aType, 0, TimeStamp(), ScreenPoint(aFocusX, aFocusY),
-                           aCurrentSpan, aPreviousSpan, 0);
-  result.mLocalFocusPoint = ParentLayerPoint(aFocusX, aFocusY);
-  return result;
-}
-
 template<class InputReceiver> static nsEventStatus
 TouchDown(const nsRefPtr<InputReceiver>& aTarget, int aX, int aY, int aTime, uint64_t* aOutInputBlockId = nullptr)
 {
   MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, aTime, TimeStamp(), 0);
-  mti.mTouches.AppendElement(CreateSingleTouchData(0, aX, aY));
+  mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0));
   return aTarget->ReceiveInputEvent(mti, nullptr, aOutInputBlockId);
 }
 
 template<class InputReceiver> static nsEventStatus
 TouchMove(const nsRefPtr<InputReceiver>& aTarget, int aX, int aY, int aTime)
 {
   MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, aTime, TimeStamp(), 0);
-  mti.mTouches.AppendElement(CreateSingleTouchData(0, aX, aY));
+  mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0));
   return aTarget->ReceiveInputEvent(mti, nullptr, nullptr);
 }
 
 template<class InputReceiver> static nsEventStatus
 TouchUp(const nsRefPtr<InputReceiver>& aTarget, int aX, int aY, int aTime)
 {
   MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, aTime, TimeStamp(), 0);
-  mti.mTouches.AppendElement(CreateSingleTouchData(0, aX, aY));
+  mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0));
   return aTarget->ReceiveInputEvent(mti, nullptr, nullptr);
 }
 
 template<class InputReceiver> static void
 Tap(const nsRefPtr<InputReceiver>& aTarget, int aX, int aY, int& aTime, int aTapLength,
     nsEventStatus (*aOutEventStatuses)[2] = nullptr)
 {
   nsEventStatus status = TouchDown(aTarget, aX, aY, aTime);
@@ -452,35 +430,38 @@ ApzcPanNoFling(const nsRefPtr<TestAsyncP
 }
 
 template<class InputReceiver> static void
 PinchWithPinchInput(const nsRefPtr<InputReceiver>& aTarget,
                     int aFocusX, int aFocusY, float aScale,
                     nsEventStatus (*aOutEventStatuses)[3] = nullptr)
 {
   nsEventStatus actualStatus = aTarget->ReceiveInputEvent(
-      CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_START,
-                              aFocusX, aFocusY, 10.0, 10.0),
-      nullptr);
+    PinchGestureInput(PinchGestureInput::PINCHGESTURE_START,
+                      0, TimeStamp(), ScreenPoint(aFocusX, aFocusY),
+                      10.0, 10.0, 0),
+    nullptr);
   if (aOutEventStatuses) {
     (*aOutEventStatuses)[0] = actualStatus;
   }
   actualStatus = aTarget->ReceiveInputEvent(
-      CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_SCALE,
-                              aFocusX, aFocusY, 10.0 * aScale, 10.0),
-      nullptr);
+    PinchGestureInput(PinchGestureInput::PINCHGESTURE_SCALE,
+                      0, TimeStamp(), ScreenPoint(aFocusX, aFocusY),
+                      10.0 * aScale, 10.0, 0),
+    nullptr);
   if (aOutEventStatuses) {
     (*aOutEventStatuses)[1] = actualStatus;
   }
   actualStatus = aTarget->ReceiveInputEvent(
-      CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_END,
-                              // note: negative values here tell APZC
-                              //       not to turn the pinch into a pan
-                              aFocusX, aFocusY, -1.0, -1.0),
-      nullptr);
+    PinchGestureInput(PinchGestureInput::PINCHGESTURE_END,
+                      0, TimeStamp(), ScreenPoint(aFocusX, aFocusY),
+                      // note: negative values here tell APZC
+                      //       not to turn the pinch into a pan
+                      -1.0, -1.0, 0),
+    nullptr);
   if (aOutEventStatuses) {
     (*aOutEventStatuses)[2] = actualStatus;
   }
 }
 
 template<class InputReceiver> static void
 PinchWithPinchInputAndCheckStatus(const nsRefPtr<InputReceiver>& aTarget,
                                   int aFocusX, int aFocusY, float aScale,
@@ -512,46 +493,46 @@ PinchWithTouchInput(const nsRefPtr<Input
   // Even if the caller doesn't care about the block id, we need it to set the
   // allowed touch behaviour below, so make sure aOutInputBlockId is non-null.
   uint64_t blockId;
   if (!aOutInputBlockId) {
     aOutInputBlockId = &blockId;
   }
 
   MultiTouchInput mtiStart = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0);
-  mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX, aFocusY));
-  mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX, aFocusY));
+  mtiStart.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX, aFocusY), ScreenSize(0, 0), 0, 0));
+  mtiStart.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX, aFocusY), ScreenSize(0, 0), 0, 0));
   nsEventStatus status = aTarget->ReceiveInputEvent(mtiStart, aOutInputBlockId);
   if (aOutEventStatuses) {
     (*aOutEventStatuses)[0] = status;
   }
 
   if (gfxPrefs::TouchActionEnabled() && aAllowedTouchBehaviors) {
     aTarget->SetAllowedTouchBehavior(*aOutInputBlockId, *aAllowedTouchBehaviors);
   }
 
   MultiTouchInput mtiMove1 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0);
-  mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX - pinchLength, aFocusY));
-  mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX + pinchLength, aFocusY));
+  mtiMove1.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLength, aFocusY), ScreenSize(0, 0), 0, 0));
+  mtiMove1.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLength, aFocusY), ScreenSize(0, 0), 0, 0));
   status = aTarget->ReceiveInputEvent(mtiMove1, nullptr);
   if (aOutEventStatuses) {
     (*aOutEventStatuses)[1] = status;
   }
 
   MultiTouchInput mtiMove2 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0);
-  mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX - pinchLengthScaled, aFocusY));
-  mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX + pinchLengthScaled, aFocusY));
+  mtiMove2.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0));
+  mtiMove2.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0));
   status = aTarget->ReceiveInputEvent(mtiMove2, nullptr);
   if (aOutEventStatuses) {
     (*aOutEventStatuses)[2] = status;
   }
 
   MultiTouchInput mtiEnd = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, 0, TimeStamp(), 0);
-  mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX - pinchLengthScaled, aFocusY));
-  mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX + pinchLengthScaled, aFocusY));
+  mtiEnd.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0));
+  mtiEnd.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0));
   status = aTarget->ReceiveInputEvent(mtiEnd, nullptr);
   if (aOutEventStatuses) {
     (*aOutEventStatuses)[3] = status;
   }
 
   inputId += 2;
 }
 
@@ -581,17 +562,17 @@ public:
 
 protected:
   FrameMetrics GetPinchableFrameMetrics()
   {
     FrameMetrics fm;
     fm.mCompositionBounds = ParentLayerRect(200, 200, 100, 200);
     fm.mScrollableRect = CSSRect(0, 0, 980, 1000);
     fm.SetScrollOffset(CSSPoint(300, 300));
-    fm.SetZoom(CSSToParentLayerScale(2.0));
+    fm.SetZoom(CSSToScreenScale(2.0));
     // the visible area of the document in CSS pixels is x=300 y=300 w=50 h=100
     return fm;
   }
 
   void DoPinchTest(bool aShouldTriggerPinch,
                    nsTArray<uint32_t> *aAllowedTouchBehaviors = nullptr)
   {
     apzc->SetFrameMetrics(GetPinchableFrameMetrics());
@@ -624,17 +605,17 @@ protected:
       // apzc ignore pinch gestures.
       EXPECT_EQ(2.0f, fm.GetZoom().scale);
       EXPECT_EQ(300, fm.GetScrollOffset().x);
       EXPECT_EQ(300, fm.GetScrollOffset().y);
     }
 
     // part 2 of the test, move to the top-right corner of the page and pinch and
     // make sure we stay in the correct spot
-    fm.SetZoom(CSSToParentLayerScale(2.0));
+    fm.SetZoom(CSSToScreenScale(2.0));
     fm.SetScrollOffset(CSSPoint(930, 5));
     apzc->SetFrameMetrics(fm);
     // the visible area of the document in CSS pixels is x=930 y=5 w=50 h=100
 
     if (mGestureBehavior == AsyncPanZoomController::USE_GESTURE_DETECTOR) {
       PinchWithTouchInputAndCheckStatus(apzc, 250, 300, 0.5, touchInputId, aShouldTriggerPinch, aAllowedTouchBehaviors);
     } else {
       PinchWithPinchInputAndCheckStatus(apzc, 250, 300, 0.5, aShouldTriggerPinch);
@@ -723,17 +704,17 @@ TEST_F(APZCPinchGestureDetectorTester, P
 }
 
 TEST_F(APZCBasicTester, Overzoom) {
   // the visible area of the document in CSS pixels is x=10 y=0 w=100 h=100
   FrameMetrics fm;
   fm.mCompositionBounds = ParentLayerRect(0, 0, 100, 100);
   fm.mScrollableRect = CSSRect(0, 0, 125, 150);
   fm.SetScrollOffset(CSSPoint(10, 0));
-  fm.SetZoom(CSSToParentLayerScale(1.0));
+  fm.SetZoom(CSSToScreenScale(1.0));
   apzc->SetFrameMetrics(fm);
 
   MakeApzcZoomable();
 
   EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
   EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
 
   PinchWithPinchInputAndCheckStatus(apzc, 50, 50, 0.5, true);
@@ -742,21 +723,21 @@ TEST_F(APZCBasicTester, Overzoom) {
   EXPECT_EQ(0.8f, fm.GetZoom().scale);
   // bug 936721 - PGO builds introduce rounding error so
   // use a fuzzy match instead
   EXPECT_LT(abs(fm.GetScrollOffset().x), 1e-5);
   EXPECT_LT(abs(fm.GetScrollOffset().y), 1e-5);
 }
 
 TEST_F(APZCBasicTester, SimpleTransform) {
-  ParentLayerPoint pointOut;
+  ScreenPoint pointOut;
   ViewTransform viewTransformOut;
   apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
 
-  EXPECT_EQ(ParentLayerPoint(), pointOut);
+  EXPECT_EQ(ScreenPoint(), pointOut);
   EXPECT_EQ(ViewTransform(), viewTransformOut);
 }
 
 
 TEST_F(APZCBasicTester, ComplexTransform) {
   // This test assumes there is a page that gets rendered to
   // two layers. In CSS pixels, the first layer is 50x50 and
   // the second layer is 25x50. The widget scale factor is 3.0
@@ -792,71 +773,71 @@ TEST_F(APZCBasicTester, ComplexTransform
   nsRefPtr<Layer> root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, lm, layers);
 
   FrameMetrics metrics;
   metrics.mCompositionBounds = ParentLayerRect(0, 0, 24, 24);
   metrics.mDisplayPort = CSSRect(-1, -1, 6, 6);
   metrics.SetScrollOffset(CSSPoint(10, 10));
   metrics.mScrollableRect = CSSRect(0, 0, 50, 50);
   metrics.mCumulativeResolution = LayoutDeviceToLayerScale(2);
-  metrics.mPresShellResolution = 2.0f;
-  metrics.SetZoom(CSSToParentLayerScale(6));
+  metrics.mPresShellResolution = ParentLayerToLayerScale(2);
+  metrics.SetZoom(CSSToScreenScale(6));
   metrics.mDevPixelsPerCSSPixel = CSSToLayoutDeviceScale(3);
   metrics.SetScrollId(FrameMetrics::START_SCROLL_ID);
 
   FrameMetrics childMetrics = metrics;
   childMetrics.SetScrollId(FrameMetrics::START_SCROLL_ID + 1);
 
   layers[0]->SetFrameMetrics(metrics);
   layers[1]->SetFrameMetrics(childMetrics);
 
-  ParentLayerPoint pointOut;
+  ScreenPoint pointOut;
   ViewTransform viewTransformOut;
 
   // Both the parent and child layer should behave exactly the same here, because
   // the CSS transform on the child layer does not affect the SampleContentTransformForFrame code
 
   // initial transform
   apzc->SetFrameMetrics(metrics);
   apzc->NotifyLayersUpdated(metrics, true);
   apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
-  EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint()), viewTransformOut);
-  EXPECT_EQ(ParentLayerPoint(60, 60), pointOut);
+  EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(2), ScreenPoint()), viewTransformOut);
+  EXPECT_EQ(ScreenPoint(60, 60), pointOut);
 
   childApzc->SetFrameMetrics(childMetrics);
   childApzc->NotifyLayersUpdated(childMetrics, true);
   childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
-  EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint()), viewTransformOut);
-  EXPECT_EQ(ParentLayerPoint(60, 60), pointOut);
+  EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(2), ScreenPoint()), viewTransformOut);
+  EXPECT_EQ(ScreenPoint(60, 60), pointOut);
 
   // do an async scroll by 5 pixels and check the transform
   metrics.ScrollBy(CSSPoint(5, 0));
   apzc->SetFrameMetrics(metrics);
   apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
-  EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint(-30, 0)), viewTransformOut);
-  EXPECT_EQ(ParentLayerPoint(90, 60), pointOut);
+  EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(2), ScreenPoint(-30, 0)), viewTransformOut);
+  EXPECT_EQ(ScreenPoint(90, 60), pointOut);
 
   childMetrics.ScrollBy(CSSPoint(5, 0));
   childApzc->SetFrameMetrics(childMetrics);
   childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
-  EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint(-30, 0)), viewTransformOut);
-  EXPECT_EQ(ParentLayerPoint(90, 60), pointOut);
+  EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(2), ScreenPoint(-30, 0)), viewTransformOut);
+  EXPECT_EQ(ScreenPoint(90, 60), pointOut);
 
   // do an async zoom of 1.5x and check the transform
   metrics.ZoomBy(1.5f);
   apzc->SetFrameMetrics(metrics);
   apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
-  EXPECT_EQ(ViewTransform(LayerToParentLayerScale(3), ParentLayerPoint(-45, 0)), viewTransformOut);
-  EXPECT_EQ(ParentLayerPoint(135, 90), pointOut);
+  EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(3), ScreenPoint(-45, 0)), viewTransformOut);
+  EXPECT_EQ(ScreenPoint(135, 90), pointOut);
 
   childMetrics.ZoomBy(1.5f);
   childApzc->SetFrameMetrics(childMetrics);
   childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
-  EXPECT_EQ(ViewTransform(LayerToParentLayerScale(3), ParentLayerPoint(-45, 0)), viewTransformOut);
-  EXPECT_EQ(ParentLayerPoint(135, 90), pointOut);
+  EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(3), ScreenPoint(-45, 0)), viewTransformOut);
+  EXPECT_EQ(ScreenPoint(135, 90), pointOut);
 }
 
 class APZCPanningTester : public APZCBasicTester {
 protected:
   void DoPanTest(bool aShouldTriggerScroll, bool aShouldBeConsumed, uint32_t aBehavior)
   {
     if (aShouldTriggerScroll) {
       EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
@@ -864,71 +845,71 @@ protected:
     } else {
       EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(0);
       EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
     }
 
     int time = 0;
     int touchStart = 50;
     int touchEnd = 10;
-    ParentLayerPoint pointOut;
+    ScreenPoint pointOut;
     ViewTransform viewTransformOut;
 
     nsTArray<uint32_t> allowedTouchBehaviors;
     allowedTouchBehaviors.AppendElement(aBehavior);
 
     // Pan down
     PanAndCheckStatus(apzc, time, touchStart, touchEnd, aShouldBeConsumed, &allowedTouchBehaviors);
     apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
 
     if (aShouldTriggerScroll) {
-      EXPECT_EQ(ParentLayerPoint(0, -(touchEnd-touchStart)), pointOut);
+      EXPECT_EQ(ScreenPoint(0, -(touchEnd-touchStart)), pointOut);
       EXPECT_NE(ViewTransform(), viewTransformOut);
     } else {
-      EXPECT_EQ(ParentLayerPoint(), pointOut);
+      EXPECT_EQ(ScreenPoint(), pointOut);
       EXPECT_EQ(ViewTransform(), viewTransformOut);
     }
 
     // Clear the fling from the previous pan, or stopping it will
     // consume the next touchstart
     apzc->CancelAnimation();
 
     // Pan back
     PanAndCheckStatus(apzc, time, touchEnd, touchStart, aShouldBeConsumed, &allowedTouchBehaviors);
     apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
 
-    EXPECT_EQ(ParentLayerPoint(), pointOut);
+    EXPECT_EQ(ScreenPoint(), pointOut);
     EXPECT_EQ(ViewTransform(), viewTransformOut);
   }
 
   void DoPanWithPreventDefaultTest()
   {
     SetMayHaveTouchListeners();
 
     int time = 0;
     int touchStart = 50;
     int touchEnd = 10;
-    ParentLayerPoint pointOut;
+    ScreenPoint pointOut;
     ViewTransform viewTransformOut;
     uint64_t blockId = 0;
 
     // Pan down
     nsTArray<uint32_t> allowedTouchBehaviors;
     allowedTouchBehaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
     PanAndCheckStatus(apzc, time, touchStart, touchEnd, true, &allowedTouchBehaviors, &blockId);
 
     // Send the signal that content has handled and preventDefaulted the touch
     // events. This flushes the event queue.
     apzc->ContentReceivedTouch(blockId, true);
     // Run all pending tasks (this should include at least the
     // prevent-default timer).
     EXPECT_LE(1, mcc->RunThroughDelayedTasks());
 
     apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
-    EXPECT_EQ(ParentLayerPoint(), pointOut);
+    EXPECT_EQ(ScreenPoint(), pointOut);
     EXPECT_EQ(ViewTransform(), viewTransformOut);
 
     apzc->AssertStateIsReset();
   }
 };
 
 TEST_F(APZCPanningTester, Pan) {
   DoPanTest(true, true, mozilla::layers::AllowedTouchBehavior::NONE);
@@ -975,22 +956,22 @@ TEST_F(APZCPanningTester, PanWithPrevent
 
 TEST_F(APZCBasicTester, Fling) {
   EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(AtLeast(1));
   EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
 
   int time = 0;
   int touchStart = 50;
   int touchEnd = 10;
-  ParentLayerPoint pointOut;
+  ScreenPoint pointOut;
   ViewTransform viewTransformOut;
 
   // Fling down. Each step scroll further down
   Pan(apzc, time, touchStart, touchEnd);
-  ParentLayerPoint lastPoint;
+  ScreenPoint lastPoint;
   for (int i = 1; i < 50; i+=1) {
     apzc->SampleContentTransformForFrame(testStartTime+TimeDuration::FromMilliseconds(i), &viewTransformOut, pointOut);
     EXPECT_GT(pointOut.y, lastPoint.y);
     lastPoint = pointOut;
   }
 }
 
 TEST_F(APZCBasicTester, FlingIntoOverscroll) {
@@ -1068,21 +1049,21 @@ TEST_F(APZCBasicTester, OverScrollPannin
   int touchStart = 500;
   int touchEnd = 10;
   Pan(apzc, time, touchStart, touchEnd);
   EXPECT_TRUE(apzc->IsOverscrolled());
 
   // Check that we recover from overscroll via an animation.
   const TimeDuration increment = TimeDuration::FromMilliseconds(1);
   bool recoveredFromOverscroll = false;
-  ParentLayerPoint pointOut;
+  ScreenPoint pointOut;
   ViewTransform viewTransformOut;
   while (apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut)) {
     // The reported scroll offset should be the same throughout.
-    EXPECT_EQ(ParentLayerPoint(0, 90), pointOut);
+    EXPECT_EQ(ScreenPoint(0, 90), pointOut);
 
     if (!apzc->IsOverscrolled()) {
       recoveredFromOverscroll = true;
     }
 
     testStartTime += increment;
   }
   EXPECT_TRUE(recoveredFromOverscroll);
@@ -1094,17 +1075,17 @@ TEST_F(APZCBasicTester, OverScrollAbort)
 
   // Pan sufficiently to hit overscroll behavior
   int time = 0;
   int touchStart = 500;
   int touchEnd = 10;
   Pan(apzc, time, touchStart, touchEnd);
   EXPECT_TRUE(apzc->IsOverscrolled());
 
-  ParentLayerPoint pointOut;
+  ScreenPoint pointOut;
   ViewTransform viewTransformOut;
 
   // This sample call will run to the end of the fling animation
   // and will schedule the overscroll animation.
   apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(10000), &viewTransformOut, pointOut);
   EXPECT_TRUE(apzc->IsOverscrolled());
 
   // At this point, we have an active overscroll animation.
@@ -1154,28 +1135,28 @@ protected:
 
     // If we want to tap while the fling is fast, let the fling advance for 10ms only. If we want
     // the fling to slow down more, advance to 2000ms. These numbers may need adjusting if our
     // friction and threshold values change, but they should be deterministic at least.
     int timeDelta = aSlow ? 2000 : 10;
     int tapCallsExpected = aSlow ? 1 : 0;
 
     // Advance the fling animation by timeDelta milliseconds.
-    ParentLayerPoint pointOut;
+    ScreenPoint pointOut;
     ViewTransform viewTransformOut;
     apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(timeDelta), &viewTransformOut, pointOut);
 
     // Deliver a tap to abort the fling. Ensure that we get a HandleSingleTap
     // call out of it if and only if the fling is slow.
     EXPECT_CALL(*mcc, HandleSingleTap(_, 0, apzc->GetGuid())).Times(tapCallsExpected);
     Tap(apzc, 10, 10, time, 0);
     while (mcc->RunThroughDelayedTasks());
 
     // Verify that we didn't advance any further after the fling was aborted, in either case.
-    ParentLayerPoint finalPointOut;
+    ScreenPoint finalPointOut;
     apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(timeDelta + 1000), &viewTransformOut, finalPointOut);
     EXPECT_EQ(pointOut.x, finalPointOut.x);
     EXPECT_EQ(pointOut.y, finalPointOut.y);
 
     apzc->AssertStateIsReset();
   }
 
   void DoFlingStopWithSlowListener(bool aPreventDefault) {
@@ -1187,17 +1168,17 @@ protected:
     uint64_t blockId = 0;
 
     // Start the fling down.
     Pan(apzc, time, touchStart, touchEnd, false, nullptr, nullptr, &blockId);
     apzc->ContentReceivedTouch(blockId, false);
     while (mcc->RunThroughDelayedTasks());
 
     // Sample the fling a couple of times to ensure it's going.
-    ParentLayerPoint point, finalPoint;
+    ScreenPoint point, finalPoint;
     ViewTransform viewTransform;
     apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(10), &viewTransform, point);
     apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(20), &viewTransform, finalPoint);
     EXPECT_GT(finalPoint.y, point.y);
 
     // Now we put our finger down to stop the fling
     TouchDown(apzc, 10, 10, time, &blockId);
 
@@ -1399,29 +1380,29 @@ protected:
     // race. This takes the place of the "contextmenu" event.
     apzc->ContentReceivedTouch(blockId, true);
     mcc->CheckHasDelayedTask();
     mcc->RunDelayedTask();
 
     time += 1000;
 
     MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, time, TimeStamp(), 0);
-    mti.mTouches.AppendElement(SingleTouchData(0, ParentLayerPoint(touchX, touchEndY), ScreenSize(0, 0), 0, 0));
+    mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(touchX, touchEndY), ScreenSize(0, 0), 0, 0));
     status = apzc->ReceiveInputEvent(mti, nullptr);
     EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status);
 
     EXPECT_CALL(*mcc, HandleLongTapUp(CSSPoint(touchX, touchEndY), 0, apzc->GetGuid())).Times(0);
     status = TouchUp(apzc, touchX, touchEndY, time);
     EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status);
 
-    ParentLayerPoint pointOut;
+    ScreenPoint pointOut;
     ViewTransform viewTransformOut;
     apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
 
-    EXPECT_EQ(ParentLayerPoint(), pointOut);
+    EXPECT_EQ(ScreenPoint(), pointOut);
     EXPECT_EQ(ViewTransform(), viewTransformOut);
 
     apzc->AssertStateIsReset();
   }
 };
 
 TEST_F(APZCLongPressTester, LongPress) {
   DoLongPressTest(mozilla::layers::AllowedTouchBehavior::NONE);
@@ -1577,23 +1558,23 @@ TEST_F(APZCGestureDetectorTester, TapFol
   EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
 
   int time = 0;
   Tap(apzc, 10, 10, time, 100);
 
   int inputId = 0;
   MultiTouchInput mti;
   mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0);
-  mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0));
-  mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0));
+  mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0));
+  mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0));
   apzc->ReceiveInputEvent(mti, nullptr);
 
   mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, time, TimeStamp(), 0);
-  mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0));
-  mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0));
+  mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0));
+  mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0));
   apzc->ReceiveInputEvent(mti, nullptr);
 
   while (mcc->RunThroughDelayedTasks());
 
   apzc->AssertStateIsReset();
 }
 
 TEST_F(APZCGestureDetectorTester, TapFollowedByMultipleTouches) {
@@ -1602,27 +1583,27 @@ TEST_F(APZCGestureDetectorTester, TapFol
   EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
 
   int time = 0;
   Tap(apzc, 10, 10, time, 100);
 
   int inputId = 0;
   MultiTouchInput mti;
   mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0);
-  mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0));
+  mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0));
   apzc->ReceiveInputEvent(mti, nullptr);
 
   mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0);
-  mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0));
-  mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0));
+  mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0));
+  mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0));
   apzc->ReceiveInputEvent(mti, nullptr);
 
   mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, time, TimeStamp(), 0);
-  mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0));
-  mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0));
+  mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0));
+  mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0));
   apzc->ReceiveInputEvent(mti, nullptr);
 
   while (mcc->RunThroughDelayedTasks());
 
   apzc->AssertStateIsReset();
 }
 
 class APZCTreeManagerTester : public ::testing::Test {
--- a/layout/base/UnitTransforms.h
+++ b/layout/base/UnitTransforms.h
@@ -16,43 +16,29 @@ namespace mozilla {
 // coordinate system to another without changing the values it stores (this
 // can be thought of as a cast).
 // To use these functions, you must provide a justification for each use!
 // Feel free to add more justifications to PixelCastJustification, along with
 // a comment that explains under what circumstances it is appropriate to use.
 
 MOZ_BEGIN_ENUM_CLASS(PixelCastJustification, uint8_t)
   // For the root layer, Screen Pixel = Parent Layer Pixel.
-  ScreenIsParentLayerForRoot,
+  ScreenToParentLayerForRoot,
   // For the root composition size we want to view it as layer pixels in any layer
-  ParentLayerToLayerForRootComposition,
-  // The transform that is usually used to convert between two coordinate
-  // systems is not available (for example, because the object that stores it
-  // is being destroyed), so fall back to the identity.
-  TransformNotAvailable
+  ParentLayerToLayerForRootComposition
 MOZ_END_ENUM_CLASS(PixelCastJustification)
 
 template <class TargetUnits, class SourceUnits>
 gfx::SizeTyped<TargetUnits> ViewAs(const gfx::SizeTyped<SourceUnits>& aSize, PixelCastJustification) {
   return gfx::SizeTyped<TargetUnits>(aSize.width, aSize.height);
 }
 template <class TargetUnits, class SourceUnits>
 gfx::IntSizeTyped<TargetUnits> ViewAs(const gfx::IntSizeTyped<SourceUnits>& aSize, PixelCastJustification) {
   return gfx::IntSizeTyped<TargetUnits>(aSize.width, aSize.height);
 }
-template <class TargetUnits, class SourceUnits>
-gfx::PointTyped<TargetUnits> ViewAs(const gfx::PointTyped<SourceUnits>& aPoint, PixelCastJustification) {
-  return gfx::PointTyped<TargetUnits>(aPoint.x, aPoint.y);
-}
-template <class NewTargetUnits, class OldTargetUnits, class SourceUnits>
-gfx::ScaleFactor<SourceUnits, NewTargetUnits> ViewTargetAs(
-    const gfx::ScaleFactor<SourceUnits, OldTargetUnits>& aScaleFactor,
-    PixelCastJustification) {
-  return gfx::ScaleFactor<SourceUnits, NewTargetUnits>(aScaleFactor.scale);
-}
 
 // Convenience functions for casting untyped entities to typed entities.
 // Using these functions does not require a justification, but once we convert
 // all code to use strongly typed units they should not be needed any longer.
 template <class TargetUnits>
 gfx::PointTyped<TargetUnits> ViewAs(const gfxPoint& aPoint) {
   return gfx::PointTyped<TargetUnits>(aPoint.x, aPoint.y);
 }
@@ -100,24 +86,12 @@ static gfx::RectTyped<TargetUnits> Trans
 template <typename TargetUnits, typename SourceUnits>
 static gfx::IntRectTyped<TargetUnits> TransformTo(const gfx::Matrix4x4& aTransform,
                                                   const gfx::IntRectTyped<SourceUnits>& aRect)
 {
   gfx::Rect rect(aRect.ToUnknownRect());
   return RoundedToInt(ViewAs<TargetUnits>(aTransform.TransformBounds(rect)));
 }
 
-// Transform |aVector|, which is anchored at |aAnchor|, by the given transform
-// matrix, yielding a point in |TargetUnits|.
-// The anchor is necessary because with 3D tranforms, the location of the
-// vector can affect the result of the transform.
-template <typename TargetUnits, typename SourceUnits>
-static gfx::PointTyped<TargetUnits> TransformVector(const gfx::Matrix4x4& aTransform,
-                                                    const gfx::PointTyped<SourceUnits>& aVector,
-                                                    const gfx::PointTyped<SourceUnits>& aAnchor) {
-  gfx::PointTyped<TargetUnits> transformedStart = TransformTo<TargetUnits>(aTransform, aAnchor);
-  gfx::PointTyped<TargetUnits> transformedEnd = TransformTo<TargetUnits>(aTransform, aAnchor + aVector);
-  return transformedEnd - transformedStart;
-}
 
 }
 
 #endif
--- a/layout/base/Units.h
+++ b/layout/base/Units.h
@@ -22,35 +22,22 @@ template <typename T>
 struct IsPixel : FalseType {};
 
 // See struct decleration for a description of each unit type
 struct CSSPixel;
 struct LayoutDevicePixel;
 struct LayerPixel;
 struct RenderTargetPixel;
 struct ScreenPixel;
-// The layer coordinates of the parent frame.
-// This can be arrived at in three ways:
-//   - Start with the CSS coordinates of the parent frame, multiply by the
-//     device scale and the cumulative resolution of the parent frame.
-//   - Start with the CSS coordinates of current frame, multiply by the device
-//     scale, the cumulative resolution of the current frame, and the scales
-//     from the CSS and async transforms of the current frame.
-//   - Start with global screen coordinates and unapply all CSS and async
-//     transforms from the root down to and including the parent.
-// It's helpful to look at https://wiki.mozilla.org/Platform/GFX/APZ#Coordinate_systems
-// to get a picture of how the various coordinate systems relate to each other.
-struct ParentLayerPixel {};
 
 template<> struct IsPixel<CSSPixel>          : TrueType {};
 template<> struct IsPixel<LayoutDevicePixel> : TrueType {};
 template<> struct IsPixel<LayerPixel>        : TrueType {};
 template<> struct IsPixel<RenderTargetPixel> : TrueType {};
 template<> struct IsPixel<ScreenPixel>       : TrueType {};
-template<> struct IsPixel<ParentLayerPixel>  : TrueType {};
 
 typedef gfx::CoordTyped<CSSPixel> CSSCoord;
 typedef gfx::IntCoordTyped<CSSPixel> CSSIntCoord;
 typedef gfx::PointTyped<CSSPixel> CSSPoint;
 typedef gfx::IntPointTyped<CSSPixel> CSSIntPoint;
 typedef gfx::SizeTyped<CSSPixel> CSSSize;
 typedef gfx::IntSizeTyped<CSSPixel> CSSIntSize;
 typedef gfx::RectTyped<CSSPixel> CSSRect;
@@ -75,68 +62,50 @@ typedef gfx::PointTyped<LayerPixel> Laye
 typedef gfx::IntPointTyped<LayerPixel> LayerIntPoint;
 typedef gfx::SizeTyped<LayerPixel> LayerSize;
 typedef gfx::IntSizeTyped<LayerPixel> LayerIntSize;
 typedef gfx::RectTyped<LayerPixel> LayerRect;
 typedef gfx::IntRectTyped<LayerPixel> LayerIntRect;
 typedef gfx::MarginTyped<LayerPixel> LayerMargin;
 typedef gfx::IntMarginTyped<LayerPixel> LayerIntMargin;
 
+typedef gfx::CoordTyped<ScreenPixel> ScreenCoord;
+typedef gfx::IntCoordTyped<ScreenPixel> ScreenIntCoord;
 typedef gfx::PointTyped<RenderTargetPixel> RenderTargetPoint;
 typedef gfx::IntPointTyped<RenderTargetPixel> RenderTargetIntPoint;
 typedef gfx::SizeTyped<RenderTargetPixel> RenderTargetSize;
 typedef gfx::IntSizeTyped<RenderTargetPixel> RenderTargetIntSize;
 typedef gfx::RectTyped<RenderTargetPixel> RenderTargetRect;
 typedef gfx::IntRectTyped<RenderTargetPixel> RenderTargetIntRect;
 typedef gfx::MarginTyped<RenderTargetPixel> RenderTargetMargin;
 typedef gfx::IntMarginTyped<RenderTargetPixel> RenderTargetIntMargin;
 
-typedef gfx::CoordTyped<ScreenPixel> ScreenCoord;
-typedef gfx::IntCoordTyped<ScreenPixel> ScreenIntCoord;
 typedef gfx::PointTyped<ScreenPixel> ScreenPoint;
 typedef gfx::IntPointTyped<ScreenPixel> ScreenIntPoint;
 typedef gfx::SizeTyped<ScreenPixel> ScreenSize;
 typedef gfx::IntSizeTyped<ScreenPixel> ScreenIntSize;
 typedef gfx::RectTyped<ScreenPixel> ScreenRect;
 typedef gfx::IntRectTyped<ScreenPixel> ScreenIntRect;
 typedef gfx::MarginTyped<ScreenPixel> ScreenMargin;
 typedef gfx::IntMarginTyped<ScreenPixel> ScreenIntMargin;
 
-typedef gfx::CoordTyped<ParentLayerPixel> ParentLayerCoord;
-typedef gfx::IntCoordTyped<ParentLayerPixel> ParentLayerIntCoord;
-typedef gfx::PointTyped<ParentLayerPixel> ParentLayerPoint;
-typedef gfx::IntPointTyped<ParentLayerPixel> ParentLayerIntPoint;
-typedef gfx::SizeTyped<ParentLayerPixel> ParentLayerSize;
-typedef gfx::IntSizeTyped<ParentLayerPixel> ParentLayerIntSize;
-typedef gfx::RectTyped<ParentLayerPixel> ParentLayerRect;
-typedef gfx::IntRectTyped<ParentLayerPixel> ParentLayerIntRect;
-typedef gfx::MarginTyped<ParentLayerPixel> ParentLayerMargin;
-typedef gfx::IntMarginTyped<ParentLayerPixel> ParentLayerIntMargin;
-
 typedef gfx::ScaleFactor<CSSPixel, LayoutDevicePixel> CSSToLayoutDeviceScale;
 typedef gfx::ScaleFactor<CSSPixel, LayerPixel> CSSToLayerScale;
 typedef gfx::ScaleFactor<CSSPixel, ScreenPixel> CSSToScreenScale;
-typedef gfx::ScaleFactor<CSSPixel, ParentLayerPixel> CSSToParentLayerScale;
 typedef gfx::ScaleFactor<LayoutDevicePixel, CSSPixel> LayoutDeviceToCSSScale;
 typedef gfx::ScaleFactor<LayoutDevicePixel, LayerPixel> LayoutDeviceToLayerScale;
 typedef gfx::ScaleFactor<LayoutDevicePixel, ScreenPixel> LayoutDeviceToScreenScale;
-typedef gfx::ScaleFactor<LayoutDevicePixel, ParentLayerPixel> LayoutDeviceToParentLayerScale;
 typedef gfx::ScaleFactor<LayerPixel, CSSPixel> LayerToCSSScale;
 typedef gfx::ScaleFactor<LayerPixel, LayoutDevicePixel> LayerToLayoutDeviceScale;
 typedef gfx::ScaleFactor<LayerPixel, RenderTargetPixel> LayerToRenderTargetScale;
 typedef gfx::ScaleFactor<LayerPixel, ScreenPixel> LayerToScreenScale;
-typedef gfx::ScaleFactor<LayerPixel, ParentLayerPixel> LayerToParentLayerScale;
 typedef gfx::ScaleFactor<RenderTargetPixel, ScreenPixel> RenderTargetToScreenScale;
 typedef gfx::ScaleFactor<ScreenPixel, CSSPixel> ScreenToCSSScale;
 typedef gfx::ScaleFactor<ScreenPixel, LayoutDevicePixel> ScreenToLayoutDeviceScale;
 typedef gfx::ScaleFactor<ScreenPixel, LayerPixel> ScreenToLayerScale;
-typedef gfx::ScaleFactor<ScreenPixel, ParentLayerPixel> ScreenToParentLayerScale;
-typedef gfx::ScaleFactor<ParentLayerPixel, LayerPixel> ParentLayerToLayerScale;
-typedef gfx::ScaleFactor<ParentLayerPixel, ScreenPixel> ParentLayerToScreenScale;
-typedef gfx::ScaleFactor<ParentLayerPixel, ParentLayerPixel> ParentLayerToParentLayerScale;
 
 /*
  * The pixels that content authors use to specify sizes in.
  */
 struct CSSPixel {
 
   // Conversions from app units
 
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -719,19 +719,20 @@ nsDisplayScrollLayer::ComputeFrameMetric
 
   metrics.SetScrollId(scrollId);
   metrics.SetIsRoot(aIsRoot);
   metrics.SetScrollParentId(aScrollParentId);
 
   // Only the root scrollable frame for a given presShell should pick up
   // the presShell's resolution. All the other frames are 1.0.
   if (aScrollFrame == presShell->GetRootScrollFrame()) {
-    metrics.mPresShellResolution = presShell->GetXResolution();
+    metrics.mPresShellResolution = ParentLayerToLayerScale(presShell->GetXResolution(),
+                                                  presShell->GetYResolution());
   } else {
-    metrics.mPresShellResolution = 1.0f;
+    metrics.mPresShellResolution = ParentLayerToLayerScale(1.0f);
   }
   // The cumulative resolution is the resolution at which the scroll frame's
   // content is actually rendered. It includes the pres shell resolutions of
   // all the pres shells from here up to the root, as well as any css-driven
   // resolution. We don't need to compute it as it's already stored in the
   // container parameters.
   metrics.mCumulativeResolution = LayoutDeviceToLayerScale(aContainerParameters.mXScale,
                                                            aContainerParameters.mYScale);
@@ -741,42 +742,46 @@ nsDisplayScrollLayer::ComputeFrameMetric
     * nsLayoutUtils::GetTransformToAncestorScale(aScrollFrame ? aScrollFrame : aForFrame).width);
   metrics.SetExtraResolution(metrics.mCumulativeResolution / resolutionToScreen);
 
   metrics.mDevPixelsPerCSSPixel = CSSToLayoutDeviceScale(
     (float)nsPresContext::AppUnitsPerCSSPixel() / auPerDevPixel);
 
   // Initially, AsyncPanZoomController should render the content to the screen
   // at the painted resolution.
-  const LayerToParentLayerScale layerToParentLayerScale(1.0f);
+  const LayerToScreenScale layerToScreenScale(1.0f);
   metrics.SetZoom(metrics.mCumulativeResolution * metrics.mDevPixelsPerCSSPixel
-                  * layerToParentLayerScale);
+                  * layerToScreenScale);
 
   if (presShell) {
     nsIDocument* document = nullptr;
     document = presShell->GetDocument();
     if (document) {
       nsCOMPtr<nsPIDOMWindow> innerWin(document->GetInnerWindow());
       if (innerWin) {
         metrics.SetMayHaveTouchListeners(innerWin->HasTouchEventListeners());
       }
     }
     metrics.SetMayHaveTouchCaret(presShell->MayHaveTouchCaret());
   }
 
+  LayoutDeviceToParentLayerScale layoutToParentLayerScale =
+    // The ScreenToParentLayerScale should be mTransformScale which is not calculated yet,
+    // but we don't yet handle CSS transforms, so we assume it's 1 here.
+    metrics.mCumulativeResolution * LayerToScreenScale(1.0) * ScreenToParentLayerScale(1.0);
+
   // Calculate the composition bounds as the size of the scroll frame and
   // its origin relative to the reference frame.
   // If aScrollFrame is null, we are in a document without a root scroll frame,
   // so it's a xul document. In this case, use the size of the viewport frame.
   nsIFrame* frameForCompositionBoundsCalculation = aScrollFrame ? aScrollFrame : aForFrame;
   nsRect compositionBounds(frameForCompositionBoundsCalculation->GetOffsetToCrossDoc(aReferenceFrame),
                            frameForCompositionBoundsCalculation->GetSize());
   ParentLayerRect frameBounds = LayoutDeviceRect::FromAppUnits(compositionBounds, auPerDevPixel)
-                              * metrics.mCumulativeResolution
-                              * layerToParentLayerScale;
+                                 * layoutToParentLayerScale;
   metrics.mCompositionBounds = frameBounds;
 
   // For the root scroll frame of the root content document, the above calculation
   // will yield the size of the viewport frame as the composition bounds, which
   // doesn't actually correspond to what is visible when
   // nsIDOMWindowUtils::setCSSViewport has been called to modify the visible area of
   // the prescontext that the viewport frame is reflowed into. In that case if our
   // document has a widget then the widget's bounds will correspond to what is
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2779,49 +2779,51 @@ CalculateFrameMetricsForDisplayPort(nsIF
   // Calculate the metrics necessary for calculating the displayport.
   // This code has a lot in common with the code in ComputeFrameMetrics();
   // we may want to refactor this at some point.
   FrameMetrics metrics;
   nsPresContext* presContext = aScrollFrame->PresContext();
   nsIPresShell* presShell = presContext->PresShell();
   CSSToLayoutDeviceScale deviceScale(float(nsPresContext::AppUnitsPerCSSPixel())
                                      / presContext->AppUnitsPerDevPixel());
-  float resolution = 1.0f;
+  ParentLayerToLayerScale resolution;
   if (aScrollFrame == presShell->GetRootScrollFrame()) {
     // Only the root scrollable frame for a given presShell should pick up
     // the presShell's resolution. All the other frames are 1.0.
-    resolution = presShell->GetXResolution();
+    resolution = ParentLayerToLayerScale(presShell->GetXResolution(),
+                                         presShell->GetYResolution());
   }
   // Note: unlike in ComputeFrameMetrics(), we don't know the full cumulative
   // resolution including FrameMetrics::mExtraResolution, because layout hasn't
   // chosen a resolution to paint at yet. However, the display port calculation
   // divides out mExtraResolution anyways, so we get the correct result by
   // setting the mCumulativeResolution to everything except the extra resolution
   // and leaving mExtraResolution at 1.
   LayoutDeviceToLayerScale cumulativeResolution(
       presShell->GetCumulativeResolution().width
     * nsLayoutUtils::GetTransformToAncestorScale(aScrollFrame).width);
 
-  LayerToParentLayerScale layerToParentLayerScale(1.0f);
   metrics.mDevPixelsPerCSSPixel = deviceScale;
   metrics.mPresShellResolution = resolution;
   metrics.mCumulativeResolution = cumulativeResolution;
-  metrics.SetZoom(deviceScale * cumulativeResolution * layerToParentLayerScale);
+  metrics.SetZoom(deviceScale * cumulativeResolution * LayerToScreenScale(1));
 
   // Only the size of the composition bounds is relevant to the
   // displayport calculation, not its origin.
   nsSize compositionSize = nsLayoutUtils::CalculateCompositionSizeForFrame(aScrollFrame);
   LayoutDeviceToParentLayerScale compBoundsScale(1.0f);
   if (aScrollFrame == presShell->GetRootScrollFrame() && presContext->IsRootContentDocument()) {
     if (presContext->GetParentPresContext()) {
       gfxSize res = presContext->GetParentPresContext()->PresShell()->GetCumulativeResolution();
       compBoundsScale = LayoutDeviceToParentLayerScale(res.width, res.height);
     }
   } else {
-    compBoundsScale = cumulativeResolution * layerToParentLayerScale;
+    compBoundsScale = cumulativeResolution
+                    * LayerToScreenScale(1.0f)
+                    * ScreenToParentLayerScale(1.0f);
   }
   metrics.mCompositionBounds
       = LayoutDeviceRect::FromAppUnits(nsRect(nsPoint(0, 0), compositionSize),
                                        presContext->AppUnitsPerDevPixel())
       * compBoundsScale;
 
   metrics.SetRootCompositionSize(
       nsLayoutUtils::CalculateRootCompositionSize(aScrollFrame, false, metrics));
@@ -2862,17 +2864,17 @@ nsLayoutUtils::GetOrMaybeCreateDisplayPo
   if (aBuilder.IsPaintingToWindow() && WantSubAPZC() &&
       !aBuilder.HaveScrollableDisplayPort() &&
       scrollableFrame->WantAsyncScroll()) {
 
     // If we don't already have a displayport, calculate and set one.
     if (!haveDisplayPort) {
       FrameMetrics metrics = CalculateFrameMetricsForDisplayPort(aScrollFrame, scrollableFrame);
       ScreenMargin displayportMargins = APZCTreeManager::CalculatePendingDisplayPort(
-          metrics, ParentLayerPoint(0.0f, 0.0f), 0.0);
+          metrics, ScreenPoint(0.0f, 0.0f), 0.0);
       nsIPresShell* presShell = aScrollFrame->PresContext()->GetPresShell();
       gfx::IntSize alignment = gfxPlatform::GetPlatform()->UseTiling()
           ? gfx::IntSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight()) :
             gfx::IntSize(0, 0);
       nsLayoutUtils::SetDisplayPortMargins(
           content, presShell, displayportMargins, alignment.width,
           alignment.height, 0, nsLayoutUtils::RepaintMode::DoNotRepaint);
       haveDisplayPort = GetDisplayPort(content, aOutDisplayport);
--- a/widget/InputData.h
+++ b/widget/InputData.h
@@ -103,66 +103,43 @@ protected:
  * event. It is only a container/struct that should have any number of instances
  * within a MultiTouchInput.
  *
  * fixme/bug 775746: Make dom::Touch inherit from this class.
  */
 class SingleTouchData
 {
 public:
-  // Construct a SingleTouchData from a Screen point.
-  // mLocalScreenPoint remains (0,0) unless it's set later.
   SingleTouchData(int32_t aIdentifier,
                   ScreenIntPoint aScreenPoint,
                   ScreenSize aRadius,
                   float aRotationAngle,
                   float aForce)
     : mIdentifier(aIdentifier),
       mScreenPoint(aScreenPoint),
       mRadius(aRadius),
       mRotationAngle(aRotationAngle),
       mForce(aForce)
   {
   }
 
-  // Construct a SingleTouchData from a ParentLayer point.
-  // mScreenPoint remains (0,0) unless it's set later.
-  // Note: if APZ starts using the radius for anything, we should add a local
-  // version of that too, and have this constructor take it as a ParentLayerSize.
-  SingleTouchData(int32_t aIdentifier,
-                  ParentLayerPoint aLocalScreenPoint,
-                  ScreenSize aRadius,
-                  float aRotationAngle,
-                  float aForce)
-    : mIdentifier(aIdentifier),
-      mLocalScreenPoint(aLocalScreenPoint),
-      mRadius(aRadius),
-      mRotationAngle(aRotationAngle),
-      mForce(aForce)
-  {
-  }
-
   SingleTouchData()
   {
   }
 
   already_AddRefed<dom::Touch> ToNewDOMTouch() const;
 
   // A unique number assigned to each SingleTouchData within a MultiTouchInput so
   // that they can be easily distinguished when handling a touch start/move/end.
   int32_t mIdentifier;
 
   // Point on the screen that the touch hit, in device pixels. They are
   // coordinates on the screen.
   ScreenIntPoint mScreenPoint;
 
-  // |mScreenPoint| transformed to the local coordinates of the APZC targeted
-  // by the hit. This is set and used by APZ.
-  ParentLayerPoint mLocalScreenPoint;
-
   // Radius that the touch covers, i.e. if you're using your thumb it will
   // probably be larger than using your pinky, even with the same force.
   // Radius can be different along x and y. For example, if you press down with
   // your entire finger vertically, the y radius will be much larger than the x
   // radius.
   ScreenSize mRadius;
 
   float mRotationAngle;
@@ -292,21 +269,16 @@ public:
   {
   }
 
   PanGestureType mType;
   ScreenPoint mPanStartPoint;
 
   // Only non-zero if mType is PANGESTURE_PAN or PANGESTURE_MOMENTUMPAN.
   ScreenPoint mPanDisplacement;
-
-  // Versions of |mPanStartPoint| and |mPanDisplacement| in the local
-  // coordinates of the APZC receiving the pan. These are set and used by APZ.
-  ParentLayerPoint mLocalPanStartPoint;
-  ParentLayerPoint mLocalPanDisplacement;
 };
 
 /**
  * Encapsulation class for pinch events. In general, these will be generated by
  * a gesture listener by looking at SingleTouchData/MultiTouchInput instances and
  * determining whether or not the user was trying to do a gesture.
  */
 class PinchGestureInput : public InputData
@@ -314,63 +286,42 @@ class PinchGestureInput : public InputDa
 public:
   enum PinchGestureType
   {
     PINCHGESTURE_START,
     PINCHGESTURE_SCALE,
     PINCHGESTURE_END
   };
 
-  // Construct a tap gesture from a Screen point.
-  // mLocalFocusPoint remains (0,0) unless it's set later.
   PinchGestureInput(PinchGestureType aType,
                     uint32_t aTime,
                     TimeStamp aTimeStamp,
                     const ScreenPoint& aFocusPoint,
                     float aCurrentSpan,
                     float aPreviousSpan,
                     Modifiers aModifiers)
     : InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
       mType(aType),
       mFocusPoint(aFocusPoint),
       mCurrentSpan(aCurrentSpan),
       mPreviousSpan(aPreviousSpan)
   {
-  }
 
-  // Construct a tap gesture from a ParentLayer point.
-  // mFocusPoint remains (0,0) unless it's set later.
-  PinchGestureInput(PinchGestureType aType,
-                    uint32_t aTime,
-                    TimeStamp aTimeStamp,
-                    const ParentLayerPoint& aLocalFocusPoint,
-                    float aCurrentSpan,
-                    float aPreviousSpan,
-                    Modifiers aModifiers)
-    : InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
-      mType(aType),
-      mLocalFocusPoint(aLocalFocusPoint),
-      mCurrentSpan(aCurrentSpan),
-      mPreviousSpan(aPreviousSpan)
-  {
+
   }
 
   PinchGestureType mType;
 
   // Center point of the pinch gesture. That is, if there are two fingers on the
   // screen, it is their midpoint. In the case of more than two fingers, the
   // point is implementation-specific, but can for example be the midpoint
   // between the very first and very last touch. This is in device pixels and
   // are the coordinates on the screen of this midpoint.
   ScreenPoint mFocusPoint;
 
-  // |mFocusPoint| transformed to the local coordinates of the APZC targeted
-  // by the hit. This is set and used by APZ.
-  ParentLayerPoint mLocalFocusPoint;
-
   // The distance in device pixels (though as a float for increased precision
   // and because it is the distance along both the x and y axis) between the
   // touches responsible for the pinch gesture.
   float mCurrentSpan;
 
   // The previous |mCurrentSpan| in the PinchGestureInput preceding this one.
   // This is only really relevant during a PINCHGESTURE_SCALE because when it is
   // of this type then there must have been a history of spans.
@@ -390,47 +341,28 @@ public:
     TAPGESTURE_LONG,
     TAPGESTURE_LONG_UP,
     TAPGESTURE_UP,
     TAPGESTURE_CONFIRMED,
     TAPGESTURE_DOUBLE,
     TAPGESTURE_CANCEL
   };
 
-  // Construct a tap gesture from a Screen point.
-  // mLocalPoint remains (0,0) unless it's set later.
   TapGestureInput(TapGestureType aType,
                   uint32_t aTime,
                   TimeStamp aTimeStamp,
                   const ScreenIntPoint& aPoint,
                   Modifiers aModifiers)
     : InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
       mType(aType),
       mPoint(aPoint)
   {
-  }
 
-  // Construct a tap gesture from a ParentLayer point.
-  // mPoint remains (0,0) unless it's set later.
-  TapGestureInput(TapGestureType aType,
-                  uint32_t aTime,
-                  TimeStamp aTimeStamp,
-                  const ParentLayerPoint& aLocalPoint,
-                  Modifiers aModifiers)
-    : InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
-      mType(aType),
-      mLocalPoint(aLocalPoint)
-  {
+
   }
 
   TapGestureType mType;
-
-  // The location of the tap in screen pixels.
   ScreenIntPoint mPoint;
-
-  // The location of the tap in the local coordinates of the APZC receiving it.
-  // This is set and used by APZ.
-  ParentLayerPoint mLocalPoint;
 };
 
 }
 
 #endif // InputData_h__
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -1488,17 +1488,17 @@ AndroidBridge::SetPageRect(const CSSRect
     if (!client)
         return;
 
     client->SetPageRect(aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
 }
 
 void
 AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
-                                bool aLayersUpdated, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aScale,
+                                bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale,
                                 LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
 {
     mozilla::widget::android::GeckoLayerClient *client = mLayerClient;
     if (!client) {
         ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
         return;
     }
 
@@ -1507,28 +1507,28 @@ AndroidBridge::SyncViewportInfo(const La
                                 aDisplayResolution.scale, aLayersUpdated);
     NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
 
     if (!viewTransformJObj) {
         return;
     }
 
     ViewTransform* viewTransform = ViewTransform::Wrap(viewTransformJObj);
-    aScrollOffset = ParentLayerPoint(viewTransform->getx(), viewTransform->gety());
+    aScrollOffset = ScreenPoint(viewTransform->getx(), viewTransform->gety());
     aScale.scale = viewTransform->getscale();
     aFixedLayerMargins.top = viewTransform->getfixedLayerMarginTop();
     aFixedLayerMargins.right = viewTransform->getfixedLayerMarginRight();
     aFixedLayerMargins.bottom = viewTransform->getfixedLayerMarginBottom();
     aFixedLayerMargins.left = viewTransform->getfixedLayerMarginLeft();
     aOffset.x = viewTransform->getoffsetX();
     aOffset.y = viewTransform->getoffsetY();
     delete viewTransform;
 }
 
-void AndroidBridge::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
+void AndroidBridge::SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
                                      bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
                                      bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
 {
     mozilla::widget::android::GeckoLayerClient *client = mLayerClient;
     if (!client) {
         ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
         return;
     }
@@ -1951,17 +1951,17 @@ AndroidBridge::IsContentDocumentDisplaye
     if (!mLayerClient)
         return false;
 
     return mLayerClient->IsContentDocumentDisplayed();
 }
 
 bool
 AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution,
-                                         bool aDrawingCritical, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aZoom)
+                                         bool aDrawingCritical, ScreenPoint& aScrollOffset, CSSToScreenScale& aZoom)
 {
     mozilla::widget::android::GeckoLayerClient *client = mLayerClient;
     if (!client) {
         ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
         return false;
     }
 
     jobject progressiveUpdateDataJObj = client->ProgressiveUpdateCallback(aHasPendingNewThebesContent,
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -203,17 +203,17 @@ public:
     bool GetFrameNameJavaProfiling(uint32_t aThreadId, uint32_t aSampleId, uint32_t aFrameId, nsCString & aResult);
 
     nsresult CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, jobject buffer, bool &shouldStore);
     void GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort);
     void ContentDocumentChanged();
     bool IsContentDocumentDisplayed();
 
     bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical,
-                                   mozilla::ParentLayerPoint& aScrollOffset, mozilla::CSSToParentLayerScale& aZoom);
+                                   mozilla::ScreenPoint& aScrollOffset, mozilla::CSSToScreenScale& aZoom);
 
     void SetLayerClient(JNIEnv* env, jobject jobj);
     mozilla::widget::android::GeckoLayerClient* GetLayerClient() { return mLayerClient; }
 
     bool GetHandlersForURL(const nsAString& aURL,
                            nsIMutableArray* handlersArray = nullptr,
                            nsIHandlerApp **aDefaultApp = nullptr,
                            const nsAString& aAction = EmptyString());
@@ -301,19 +301,19 @@ public:
     void GetNextMessageInList(int32_t aListId, nsIMobileMessageCallback* aRequest);
     already_AddRefed<nsIMobileMessageCallback> DequeueSmsRequest(uint32_t aRequestId);
 
     void GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo);
 
     void SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect);
     void SetPageRect(const CSSRect& aCssPageRect);
     void SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
-                          bool aLayersUpdated, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aScale,
+                          bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale,
                           LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset);
-    void SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
+    void SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
                           bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
                           bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset);
 
     void AddPluginView(jobject view, const LayoutDeviceRect& rect, bool isFullScreen);
 
     // These methods don't use a ScreenOrientation because it's an
     // enum and that would require including the header which requires
     // include IPC headers which requires including basictypes.h which
--- a/widget/windows/winrt/APZController.cpp
+++ b/widget/windows/winrt/APZController.cpp
@@ -248,18 +248,18 @@ APZController::PostDelayedTask(Task* aTa
 bool
 APZController::GetRootZoomConstraints(ZoomConstraints* aOutConstraints)
 {
   if (aOutConstraints) {
     // Until we support the meta-viewport tag properly allow zooming
     // from 1/4 to 4x by default.
     aOutConstraints->mAllowZoom = true;
     aOutConstraints->mAllowDoubleTapZoom = false;
-    aOutConstraints->mMinZoom = CSSToParentLayerScale(0.25f);
-    aOutConstraints->mMaxZoom = CSSToParentLayerScale(4.0f);
+    aOutConstraints->mMinZoom = CSSToScreenScale(0.25f);
+    aOutConstraints->mMaxZoom = CSSToScreenScale(4.0f);
     return true;
   }
   return false;
 }
 
 // apzc notifications
 
 class TransformedStartEvent : public nsRunnable