Bug 785929 - Kill FrameMetrics.mContentRect. r=kentuckyfriedtakahe
authorKartikaya Gupta <kgupta@mozilla.com>
Tue, 11 Jun 2013 09:46:51 -0400
changeset 134638 a1ebe92839fa9fc24e20e30ce8dcf14a3325d2a3
parent 134637 c8dc1b7370454de71d9421ae4cf4d06ec7910cd6
child 134639 57c8642772b50737cd19b3a96bc2dc7a6b89aadf
push id24808
push userryanvm@gmail.com
push dateTue, 11 Jun 2013 19:01:06 +0000
treeherdermozilla-central@0acda90a6f6a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskentuckyfriedtakahe
bugs785929
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 785929 - Kill FrameMetrics.mContentRect. r=kentuckyfriedtakahe
gfx/layers/FrameMetrics.h
gfx/layers/composite/AsyncCompositionManager.cpp
gfx/layers/composite/AsyncCompositionManager.h
gfx/layers/composite/ThebesLayerComposite.cpp
gfx/layers/ipc/AsyncPanZoomController.cpp
gfx/layers/ipc/AsyncPanZoomController.h
ipc/glue/IPCMessageUtils.h
layout/base/Units.h
layout/base/nsDisplayList.cpp
layout/ipc/RenderFrameParent.cpp
mobile/android/base/gfx/GeckoLayerClient.java
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/AndroidJavaWrappers.cpp
widget/android/AndroidJavaWrappers.h
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -27,17 +27,16 @@ public:
   typedef uint64_t ViewID;
   static const ViewID NULL_SCROLL_ID;   // This container layer does not scroll.
   static const ViewID ROOT_SCROLL_ID;   // This is the root scroll frame.
   static const ViewID START_SCROLL_ID;  // This is the ID that scrolling subframes
                                         // will begin at.
 
   FrameMetrics()
     : mCompositionBounds(0, 0, 0, 0)
-    , mContentRect(0, 0, 0, 0)
     , mDisplayPort(0, 0, 0, 0)
     , mCriticalDisplayPort(0, 0, 0, 0)
     , mViewport(0, 0, 0, 0)
     , mScrollOffset(0, 0)
     , mScrollId(NULL_SCROLL_ID)
     , mScrollableRect(0, 0, 0, 0)
     , mResolution(1, 1)
     , mZoom(1, 1)
