Bug 879004 - Convert mDisplayport and mCriticalDisplayport in FrameMetrics to CSSRects. r=BenWa
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 10 Jun 2013 09:05:42 -0400
changeset 134510 6b0d5080b1d605dbcdecaa641e64906f4a59494e
parent 134509 0cb9ae85c68705aa7c9ce36a8d62b351fb74bda7
child 134511 2dcce926842be02d4da747a5980dd056aaa47757
push id24803
push userryanvm@gmail.com
push dateMon, 10 Jun 2013 19:43:46 +0000
treeherdermozilla-central@9115d8b717e1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBenWa
bugs879004
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 879004 - Convert mDisplayport and mCriticalDisplayport in FrameMetrics to CSSRects. r=BenWa
gfx/2d/BaseRect.h
gfx/layers/FrameMetrics.h
gfx/layers/LayersLogging.cpp
gfx/layers/LayersLogging.h
gfx/layers/client/ClientLayerManager.cpp
gfx/layers/client/ClientTiledThebesLayer.cpp
gfx/layers/composite/AsyncCompositionManager.cpp
gfx/layers/composite/AsyncCompositionManager.h
gfx/layers/composite/LayerManagerComposite.cpp
gfx/layers/ipc/AsyncPanZoomController.cpp
gfx/layers/ipc/AsyncPanZoomController.h
layout/base/Units.h
layout/base/nsDisplayList.cpp
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/AndroidJavaWrappers.cpp
widget/android/AndroidJavaWrappers.h
--- a/gfx/2d/BaseRect.h
+++ b/gfx/2d/BaseRect.h
@@ -338,16 +338,28 @@ struct BaseRect {
 
     x = x0;
     y = y0;
 
     width = x1 - x0;
     height = y1 - y0;
   }
 
+  // Scale 'this' by aScale without doing any rounding.
+  void Scale(T aScale) { Scale(aScale, aScale); }
+  // Scale 'this' by aXScale and aYScale, without doing any rounding.
+  void Scale(T aXScale, T aYScale)
+  {
+    T right = XMost() * aXScale;
+    T bottom = YMost() * aYScale;
+    x = x * aXScale;
+    y = y * aYScale;
+    width = right - x;
+    height = bottom - y;
+  }
   // Scale 'this' by aScale, converting coordinates to integers so that the result is
   // the smallest integer-coordinate rectangle containing the unrounded result.
   // Note: this can turn an empty rectangle into a non-empty rectangle
   void ScaleRoundOut(double aScale) { ScaleRoundOut(aScale, aScale); }
   // Scale 'this' by aXScale and aYScale, converting coordinates to integers so
   // that the result is the smallest integer-coordinate rectangle containing the
   // unrounded result.
   // Note: this can turn an empty rectangle into a non-empty rectangle
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -150,25 +150,25 @@ public:
   // May be larger or smaller than |mScrollableRect|.
   //
   // To pre-render a margin of 100 CSS pixels around the window,
   // { x = -100, y = - 100,
   //   width = window.innerWidth + 100, height = window.innerHeight + 100 }
   //
   // This is only valid on the root layer. Nested iframes do not have a
   // displayport set on them. See bug 775452.
-  gfx::Rect mDisplayPort;
+  CSSRect mDisplayPort;
 
   // If non-empty, the area of a frame's contents that is considered critical
   // to paint. Area outside of this area (i.e. area inside mDisplayPort, but
   // outside of mCriticalDisplayPort) is considered low-priority, and may be
   // painted with lower precision, or not painted at all.
   //
   // The same restrictions for mDisplayPort apply here.