@@ -46,17 +45,16 @@ public:
     , mPresShellId(-1)
   {}
 
   // Default copy ctor and operator= are fine
 
   bool operator==(const FrameMetrics& aOther) const
   {
     return mCompositionBounds.IsEqualEdges(aOther.mCompositionBounds) &&
-           mContentRect.IsEqualEdges(aOther.mContentRect) &&
            mDisplayPort.IsEqualEdges(aOther.mDisplayPort) &&
            mCriticalDisplayPort.IsEqualEdges(aOther.mCriticalDisplayPort) &&
            mViewport.IsEqualEdges(aOther.mViewport) &&
            mScrollOffset == aOther.mScrollOffset &&
            mScrollId == aOther.mScrollId &&
            mScrollableRect.IsEqualEdges(aOther.mScrollableRect) &&
            mResolution == aOther.mResolution &&
            mDevPixelsPerCSSPixel == aOther.mDevPixelsPerCSSPixel &&
@@ -117,27 +115,16 @@ public:
   // or too much of it prerendered. If the displayport is the same as the
   // viewport, there is no need for this and we can just use the viewport
   // instead.
   //
   // This is only valid on the root layer. Nested iframes do not need this
   // metric as they do not have a displayport set. See bug 775452.
   LayerIntRect mCompositionBounds;
 
-  // |mScrollableRect|, stored in layer pixels. DECPRECATED, DO NOT USE.
-  //
-  // This is valid on any layer where |mScrollableRect| is, though it may be
-  // more lazily maintained than |mScrollableRect|. That is, when
-  // |mScrollableRect| is updated, this may lag. For this reason, it's better to
-  // use |mScrollableRect| for any control logic.
-  //
-  // FIXME/bug 785929: Is this really necessary? Can it not be calculated from
-  // |mScrollableRect| whenever it's needed?
-  LayerIntRect mContentRect;
-
   // ---------------------------------------------------------------------------
   // The following metrics are all in CSS pixels. They are not in any uniform
   // space, so each is explained separately.
   //
 
   // The area of a frame's contents that has been painted, relative to the
   // viewport. It is in the same coordinate space as |mViewport|. For example,
   // if it is at 0,0, then it's at the same place at the viewport, which is at
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -406,25 +406,24 @@ AsyncCompositionManager::TransformScroll
 
   float layerPixelRatioX = 1 / aRootTransform.GetXScale(),
         layerPixelRatioY = 1 / aRootTransform.GetYScale();
 
   LayerIntPoint scrollOffsetLayerPixels = LayerIntPoint::FromCSSPointRounded(
     metrics.mScrollOffset, layerPixelRatioX, layerPixelRatioY);
 
   if (mIsFirstPaint) {
-    mContentRect = metrics.mContentRect;
+    mContentRect = metrics.mScrollableRect;
     SetFirstPaintViewport(scrollOffsetLayerPixels,
                           layerPixelRatioX,
-                          mContentRect,
-                          metrics.mScrollableRect);
+                          mContentRect);
     mIsFirstPaint = false;
-  } else if (!metrics.mContentRect.IsEqualEdges(mContentRect)) {
-    mContentRect = metrics.mContentRect;
-    SetPageRect(metrics.mScrollableRect);
+  } else if (!metrics.mScrollableRect.IsEqualEdges(mContentRect)) {
+    mContentRect = metrics.mScrollableRect;
+    SetPageRect(mContentRect);
   }
 
   // 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(metrics.mCriticalDisplayPort.IsEmpty()
                                        ? metrics.mDisplayPort
@@ -465,36 +464,37 @@ AsyncCompositionManager::TransformScroll
   treeTransform = gfx3DMatrix(ViewTransform(-scrollCompensation,
                                             gfxSize(scaleX, scaleY)));
 
   // Translate fixed position layers so that they stay in the correct position
   // when scrollOffset and metricsScrollOffset differ.
   gfxPoint fixedOffset;
   gfxSize scaleDiff;
 
+  LayerRect content = LayerRect::FromCSSRect(mContentRect,
+                                             1 / aRootTransform.GetXScale(),
+                                             1 / aRootTransform.GetYScale());
   // If the contents can fit entirely within the widget area on a particular
-  // dimenson, we need to translate and scale so that the fixed layers remain
+  // dimension, we need to translate and scale so that the fixed layers remain
   // within the page boundaries.
-  if (mContentRect.width * tempScaleDiffX < metrics.mCompositionBounds.width) {
+  if (mContentRect.width * scaleX < metrics.mCompositionBounds.width) {
     fixedOffset.x = -metricsScrollOffset.x;
-    scaleDiff.width = std::min(1.0f, metrics.mCompositionBounds.width / (float)mContentRect.width);
+    scaleDiff.width = std::min(1.0f, metrics.mCompositionBounds.width / content.width);
   } else {
-    fixedOffset.x = clamped(scrollOffset.x / tempScaleDiffX, (float)mContentRect.x,
-                       mContentRect.XMost() - metrics.mCompositionBounds.width / tempScaleDiffX) -
-               metricsScrollOffset.x;
+    fixedOffset.x = clamped(scrollOffset.x / tempScaleDiffX, content.x,
+        content.XMost() - metrics.mCompositionBounds.width / tempScaleDiffX) - metricsScrollOffset.x;
     scaleDiff.width = tempScaleDiffX;
   }
 
-  if (mContentRect.height * tempScaleDiffY < metrics.mCompositionBounds.height) {
+  if (mContentRect.height * scaleY < metrics.mCompositionBounds.height) {
     fixedOffset.y = -metricsScrollOffset.y;
-    scaleDiff.height = std::min(1.0f, metrics.mCompositionBounds.height / (float)mContentRect.height);
+    scaleDiff.height = std::min(1.0f, metrics.mCompositionBounds.height / content.height);
   } else {
-    fixedOffset.y = clamped(scrollOffset.y / tempScaleDiffY, (float)mContentRect.y,
-                       mContentRect.YMost() - metrics.mCompositionBounds.height / tempScaleDiffY) -
-               metricsScrollOffset.y;
+    fixedOffset.y = clamped(scrollOffset.y / tempScaleDiffY, content.y,
+        content.YMost() - metrics.mCompositionBounds.height / tempScaleDiffY) - metricsScrollOffset.y;
     scaleDiff.height = tempScaleDiffY;
   }
 
   // The transform already takes the resolution scale into account.  Since we
   // will apply the resolution scale again when computing the effective
   // transform, we must apply the inverse resolution scale here.
   gfx3DMatrix computedTransform = treeTransform * currentTransform;
   computedTransform.Scale(1.0f/container->GetPreXScale(),
@@ -547,21 +547,20 @@ AsyncCompositionManager::TransformShadow
   }
 
   return wantNextFrame;
 }
 
 void
 AsyncCompositionManager::SetFirstPaintViewport(const LayerIntPoint& aOffset,
                                                float aZoom,
-                                               const LayerIntRect& aPageRect,
                                                const CSSRect& aCssPageRect)
 {
 #ifdef MOZ_WIDGET_ANDROID
-  AndroidBridge::Bridge()->SetFirstPaintViewport(aOffset, aZoom, aPageRect, aCssPageRect);
+  AndroidBridge::Bridge()->SetFirstPaintViewport(aOffset, aZoom, aCssPageRect);
 #endif
 }
 
 void
 AsyncCompositionManager::SetPageRect(const CSSRect& aCssPageRect)
 {
 #ifdef MOZ_WIDGET_ANDROID
   AndroidBridge::Bridge()->SetPageRect(aCssPageRect);
--- a/gfx/layers/composite/AsyncCompositionManager.h
+++ b/gfx/layers/composite/AsyncCompositionManager.h
@@ -111,17 +111,16 @@ private:
   // Return true if an AsyncPanZoomController content transform was
   // applied for |aLayer|.  *aWantNextFrame is set to true if the
   // controller wants another animation frame.
   bool ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame, Layer* aLayer,
                                         bool* aWantNextFrame);
 
   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,
@@ -158,17 +157,17 @@ private:
   /**
    * Detaches all referents resolved by ResolveRefLayers.
    * Assumes that mLayerManager->GetRoot() and mTargetConfig have not changed
    * since ResolveRefLayers was called.
    */
   void DetachRefLayers();
 
   TargetConfig mTargetConfig;
-  LayerIntRect mContentRect;
+  CSSRect mContentRect;
 
   nsRefPtr<LayerManagerComposite> mLayerManager;
   // When this flag is set, the next composition will be the first for a
   // particular document (i.e. the document displayed on the screen will change).
   // This happens when loading a new page or switching tabs. We notify the
   // front-end (e.g. Java on Android) about this so that it take the new page
   // size and zoom into account when providing us with the next view transform.
   bool mIsFirstPaint;
--- a/gfx/layers/composite/ThebesLayerComposite.cpp
+++ b/gfx/layers/composite/ThebesLayerComposite.cpp
@@ -246,25 +246,27 @@ ThebesLayerComposite::GetCompositionBoun
       // the content resolution.
       Layer* rootLayer = Manager()->GetRoot();
       const gfx3DMatrix& rootTransform = rootLayer->GetTransform();
       float scaleX = rootTransform.GetXScale();
       float scaleY = rootTransform.GetYScale();
 
       // Get the content document bounds, in screen-space.
       const FrameMetrics& metrics = scrollableLayer->GetFrameMetrics();
-      const LayerIntSize& contentSize = metrics.mContentRect.Size();
+      const LayerIntRect content = LayerIntRect::FromCSSRectRounded(metrics.mScrollableRect,
+                                                                    1 / scaleX,
+                                                                    1 / scaleY);
       gfx::Point scrollOffset =
         gfx::Point((metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().width) / scaleX,
                    (metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().height) / scaleY);
       const nsIntPoint contentOrigin(
-        metrics.mContentRect.x - NS_lround(scrollOffset.x),
-        metrics.mContentRect.y - NS_lround(scrollOffset.y));
+        content.x - NS_lround(scrollOffset.x),
+        content.y - NS_lround(scrollOffset.y));
       gfxRect contentRect = gfxRect(contentOrigin.x, contentOrigin.y,
-                                    contentSize.width, contentSize.height);
+                                    content.width, content.height);
       gfxRect contentBounds = scrollableLayer->GetEffectiveTransform().
         TransformBounds(contentRect);
 
       // Clip the composition bounds to the content bounds
       compositionBounds.IntersectRect(compositionBounds, contentBounds);
       break;
     }
   }
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -827,40 +827,23 @@ void AsyncPanZoomController::SetComposit
 void AsyncPanZoomController::ScrollBy(const gfx::Point& aOffset) {
   gfx::Point newOffset(mFrameMetrics.mScrollOffset.x + aOffset.x,
                        mFrameMetrics.mScrollOffset.y + aOffset.y);
   FrameMetrics metrics(mFrameMetrics);
   metrics.mScrollOffset = CSSPoint::FromUnknownPoint(newOffset);
   mFrameMetrics = metrics;
 }
 
-void AsyncPanZoomController::SetPageRect(const CSSRect& aCSSPageRect) {
-  FrameMetrics metrics = mFrameMetrics;
-  gfxFloat resolution = CalculateResolution(mFrameMetrics).width;
-
-  // The page rect is the css page rect scaled by the current zoom.
-  // Round the page rect so we don't get any truncation, then get the nsIntRect
-  // from this.
-  metrics.mContentRect = LayerRect::FromCSSRectRoundOut(aCSSPageRect, resolution, resolution);
-  metrics.mScrollableRect = aCSSPageRect;
-
-  mFrameMetrics = metrics;
-}
-
 void AsyncPanZoomController::ScaleWithFocus(float aZoom,
                                             const nsIntPoint& aFocus) {
   float zoomFactor = aZoom / mFrameMetrics.mZoom.width;
   gfxFloat resolution = CalculateResolution(mFrameMetrics).width;
 
   SetZoomAndResolution(aZoom);
 
-  // Force a recalculation of the page rect based on the new zoom and the
-  // current CSS page rect (which is unchanged since it's not affected by zoom).
-  SetPageRect(mFrameMetrics.mScrollableRect);
-
   // If the new scale is very small, we risk multiplying in huge rounding
   // errors, so don't bother adjusting the scroll offset.
   if (resolution >= 0.01f) {
     mFrameMetrics.mScrollOffset.x +=
       gfxFloat(aFocus.x) * (zoomFactor - 1.0) / resolution;
     mFrameMetrics.mScrollOffset.y +=
       gfxFloat(aFocus.y) * (zoomFactor - 1.0) / resolution;
   }
@@ -1267,22 +1250,19 @@ void AsyncPanZoomController::NotifyLayer
   if (aIsFirstPaint || mFrameMetrics.IsDefault()) {
     mPreviousPaintDurations.Clear();
 
     mX.CancelTouch();
     mY.CancelTouch();
 
     mFrameMetrics = aViewportFrame;
 
-    SetPageRect(mFrameMetrics.mScrollableRect);
-
     mState = NOTHING;
   } else if (!mFrameMetrics.mScrollableRect.IsEqualEdges(aViewportFrame.mScrollableRect)) {
     mFrameMetrics.mScrollableRect = aViewportFrame.mScrollableRect;
-    SetPageRect(mFrameMetrics.mScrollableRect);
   }
 
   if (needContentRepaint) {
     RequestContentRepaint();
   }
 }
 
 const FrameMetrics& AsyncPanZoomController::GetFrameMetrics() {
--- a/gfx/layers/ipc/AsyncPanZoomController.h
+++ b/gfx/layers/ipc/AsyncPanZoomController.h
@@ -194,22 +194,16 @@ public:
    */
   void SetCompositorParent(CompositorParent* aCompositorParent);
 
   // --------------------------------------------------------------------------
   // These methods can be called from any thread.
   //
 
   /**
-   * Sets the CSS page rect, and calculates a new page rect based on the zoom
-   * level of the current metrics and the passed in CSS page rect.
-   */
-  void SetPageRect(const CSSRect& aCSSPageRect);
-
-  /**
    * Sets the DPI of the device for use within panning and zooming logic. It is
    * a platform responsibility to set this on initialization of this class and
    * whenever it changes.
    */
   void SetDPI(int aDPI);
 
   /**
    * Gets the DPI of the device for use outside the panning and zooming logic.
--- a/ipc/glue/IPCMessageUtils.h
+++ b/ipc/glue/IPCMessageUtils.h
@@ -1069,34 +1069,32 @@ template <>
 struct ParamTraits<mozilla::layers::FrameMetrics>
 {
   typedef mozilla::layers::FrameMetrics paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mScrollableRect);
     WriteParam(aMsg, aParam.mViewport);
-    WriteParam(aMsg, aParam.mContentRect);
     WriteParam(aMsg, aParam.mScrollOffset);
     WriteParam(aMsg, aParam.mDisplayPort);
     WriteParam(aMsg, aParam.mCriticalDisplayPort);
     WriteParam(aMsg, aParam.mCompositionBounds);
     WriteParam(aMsg, aParam.mScrollId);
     WriteParam(aMsg, aParam.mResolution);
     WriteParam(aMsg, aParam.mZoom);
     WriteParam(aMsg, aParam.mDevPixelsPerCSSPixel);
     WriteParam(aMsg, aParam.mMayHaveTouchListeners);
     WriteParam(aMsg, aParam.mPresShellId);
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     return (ReadParam(aMsg, aIter, &aResult->mScrollableRect) &&
             ReadParam(aMsg, aIter, &aResult->mViewport) &&
-            ReadParam(aMsg, aIter, &aResult->mContentRect) &&
             ReadParam(aMsg, aIter, &aResult->mScrollOffset) &&
             ReadParam(aMsg, aIter, &aResult->mDisplayPort) &&
             ReadParam(aMsg, aIter, &aResult->mCriticalDisplayPort) &&
             ReadParam(aMsg, aIter, &aResult->mCompositionBounds) &&
             ReadParam(aMsg, aIter, &aResult->mScrollId) &&
             ReadParam(aMsg, aIter, &aResult->mResolution) &&
             ReadParam(aMsg, aIter, &aResult->mZoom) &&
             ReadParam(aMsg, aIter, &aResult->mDevPixelsPerCSSPixel) &&
--- a/layout/base/Units.h
+++ b/layout/base/Units.h
@@ -78,22 +78,16 @@ struct LayerPixel {
                                       aRect.width * aResolutionX,
                                       aRect.height * aResolutionY);
   }
 
   static gfx::IntRectTyped<LayerPixel> FromCSSRectRounded(const CSSRect& aRect, float aResolutionX, float aResolutionY) {
     return RoundToInt(FromCSSRect(aRect, aResolutionX, aResolutionY));
   }
 
-  static gfx::IntRectTyped<LayerPixel> FromCSSRectRoundOut(const CSSRect& aRect, float aResolutionX, float aResolutionY) {
-    gfx::RectTyped<LayerPixel> scaled(aRect.x, aRect.y, aRect.width, aRect.height);
-    scaled.ScaleInverseRoundOut(aResolutionX, aResolutionY);
-    return gfx::IntRectTyped<LayerPixel>(scaled.x, scaled.y, scaled.width, scaled.height);
-  }
-
   static CSSIntRect ToCSSIntRectRoundIn(const gfx::IntRectTyped<LayerPixel>& aRect, float aResolutionX, float aResolutionY) {
     gfx::IntRectTyped<CSSPixel> ret(aRect.x, aRect.y, aRect.width, aRect.height);
     ret.ScaleInverseRoundIn(aResolutionX, aResolutionY);
     return ret;
   }
 };
 
 typedef gfx::PointTyped<LayerPixel> LayerPoint;
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -647,32 +647,22 @@ static void RecordFrameMetrics(nsIFrame*
   if (aScrollFrame)
     scrollableFrame = aScrollFrame->GetScrollTargetFrame();
 
   if (scrollableFrame) {
     nsRect contentBounds = scrollableFrame->GetScrollRange();
     contentBounds.width += scrollableFrame->GetScrollPortRect().width;
     contentBounds.height += scrollableFrame->GetScrollPortRect().height;
     metrics.mScrollableRect = CSSRect::FromAppUnits(contentBounds);
-    nsIntRect contentRect = contentBounds.ScaleToNearestPixels(
-      aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
-    // I'm not sure what units contentRect is really in, hence FromUnknownRect
-    metrics.mContentRect = LayerIntRect::FromUnknownRect(mozilla::gfx::IntRect(
-      contentRect.x, contentRect.y, contentRect.width, contentRect.height));
     nsPoint scrollPosition = scrollableFrame->GetScrollPosition();
     metrics.mScrollOffset = CSSPoint::FromAppUnits(scrollPosition);
   }
   else {
     nsRect contentBounds = aForFrame->GetRect();
     metrics.mScrollableRect = CSSRect::FromAppUnits(contentBounds);
-    nsIntRect contentRect = contentBounds.ScaleToNearestPixels(
-      aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
-    // I'm not sure what units contentRect is really in, hence FromUnknownRect
-    metrics.mContentRect = LayerIntRect::FromUnknownRect(mozilla::gfx::IntRect(
-      contentRect.x, contentRect.y, contentRect.width, contentRect.height));
   }
 
   metrics.mScrollId = aScrollId;
 
   nsIPresShell* presShell = presContext->GetPresShell();
   if (TabChild *tc = GetTabChildFrom(presShell)) {
     metrics.mZoom = tc->GetZoom();
   }
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -411,18 +411,18 @@ BuildViewMap(ViewMap& oldContentViews, V
 
     // I don't know what units mViewportSize is in, hence use ToUnknownRect
     // here to mark the current frontier in type info propagation
     gfx::Rect viewport = metrics.mViewport.ToUnknownRect();
     view->mViewportSize = nsSize(
       NSIntPixelsToAppUnits(viewport.width, auPerDevPixel) * aXScale,
       NSIntPixelsToAppUnits(viewport.height, auPerDevPixel) * aYScale);
     view->mContentSize = nsSize(
-      NSIntPixelsToAppUnits(metrics.mContentRect.width, auPerDevPixel) * aXScale,
-      NSIntPixelsToAppUnits(metrics.mContentRect.height, auPerDevPixel) * aYScale);
+      NSFloatPixelsToAppUnits(metrics.mScrollableRect.width, auPerCSSPixel) * aXScale,
+      NSFloatPixelsToAppUnits(metrics.mScrollableRect.height, auPerCSSPixel) * aYScale);
 
     newContentViews[scrollId] = view;
   }
 
   for (Layer* child = aLayer->GetFirstChild();
        child; child = child->GetNextSibling()) {
     BuildViewMap(oldContentViews, newContentViews, aFrameLoader, child,
                  aXScale, aYScale, aAccConfigXScale, aAccConfigYScale);
--- a/mobile/android/base/gfx/GeckoLayerClient.java
+++ b/mobile/android/base/gfx/GeckoLayerClient.java
@@ -548,28 +548,27 @@ public class GeckoLayerClient implements
     /** This function is invoked by Gecko via JNI; be careful when modifying signature.
       * The compositor invokes this function just before compositing a frame where the document
       * is different from the document composited on the last frame. In these cases, the viewport
       * information we have in Java is no longer valid and needs to be replaced with the new
       * viewport information provided. setPageRect will never be invoked on the same frame that
       * this function is invoked on; and this function will always be called prior to syncViewportInfo.
       */
     public void setFirstPaintViewport(float offsetX, float offsetY, float zoom,
-            float pageLeft, float pageTop, float pageRight, float pageBottom,
             float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) {
         synchronized (getLock()) {
             ImmutableViewportMetrics currentMetrics = getViewportMetrics();
 
             Tab tab = Tabs.getInstance().getSelectedTab();
 
+            RectF cssPageRect = new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom);
             final ImmutableViewportMetrics newMetrics = currentMetrics
                 .setViewportOrigin(offsetX, offsetY)
                 .setZoomFactor(zoom)
-                .setPageRect(new RectF(pageLeft, pageTop, pageRight, pageBottom),
-                             new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom))
+                .setPageRect(RectUtils.scale(cssPageRect, zoom), cssPageRect)
                 .setIsRTL(tab.getIsRTL());
             // Since we have switched to displaying a different document, we need to update any
             // viewport-related state we have lying around. This includes mGeckoViewport and
             // mViewportMetrics. Usually this information is updated via handleViewportMessage
             // while we remain on the same document.
             post(new Runnable() {
                 @Override
                 public void run() {
@@ -685,19 +684,18 @@ public class GeckoLayerClient implements
 
     /* Invoked by JNI from the compositor thread */
     public ViewTransform syncFrameMetrics(float offsetX, float offsetY, float zoom,
                 float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom,
                 boolean layersUpdated, int x, int y, int width, int height, float resolution,
                 boolean isFirstPaint)
     {
         if (isFirstPaint) {
-            RectF pageRect = RectUtils.scale(new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom), zoom);
-            setFirstPaintViewport(offsetX, offsetY, zoom, pageRect.left, pageRect.top, pageRect.right,
-                    pageRect.bottom, cssPageLeft, cssPageTop, cssPageRight, cssPageBottom);
+            setFirstPaintViewport(offsetX, offsetY, zoom,
+                                  cssPageLeft, cssPageTop, cssPageRight, cssPageBottom);
         }
 
         return syncViewportInfo(x, y, width, height, resolution, layersUpdated);
     }
 
     /** This function is invoked by Gecko via JNI; be careful when modifying signature. */
     public LayerRenderer.Frame createFrame() {
         // Create the shaders and textures if necessary.
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -2109,23 +2109,23 @@ AndroidBridge::IsTablet()
     bool ret = env->CallStaticBooleanMethod(mGeckoAppShellClass, jIsTablet);
     if (jniFrame.CheckForException())
         return false;
 
     return ret;
 }
 
 void
-AndroidBridge::SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const LayerIntRect& aPageRect, const CSSRect& aCssPageRect)
+AndroidBridge::SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const CSSRect& aCssPageRect)
 {
     AndroidGeckoLayerClient *client = mLayerClient;
     if (!client)
         return;
 
-    client->SetFirstPaintViewport(aOffset, aZoom, aPageRect, aCssPageRect);
+    client->SetFirstPaintViewport(aOffset, aZoom, aCssPageRect);
 }
 
 void
 AndroidBridge::SetPageRect(const CSSRect& aCssPageRect)
 {
     AndroidGeckoLayerClient *client = mLayerClient;
     if (!client)
         return;
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -366,17 +366,17 @@ public:
     already_AddRefed<nsIMobileMessageCallback> DequeueSmsRequest(uint32_t aRequestId);
 
     bool IsTablet();
 
     void GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo);
     void EnableNetworkNotifications();
     void DisableNetworkNotifications();
 
-    void SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const LayerIntRect& aPageRect, const CSSRect& aCssPageRect);
+    void SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, 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 CSSRect& aDisplayPort, float aDisplayResolution,
                           bool aIsFirstPaint, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset);
 
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -346,17 +346,17 @@ AndroidRectF::InitRectFClass(JNIEnv *jEn
 
 void
 AndroidGeckoLayerClient::InitGeckoLayerClientClass(JNIEnv *jEnv)
 {
     initInit();
 
     jGeckoLayerClientClass = getClassGlobalRef("org/mozilla/gecko/gfx/GeckoLayerClient");
 
-    jSetFirstPaintViewport = getMethod("setFirstPaintViewport", "(FFFFFFFFFFF)V");
+    jSetFirstPaintViewport = getMethod("setFirstPaintViewport", "(FFFFFFF)V");
     jSetPageRect = getMethod("setPageRect", "(FFFF)V");
     jSyncViewportInfoMethod = getMethod("syncViewportInfo",
                                         "(IIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;");
     jSyncFrameMetricsMethod = getMethod("syncFrameMetrics",
                                         "(FFFFFFFZIIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;");
     jCreateFrameMethod = getMethod("createFrame", "()Lorg/mozilla/gecko/gfx/LayerRenderer$Frame;");
     jActivateProgramMethod = getMethod("activateProgram", "()V");
     jDeactivateProgramMethod = getMethod("deactivateProgram", "()V");
@@ -858,26 +858,25 @@ AndroidViewTransform::Init(jobject jobj)
 void
 AndroidProgressiveUpdateData::Init(jobject jobj)
 {
     NS_ABORT_IF_FALSE(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!");
     wrapped_obj = jobj;
 }
 
 void
-AndroidGeckoLayerClient::SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const LayerIntRect& aPageRect, const CSSRect& aCssPageRect)
+AndroidGeckoLayerClient::SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const CSSRect& aCssPageRect)
 {
     NS_ASSERTION(!isNull(), "SetFirstPaintViewport called on null layer client!");
     JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env, 0);
     return env->CallVoidMethod(wrapped_obj, jSetFirstPaintViewport, (float)aOffset.x, (float)aOffset.y, aZoom,
-                               (float)aPageRect.x, (float)aPageRect.y, (float)aPageRect.XMost(), (float)aPageRect.YMost(),
                                aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
 }
 
 void
 AndroidGeckoLayerClient::SetPageRect(const CSSRect& aCssPageRect)
 {
     NS_ASSERTION(!isNull(), "SetPageRect called on null layer client!");
     JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
--- a/widget/android/AndroidJavaWrappers.h
+++ b/widget/android/AndroidJavaWrappers.h
@@ -264,17 +264,17 @@ class AndroidGeckoLayerClient : public W
 public:
     static void InitGeckoLayerClientClass(JNIEnv *jEnv);
 
     void Init(jobject jobj);
 
     AndroidGeckoLayerClient() {}
     AndroidGeckoLayerClient(jobject jobj) { Init(jobj); }
 
-    void SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const LayerIntRect& aPageRect, const CSSRect& aCssPageRect);
+    void SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, 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 CSSRect& aDisplayPort, float aDisplayResolution,
                           bool aIsFirstPaint, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset);
     bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);