-  gfx::Rect mCriticalDisplayPort;
+  CSSRect mCriticalDisplayPort;
 
   // The CSS viewport, which is the dimensions we're using to constrain the
   // <html> element of this frame, relative to the top-left of the layer. Note
   // that its offset is structured in such a way that it doesn't depend on the
   // method layout uses to scroll content.
   //
   // This is mainly useful on the root layer, however nested iframes can have
   // their own viewport, which will just be the size of the window of the
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -111,18 +111,19 @@ AppendToString(nsACString& s, const nsIn
 {
   s += pfx;
   s += nsPrintfCString(
     "(x=%d, y=%d, w=%d, h=%d)",
     r.x, r.y, r.width, r.height);
   return s += sfx;
 }
 
+template<class T>
 nsACString&
-AppendToString(nsACString& s, const Rect& r,
+AppendToString(nsACString& s, const RectTyped<T>& r,
                const char* pfx, const char* sfx)
 {
   s += pfx;
   s.AppendPrintf(
     "(x=%f, y=%f, w=%f, h=%f)",
     r.x, r.y, r.width, r.height);
   return s += sfx;
 }
--- a/gfx/layers/LayersLogging.h
+++ b/gfx/layers/LayersLogging.h
@@ -48,18 +48,19 @@ template<class T>
 nsACString&
 AppendToString(nsACString& s, const mozilla::gfx::PointTyped<T>& p,
                const char* pfx="", const char* sfx="");
 
 nsACString&
 AppendToString(nsACString& s, const nsIntRect& r,
                const char* pfx="", const char* sfx="");
 
+template<class T>
 nsACString&
-AppendToString(nsACString& s, const mozilla::gfx::Rect& r,
+AppendToString(nsACString& s, const mozilla::gfx::RectTyped<T>& r,
                const char* pfx="", const char* sfx="");
 
 nsACString&
 AppendToString(nsACString& s, const nsIntRegion& r,
                const char* pfx="", const char* sfx="");
 
 nsACString&
 AppendToString(nsACString& s, const nsIntSize& sz,
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -392,23 +392,21 @@ ClientLayerManager::ProgressiveUpdateCal
   if (primaryScrollable) {
     const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
 
     // This is derived from the code in
     // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree.
     const gfx3DMatrix& rootTransform = GetRoot()->GetTransform();
     float devPixelRatioX = 1 / rootTransform.GetXScale();
     float devPixelRatioY = 1 / rootTransform.GetYScale();
-    const gfx::Rect& metricsDisplayPort =
+    const CSSRect& metricsDisplayPort =
       (aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ?
         metrics.mCriticalDisplayPort : metrics.mDisplayPort;
-    gfx::Rect displayPort((metricsDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX,
-                          (metricsDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY,
-                          metricsDisplayPort.width * devPixelRatioX,
-                          metricsDisplayPort.height * devPixelRatioY);
+    LayerRect displayPort = LayerRect::FromCSSRect(metricsDisplayPort + metrics.mScrollOffset,
+                                                   devPixelRatioX, devPixelRatioY);
 
     return AndroidBridge::Bridge()->ProgressiveUpdateCallback(
       aHasPendingNewThebesContent, displayPort, devPixelRatioX, aDrawingCritical,
       aViewport, aScaleX, aScaleY);
   }
 #endif
 
   return false;
--- a/gfx/layers/client/ClientTiledThebesLayer.cpp
+++ b/gfx/layers/client/ClientTiledThebesLayer.cpp
@@ -52,17 +52,18 @@ ClientTiledThebesLayer::BeginPaint()
     if (parent->UseIntermediateSurface()) {
       mPaintData.mTransformScreenToLayer.PreMultiply(parent->GetEffectiveTransform());
     }
   }
   mPaintData.mTransformScreenToLayer.Invert();
 
   // Compute the critical display port in layer space.
   mPaintData.mLayerCriticalDisplayPort.SetEmpty();
-  const gfx::Rect& criticalDisplayPort = GetParent()->GetFrameMetrics().mCriticalDisplayPort;
+  const gfx::Rect& criticalDisplayPort =
+    GetParent()->GetFrameMetrics().mCriticalDisplayPort.ToUnknownRect();
   if (!criticalDisplayPort.IsEmpty()) {
     gfxRect transformedCriticalDisplayPort =
       mPaintData.mTransformScreenToLayer.TransformBounds(
         gfxRect(criticalDisplayPort.x, criticalDisplayPort.y,
                 criticalDisplayPort.width, criticalDisplayPort.height));
     transformedCriticalDisplayPort.RoundOut();
     mPaintData.mLayerCriticalDisplayPort = nsIntRect(transformedCriticalDisplayPort.x,
                                              transformedCriticalDisplayPort.y,
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -346,22 +346,22 @@ AsyncCompositionManager::ApplyAsyncConte
     *aWantNextFrame |=
       controller->SampleContentTransformForFrame(aCurrentFrame,
                                                  container,
                                                  &treeTransform,
                                                  scrollOffset);
 
     const gfx3DMatrix& rootTransform = mLayerManager->GetRoot()->GetTransform();
     const FrameMetrics& metrics = container->GetFrameMetrics();
-    gfx::Rect displayPortLayersPixels(metrics.mCriticalDisplayPort.IsEmpty() ?
-                                      metrics.mDisplayPort : metrics.mCriticalDisplayPort);
+    CSSRect displayPort(metrics.mCriticalDisplayPort.IsEmpty() ?
+                        metrics.mDisplayPort : metrics.mCriticalDisplayPort);
     gfx::Margin fixedLayerMargins(0, 0, 0, 0);
     ScreenPoint offset(0, 0);
     SyncFrameMetrics(scrollOffset, treeTransform.mScale.width, metrics.mScrollableRect,
-                     mLayersUpdated, displayPortLayersPixels, 1 / rootTransform.GetXScale(),
+                     mLayersUpdated, displayPort, 1 / rootTransform.GetXScale(),
                      mIsFirstPaint, fixedLayerMargins, offset);
 
     mIsFirstPaint = false;
     mLayersUpdated = false;
 
     // Apply the render offset
     mLayerManager->GetCompositor()->SetScreenRenderOffset(offset);
 
@@ -420,24 +420,22 @@ AsyncCompositionManager::TransformScroll
   } else if (!metrics.mContentRect.IsEqualEdges(mContentRect)) {
     mContentRect = metrics.mContentRect;
     SetPageRect(metrics.mScrollableRect);
   }
 
   // We synchronise the viewport information with Java after sending the above
   // notifications, so that Java can take these into account in its response.
   // Calculate the absolute display port to send to Java
-  LayerIntRect displayPort = LayerIntRect::FromCSSRectRounded(
-    CSSRect::FromUnknownRect(metrics.mCriticalDisplayPort.IsEmpty()
-                             ? metrics.mDisplayPort
-                             : metrics.mCriticalDisplayPort),
-    layerPixelRatioX, layerPixelRatioY);
-
-  displayPort.x += scrollOffsetLayerPixels.x;
-  displayPort.y += scrollOffsetLayerPixels.y;
+  LayerIntRect displayPort =
+    LayerIntRect::FromCSSRectRounded(metrics.mCriticalDisplayPort.IsEmpty()
+                                       ? metrics.mDisplayPort
+                                       : metrics.mCriticalDisplayPort,
+                                     layerPixelRatioX, layerPixelRatioY);
+  displayPort += scrollOffsetLayerPixels;
 
   gfx::Margin fixedLayerMargins(0, 0, 0, 0);
   ScreenPoint offset(0, 0);
   ScreenPoint scrollOffset(0, 0);
   float scaleX = 1.0,
         scaleY = 1.0;
   SyncViewportInfo(displayPort, layerPixelRatioX, mLayersUpdated,
                    scrollOffset, scaleX, scaleY, fixedLayerMargins,
@@ -590,17 +588,17 @@ AsyncCompositionManager::SyncViewportInf
 #endif
 }
 
 void
 AsyncCompositionManager::SyncFrameMetrics(const gfx::Point& aScrollOffset,
                                           float aZoom,
                                           const CSSRect& aCssPageRect,
                                           bool aLayersUpdated,
-                                          const gfx::Rect& aDisplayPort,
+                                          const CSSRect& aDisplayPort,
                                           float aDisplayResolution,
                                           bool aIsFirstPaint,
                                           gfx::Margin& aFixedLayerMargins,
                                           ScreenPoint& aOffset)
 {
 #ifdef MOZ_WIDGET_ANDROID
   AndroidBridge::Bridge()->SyncFrameMetrics(aScrollOffset, aZoom, aCssPageRect,
                                             aLayersUpdated, aDisplayPort,
--- a/gfx/layers/composite/AsyncCompositionManager.h
+++ b/gfx/layers/composite/AsyncCompositionManager.h
@@ -125,17 +125,17 @@ private:
                         ScreenPoint& aScrollOffset,
                         float& aScaleX, float& aScaleY,
                         gfx::Margin& aFixedLayerMargins,
                         ScreenPoint& aOffset);
   void SyncFrameMetrics(const gfx::Point& aScrollOffset,
                         float aZoom,
                         const CSSRect& aCssPageRect,
                         bool aLayersUpdated,
-                        const gfx::Rect& aDisplayPort,
+                        const CSSRect& aDisplayPort,
                         float aDisplayResolution,
                         bool aIsFirstPaint,
                         gfx::Margin& aFixedLayerMargins,
                         ScreenPoint& aOffset);
 
   /**
    * Recursively applies the given translation to all top-level fixed position
    * layers that are descendants of the given layer.
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -430,17 +430,17 @@ GetRegionArea(const nsIntRegion& aRegion
   while (const nsIntRect* rect = it.Next()) {
     area += rect->width * rect->height;
   }
   return area;
 }
 
 #ifdef MOZ_ANDROID_OMTC
 static float
-GetDisplayportCoverage(const gfx::Rect& aDisplayPort,
+GetDisplayportCoverage(const CSSRect& aDisplayPort,
                        const gfx3DMatrix& aTransformToScreen,
                        const nsIntRect& aScreenRect)
 {
   gfxRect transformedDisplayport =
     aTransformToScreen.TransformBounds(gfxRect(aDisplayPort.x,
                                                aDisplayPort.y,
                                                aDisplayPort.width,
                                                aDisplayPort.height));
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -895,34 +895,34 @@ bool AsyncPanZoomController::EnlargeDisp
       // and to the left when skating negatively.
       *aDisplayPortOffset -= aVelocity < 0 ? aCompositionBounds : 0;
     }
     return true;
   }
   return false;
 }
 
-const gfx::Rect AsyncPanZoomController::CalculatePendingDisplayPort(
+const CSSRect AsyncPanZoomController::CalculatePendingDisplayPort(
   const FrameMetrics& aFrameMetrics,
   const gfx::Point& aVelocity,
   const gfx::Point& aAcceleration,
   double aEstimatedPaintDuration)
 {
   // If we don't get an estimated paint duration, we probably don't have any
   // data. In this case, we're dealing with either a stationary frame or a first
   // paint. In either of these cases, we can just assume it'll take 1 second to
   // paint. Getting this correct is not important anyways since it's only really
   // useful when accelerating, which can't be happening at this point.
   double estimatedPaintDuration =
     aEstimatedPaintDuration > EPSILON ? aEstimatedPaintDuration : 1.0;
 
   gfxSize resolution = CalculateResolution(aFrameMetrics);
   CSSIntRect compositionBounds = LayerIntRect::ToCSSIntRectRoundIn(
     aFrameMetrics.mCompositionBounds, resolution);
-  gfx::Rect scrollableRect = aFrameMetrics.mScrollableRect.ToUnknownRect();
+  CSSRect scrollableRect = aFrameMetrics.mScrollableRect;
 
   // 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
   // down. i.e. we know that scrollableRect can go back as far as zero.
   // but we don't know how much further ahead it can go.
   if (scrollableRect.width < compositionBounds.width) {
@@ -933,19 +933,19 @@ const gfx::Rect AsyncPanZoomController::
   if (scrollableRect.height < compositionBounds.height) {
       scrollableRect.y = std::max(0.f,
                                   scrollableRect.y - (compositionBounds.height - scrollableRect.height));
       scrollableRect.height = compositionBounds.height;
   }
 
   CSSPoint scrollOffset = aFrameMetrics.mScrollOffset;
 
-  gfx::Rect displayPort(0, 0,
-                        compositionBounds.width * gXStationarySizeMultiplier,
-                        compositionBounds.height * gYStationarySizeMultiplier);
+  CSSRect displayPort = CSSRect(compositionBounds);
+  displayPort.MoveTo(0, 0);
+  displayPort.Scale(gXStationarySizeMultiplier, gYStationarySizeMultiplier);
 
   // If there's motion along an axis of movement, and it's above a threshold,
   // then we want to paint a larger area in the direction of that motion so that
   // it's less likely to checkerboard.
   bool enlargedX = EnlargeDisplayPortAlongAxis(
     gXSkateSizeMultiplier, estimatedPaintDuration,
     compositionBounds.width, aVelocity.x, aAcceleration.x,
     &displayPort.x, &displayPort.width);
@@ -976,22 +976,18 @@ const gfx::Rect AsyncPanZoomController::
     scrollOffset.x = scrollableRect.x;
   }
   if (scrollOffset.y + compositionBounds.height > scrollableRect.height) {
     scrollOffset.y -= compositionBounds.height + scrollOffset.y - scrollableRect.height;
   } else if (scrollOffset.y < scrollableRect.y) {
     scrollOffset.y = scrollableRect.y;
   }
 
-  gfx::Rect shiftedDisplayPort = displayPort;
-  shiftedDisplayPort.MoveBy(scrollOffset.x, scrollOffset.y);
-  displayPort = scrollableRect.ClampRect(shiftedDisplayPort);
-  displayPort.MoveBy(-scrollOffset.x, -scrollOffset.y);
-
-  return displayPort;
+  CSSRect shiftedDisplayPort = displayPort + scrollOffset;
+  return scrollableRect.ClampRect(shiftedDisplayPort) - scrollOffset;
 }
 
 /*static*/ gfxSize
 AsyncPanZoomController::CalculateIntrinsicScale(const FrameMetrics& aMetrics)
 {
   gfxFloat intrinsicScale = (gfxFloat(aMetrics.mCompositionBounds.width) / 
                              gfxFloat(aMetrics.mViewport.width));
   return gfxSize(intrinsicScale, intrinsicScale);
@@ -1043,26 +1039,22 @@ void AsyncPanZoomController::RequestCont
   }
 
   mFrameMetrics.mDisplayPort =
     CalculatePendingDisplayPort(mFrameMetrics,
                                 GetVelocityVector(),
                                 GetAccelerationVector(),
                                 estimatedPaintDuration);
 
-  CSSPoint oldScrollOffset = mLastPaintRequestMetrics.mScrollOffset,
-           newScrollOffset = mFrameMetrics.mScrollOffset;
-
   // If we're trying to paint what we already think is painted, discard this
   // request since it's a pointless paint.
-  gfx::Rect oldDisplayPort = mLastPaintRequestMetrics.mDisplayPort;
-  gfx::Rect newDisplayPort = mFrameMetrics.mDisplayPort;
-
-  oldDisplayPort.MoveBy(oldScrollOffset.x, oldScrollOffset.y);
-  newDisplayPort.MoveBy(newScrollOffset.x, newScrollOffset.y);
+  CSSRect oldDisplayPort = mLastPaintRequestMetrics.mDisplayPort
+                         + mLastPaintRequestMetrics.mScrollOffset;
+  CSSRect newDisplayPort = mFrameMetrics.mDisplayPort
+                         + mFrameMetrics.mScrollOffset;
 
   if (fabsf(oldDisplayPort.x - newDisplayPort.x) < EPSILON &&
       fabsf(oldDisplayPort.y - newDisplayPort.y) < EPSILON &&
       fabsf(oldDisplayPort.width - newDisplayPort.width) < EPSILON &&
       fabsf(oldDisplayPort.height - newDisplayPort.height) < EPSILON &&
       mFrameMetrics.mResolution.width == mLastPaintRequestMetrics.mResolution.width) {
     return;
   }
--- a/gfx/layers/ipc/AsyncPanZoomController.h
+++ b/gfx/layers/ipc/AsyncPanZoomController.h
@@ -218,17 +218,17 @@ public:
   int GetDPI();
 
   /**
    * 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 gfx::Rect CalculatePendingDisplayPort(
+  static const CSSRect CalculatePendingDisplayPort(
     const FrameMetrics& aFrameMetrics,
     const gfx::Point& aVelocity,
     const gfx::Point& aAcceleration,
     double aEstimatedPaintDuration);
 
   /**
    * Return the scale factor needed to fit the viewport in |aMetrics|
    * into its composition bounds.
--- a/layout/base/Units.h
+++ b/layout/base/Units.h
@@ -36,21 +36,32 @@ typedef gfx::RectTyped<CSSPixel> CSSRect
 typedef gfx::IntRectTyped<CSSPixel> CSSIntRect;
 
 struct LayerPixel {
   static gfx::IntPointTyped<LayerPixel> FromCSSPointRounded(const CSSPoint& pt, float resolutionX, float resolutionY) {
     return gfx::IntPointTyped<LayerPixel>(NS_lround(pt.x * resolutionX),
                                           NS_lround(pt.y * resolutionY));
   }
 
+  static gfx::IntRectTyped<LayerPixel> RoundToInt(const gfx::RectTyped<LayerPixel>& rect) {
+    return gfx::IntRectTyped<LayerPixel>(NS_lround(rect.x),
+                                         NS_lround(rect.y),
+                                         NS_lround(rect.width),
+                                         NS_lround(rect.height));
+  }
+
+  static gfx::RectTyped<LayerPixel> FromCSSRect(const CSSRect& rect, float resolutionX, float resolutionY) {
+    return gfx::RectTyped<LayerPixel>(rect.x * resolutionX,
+                                      rect.y * resolutionY,
+                                      rect.width * resolutionX,
+                                      rect.height * resolutionY);
+  }
+
   static gfx::IntRectTyped<LayerPixel> FromCSSRectRounded(const CSSRect& rect, float resolutionX, float resolutionY) {
-    return gfx::IntRectTyped<LayerPixel>(NS_lround(rect.x * resolutionX),
-                                         NS_lround(rect.y * resolutionY),
-                                         NS_lround(rect.width * resolutionX),
-                                         NS_lround(rect.height * resolutionY));
+    return RoundToInt(FromCSSRect(rect, resolutionX, resolutionY));
   }
 
   static gfx::IntRectTyped<LayerPixel> FromCSSRectRoundOut(const CSSRect& rect, gfxFloat resolution) {
     gfx::RectTyped<LayerPixel> scaled(rect.x, rect.y, rect.width, rect.height);
     scaled.ScaleInverseRoundOut(resolution);
     return gfx::IntRectTyped<LayerPixel>(scaled.x, scaled.y, scaled.width, scaled.height);
   }
 
@@ -62,16 +73,17 @@ struct LayerPixel {
 
   static CSSIntRect ToCSSIntRectRoundIn(const gfx::IntRectTyped<LayerPixel>& rect, gfxSize resolution) {
     gfx::IntRectTyped<CSSPixel> ret(rect.x, rect.y, rect.width, rect.height);
     ret.ScaleInverseRoundIn(resolution.width, resolution.height);
     return ret;
   }
 };
 
+typedef gfx::PointTyped<LayerPixel> LayerPoint;
 typedef gfx::IntPointTyped<LayerPixel> LayerIntPoint;
 typedef gfx::IntSizeTyped<LayerPixel> LayerIntSize;
 typedef gfx::RectTyped<LayerPixel> LayerRect;
 typedef gfx::IntRectTyped<LayerPixel> LayerIntRect;
 
 struct ScreenPixel {
 };
 
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -638,29 +638,20 @@ static void RecordFrameMetrics(nsIFrame*
 
   metrics.mViewport = mozilla::gfx::Rect(
     NSAppUnitsToDoublePixels(aViewport.x, auPerDevPixel),
     NSAppUnitsToDoublePixels(aViewport.y, auPerDevPixel),
     NSAppUnitsToDoublePixels(aViewport.width, auPerDevPixel),
     NSAppUnitsToDoublePixels(aViewport.height, auPerDevPixel));
 
   if (aDisplayPort) {
-    metrics.mDisplayPort = mozilla::gfx::Rect(
-      NSAppUnitsToDoublePixels(aDisplayPort->x, auPerDevPixel),
-      NSAppUnitsToDoublePixels(aDisplayPort->y, auPerDevPixel),
-      NSAppUnitsToDoublePixels(aDisplayPort->width, auPerDevPixel),
-      NSAppUnitsToDoublePixels(aDisplayPort->height, auPerDevPixel));
-
-      if (aCriticalDisplayPort) {
-        metrics.mCriticalDisplayPort = mozilla::gfx::Rect(
-          NSAppUnitsToDoublePixels(aCriticalDisplayPort->x, auPerDevPixel),
-          NSAppUnitsToDoublePixels(aCriticalDisplayPort->y, auPerDevPixel),
-          NSAppUnitsToDoublePixels(aCriticalDisplayPort->width, auPerDevPixel),
-          NSAppUnitsToDoublePixels(aCriticalDisplayPort->height, auPerDevPixel));
-      }
+    metrics.mDisplayPort = CSSRect::FromAppUnits(*aDisplayPort);
+    if (aCriticalDisplayPort) {
+      metrics.mCriticalDisplayPort = CSSRect::FromAppUnits(*aCriticalDisplayPort);
+    }
   }
 
   nsIScrollableFrame* scrollableFrame = nullptr;
   if (aScrollFrame)
     scrollableFrame = aScrollFrame->GetScrollTargetFrame();
 
   if (scrollableFrame) {
     nsRect contentBounds = scrollableFrame->GetScrollRange();
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -2143,17 +2143,17 @@ AndroidBridge::SyncViewportInfo(const La
         return;
 
     client->SyncViewportInfo(aDisplayPort, aDisplayResolution, aLayersUpdated,
                              aScrollOffset, aScaleX, aScaleY, aFixedLayerMargins,
                              aOffset);
 }
 
 void AndroidBridge::SyncFrameMetrics(const gfx::Point& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
-                                     bool aLayersUpdated, const gfx::Rect& aDisplayPort, float aDisplayResolution,
+                                     bool aLayersUpdated, const CSSRect& aDisplayPort, float aDisplayResolution,
                                      bool aIsFirstPaint, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset)
 {
     AndroidGeckoLayerClient *client = mLayerClient;
     if (!client)
         return;
 
     client->SyncFrameMetrics(aScrollOffset, aZoom, aCssPageRect,
                              aLayersUpdated, aDisplayPort, aDisplayResolution,
@@ -2729,17 +2729,17 @@ AndroidBridge::IsContentDocumentDisplaye
     JNIEnv* env = GetJNIEnv();
     if (!env || !mLayerClient)
         return false;
     AutoLocalJNIFrame jniFrame(env, 0);
     return mLayerClient->IsContentDocumentDisplayed(&jniFrame);
 }
 
 bool
-AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const gfx::Rect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY)
+AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY)
 {
     AndroidGeckoLayerClient *client = mLayerClient;
     if (!client)
         return false;
 
     return client->ProgressiveUpdateCallback(aHasPendingNewThebesContent, aDisplayPort, aDisplayResolution, aDrawingCritical, aViewport, aScaleX, aScaleY);
 }
 
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -189,17 +189,17 @@ public:
     double GetSampleTimeJavaProfiling(uint32_t aThreadId, uint32_t aSampleId);
 
     nsresult CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, jobject buffer);
     void SendThumbnail(jobject buffer, int32_t tabId, bool success);
     void GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort);
     void ContentDocumentChanged();
     bool IsContentDocumentDisplayed();
 
-    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const gfx::Rect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
+    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
 
     void AcknowledgeEvent();
 
     void EnableLocation(bool aEnable);
     void EnableLocationHighAccuracy(bool aEnable);
 
     void EnableSensor(int aSensorType);
 
@@ -372,17 +372,17 @@ public:
     void DisableNetworkNotifications();
 
     void SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const LayerIntRect& aPageRect, const CSSRect& aCssPageRect);
     void SetPageRect(const CSSRect& aCssPageRect);
     void SyncViewportInfo(const LayerIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated,
                           ScreenPoint& aScrollOffset, float& aScaleX, float& aScaleY,
                           gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset);
     void SyncFrameMetrics(const gfx::Point& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
-                          bool aLayersUpdated, const gfx::Rect& aDisplayPort, float aDisplayResolution,
+                          bool aLayersUpdated, const CSSRect& aDisplayPort, float aDisplayResolution,
                           bool aIsFirstPaint, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset);
 
     void AddPluginView(jobject view, const gfxRect& rect, bool isFullScreen);
     void RemovePluginView(jobject view, 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/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -918,53 +918,52 @@ AndroidGeckoLayerClient::SyncViewportInf
     viewTransform.GetFixedLayerMargins(env, aFixedLayerMargins);
 
     aOffset.x = viewTransform.GetOffsetX(env);
     aOffset.y = viewTransform.GetOffsetY(env);
 }
 
 void
 AndroidGeckoLayerClient::SyncFrameMetrics(const gfx::Point& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
-                                          bool aLayersUpdated, const gfx::Rect& aDisplayPort, float aDisplayResolution,
+                                          bool aLayersUpdated, const CSSRect& aDisplayPort, float aDisplayResolution,
                                           bool aIsFirstPaint, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset)
 {
     NS_ASSERTION(!isNull(), "SyncFrameMetrics called on null layer client!");
     JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
 
     // convert the displayport rect from scroll-relative CSS pixels to document-relative device pixels
-    int dpX = NS_lround((aDisplayPort.x * aDisplayResolution) + aScrollOffset.x);
-    int dpY = NS_lround((aDisplayPort.y * aDisplayResolution) + aScrollOffset.y);
-    int dpW = NS_lround(aDisplayPort.width * aDisplayResolution);
-    int dpH = NS_lround(aDisplayPort.height * aDisplayResolution);
+    LayerRect dpUnrounded = LayerRect::FromCSSRect(aDisplayPort, aDisplayResolution, aDisplayResolution);
+    dpUnrounded += LayerPoint::FromUnknownPoint(aScrollOffset);
+    LayerIntRect dp = LayerRect::RoundToInt(dpUnrounded);
 
     jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jSyncFrameMetricsMethod,
             aScrollOffset.x, aScrollOffset.y, aZoom,
             aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(),
-            aLayersUpdated, dpX, dpY, dpW, dpH, aDisplayResolution,
+            aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution,
             aIsFirstPaint);
 
     if (jniFrame.CheckForException())
         return;
 
     NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
 
     AndroidViewTransform viewTransform;
     viewTransform.Init(viewTransformJObj);
     viewTransform.GetFixedLayerMargins(env, aFixedLayerMargins);
     aOffset.x = viewTransform.GetOffsetX(env);
     aOffset.y = viewTransform.GetOffsetY(env);
 }
 
 bool
 AndroidGeckoLayerClient::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
-                                                   const gfx::Rect& aDisplayPort,
+                                                   const LayerRect& aDisplayPort,
                                                    float aDisplayResolution,
                                                    bool aDrawingCritical,
                                                    gfx::Rect& aViewport,
                                                    float& aScaleX,
                                                    float& aScaleY)
 {
     JNIEnv *env = AndroidBridge::GetJNIEnv();
     if (!env)
--- a/widget/android/AndroidJavaWrappers.h
+++ b/widget/android/AndroidJavaWrappers.h
@@ -270,19 +270,19 @@ public:
     AndroidGeckoLayerClient(jobject jobj) { Init(jobj); }
 
     void SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const LayerIntRect& aPageRect, const CSSRect& aCssPageRect);
     void SetPageRect(const CSSRect& aCssPageRect);
     void SyncViewportInfo(const LayerIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated,
                           ScreenPoint& aScrollOffset, float& aScaleX, float& aScaleY,
                           gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset);
     void SyncFrameMetrics(const gfx::Point& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
-                          bool aLayersUpdated, const gfx::Rect& aDisplayPort, float aDisplayResolution,
+                          bool aLayersUpdated, const CSSRect& aDisplayPort, float aDisplayResolution,
                           bool aIsFirstPaint, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset);
-    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const gfx::Rect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
+    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
     bool CreateFrame(AutoLocalJNIFrame *jniFrame, AndroidLayerRendererFrame& aFrame);
     bool ActivateProgram(AutoLocalJNIFrame *jniFrame);
     bool DeactivateProgram(AutoLocalJNIFrame *jniFrame);
     void GetDisplayPort(AutoLocalJNIFrame *jniFrame, bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort);
     void ContentDocumentChanged(AutoLocalJNIFrame *jniFrame);
     bool IsContentDocumentDisplayed(AutoLocalJNIFrame *jniFrame);
 
 protected: