Backed out 11 changesets (bug 783368) because of build bustage on a CLOSED TREE
authorEhsan Akhgari <ehsan@mozilla.com>
Wed, 21 Nov 2012 14:57:02 -0500
changeset 113923 8f61af76095066558acb9018551dc0b0b5a90f72
parent 113922 b7ee5158465d7705aa80ab16cfe9a686ef53ff35
child 113924 4b01f63ea852e74b7d27e4e0810b3c24bfe12b12
child 113957 20ec9014f220c96a0434a4043f5a5cabb0cd5e37
push id18458
push usereakhgari@mozilla.com
push dateWed, 21 Nov 2012 19:57:14 +0000
treeherdermozilla-inbound@8f61af760950 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs783368
milestone20.0a1
backs out2bc4310263c4b0c042d4d7114b36f6e9bfe32005
a35c83a8d99d4eea4fd8f0049a9751b37bfb27a0
afb9b2a661bac36ebfcbb4b237f5f25332a10f5e
3926f510f9be7ccdce07853b6a203ae49473c032
9d1fe200ff871c4169384d9afd03377565b99005
b6e4f88f5730586e6bafe9043cdc90eb5f655ac3
bc53f7dba7c69e3b5be18adb02fed396bb2ff643
1948fa2fccc1d8a0aef263ab98631a01af7abc0e
9af163388fd174a63ba115e2f50690a08533bfae
7a2256e1aa7cfe217356d28f127f3ffa3705a73c
4da1958a9885e35c58f914ddf458e5bd43468c91
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 11 changesets (bug 783368) because of build bustage on a CLOSED TREE Backed out changeset 2bc4310263c4 (bug 783368) Backed out changeset a35c83a8d99d (bug 783368) Backed out changeset afb9b2a661ba (bug 783368) Backed out changeset 3926f510f9be (bug 783368) Backed out changeset 9d1fe200ff87 (bug 783368) Backed out changeset b6e4f88f5730 (bug 783368) Backed out changeset bc53f7dba7c6 (bug 783368) Backed out changeset 1948fa2fccc1 (bug 783368) Backed out changeset 9af163388fd1 (bug 783368) Backed out changeset 7a2256e1aa7c (bug 783368) Backed out changeset 4da1958a9885 (bug 783368)
content/base/src/nsGkAtomList.h
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
gfx/layers/FrameMetrics.h
gfx/layers/TiledLayerBuffer.h
gfx/layers/basic/BasicLayerManager.cpp
gfx/layers/basic/BasicLayers.h
gfx/layers/basic/BasicTiledThebesLayer.cpp
gfx/layers/basic/BasicTiledThebesLayer.h
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/opengl/ReusableTileStoreOGL.cpp
gfx/layers/opengl/TiledThebesLayerOGL.cpp
gfx/layers/opengl/TiledThebesLayerOGL.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
ipc/glue/IPCMessageUtils.h
layout/base/nsDisplayList.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
mobile/android/app/mobile.js
mobile/android/base/gfx/GeckoLayerClient.java
mobile/android/base/gfx/ProgressiveUpdateData.java
mobile/android/chrome/content/browser.js
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/AndroidJavaWrappers.cpp
widget/android/AndroidJavaWrappers.h
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1940,17 +1940,16 @@ GK_ATOM(el, "el")
 GK_ATOM(TypingTxnName, "Typing")
 GK_ATOM(IMETxnName, "IME")
 GK_ATOM(DeleteTxnName, "Deleting")
 
 // IPC stuff
 GK_ATOM(Remote, "remote")
 GK_ATOM(RemoteId, "_remote_id")
 GK_ATOM(DisplayPort, "_displayport")
-GK_ATOM(CriticalDisplayPort, "_critical_displayport")
 
 // Names for system metrics
 GK_ATOM(scrollbar_start_backward, "scrollbar-start-backward")
 GK_ATOM(scrollbar_start_forward, "scrollbar-start-forward")
 GK_ATOM(scrollbar_end_backward, "scrollbar-end-backward")
 GK_ATOM(scrollbar_end_forward, "scrollbar-end-forward")
 GK_ATOM(scrollbar_thumb_proportional, "scrollbar-thumb-proportional")
 GK_ATOM(images_in_menus, "images-in-menus")
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -398,64 +398,16 @@ nsDOMWindowUtils::SetDisplayPortForEleme
       }
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMWindowUtils::SetCriticalDisplayPortForElement(float aXPx, float aYPx,
-                                                   float aWidthPx, float aHeightPx,
-                                                   nsIDOMElement* aElement)
-{
-  if (!nsContentUtils::IsCallerChrome()) {
-    return NS_ERROR_DOM_SECURITY_ERR;
-  }
-
-  nsIPresShell* presShell = GetPresShell();
-  if (!presShell) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (!aElement) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
-
-  if (!content) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  if (content->GetCurrentDoc() != presShell->GetDocument()) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  nsRect displayport;
-  if (!nsLayoutUtils::GetDisplayPort(content, &displayport)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  nsRect criticalDisplayport(nsPresContext::CSSPixelsToAppUnits(aXPx),
-                             nsPresContext::CSSPixelsToAppUnits(aYPx),
-                             nsPresContext::CSSPixelsToAppUnits(aWidthPx),
-                             nsPresContext::CSSPixelsToAppUnits(aHeightPx));
-  content->SetProperty(nsGkAtoms::CriticalDisplayPort, new nsRect(criticalDisplayport),
-                       DestroyNsRect);
-
-  nsIFrame* rootFrame = presShell->GetRootFrame();
-  if (rootFrame) {
-    rootFrame->InvalidateFrame();
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsDOMWindowUtils::SetResolution(float aXResolution, float aYResolution)
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsIPresShell* presShell = GetPresShell();
   return presShell ? presShell->SetResolution(aXResolution, aYResolution)
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -144,28 +144,16 @@ interface nsIDOMWindowUtils : nsISupport
    * calling this so that duplicate sets are not made with the same
    * displayport.
    */
   void setDisplayPortForElement(in float aXPx, in float aYPx,
                                 in float aWidthPx, in float aHeightPx,
                                 in nsIDOMElement aElement);
 
   /**
-   * When a display port is set, this allows a sub-section of that
-   * display port to be marked as 'critical'. In this scenario, the
-   * area outside of this rectangle may be rendered at a lower
-   * detail (for example, by reducing its resolution), or not rendered
-   * at all under some circumstances.
-   * This call will have no effect if a display port has not been set.
-   */
-  void setCriticalDisplayPortForElement(in float aXPx, in float aYPx,
-                                        in float aWidthPx, in float aHeightPx,
-                                        in nsIDOMElement aElement);
-
-  /**
    * Get/set the resolution at which rescalable web content is drawn.
    * Currently this is only (some) thebes content.
    *
    * Setting a new resolution does *not* trigger reflow.  This API is
    * entirely separate from textZoom and fullZoom; a resolution scale
    * can be applied together with both textZoom and fullZoom.
    *
    * The effect of is API for gfx code to allocate more or fewer
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -28,17 +28,16 @@ public:
   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)
     , mDevPixelsPerCSSPixel(1)
     , mMayHaveTouchListeners(false)
@@ -46,17 +45,16 @@ public:
 
   // 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 &&
            mMayHaveTouchListeners == aOther.mMayHaveTouchListeners;
   }
@@ -146,24 +144,16 @@ public:
   // 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;
 
-  // 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;
-
   // 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
   // iframe. For layers that don't correspond to a document, this metric is
--- a/gfx/layers/TiledLayerBuffer.h
+++ b/gfx/layers/TiledLayerBuffer.h
@@ -24,19 +24,17 @@ namespace mozilla {
 namespace layers {
 
 // An abstract implementation of a tile buffer. This code covers the logic of
 // moving and reusing tiles and leaves the validation up to the implementor. To
 // avoid the overhead of virtual dispatch, we employ the curiously recurring
 // template pattern.
 //
 // Tiles are aligned to a grid with one of the grid points at (0,0) and other
-// grid points spaced evenly in the x- and y-directions by GetTileLength()
-// multiplied by mResolution. GetScaledTileLength() provides convenience for
-// accessing these values.
+// grid points spaced evenly in the x- and y-directions by GetTileLength().
 //
 // This tile buffer stores a valid region, which defines the areas that have
 // up-to-date content. The contents of tiles within this region will be reused
 // from paint to paint. It also stores the region that was modified in the last
 // paint operation; this is useful when one tiled layer buffer shadows another
 // (as in an off-main-thread-compositing scenario), so that the shadow tiled
 // layer buffer can correctly reflect the updates of the master layer buffer.
 //
@@ -63,115 +61,87 @@ namespace layers {
 //
 //   void ReleaseTile(Tile aTile);
 //
 //   Destroys the given tile.
 //
 //   void SwapTiles(Tile& aTileA, Tile& aTileB);
 //
 //   Swaps two tiles.
-//
-// The contents of the tile buffer will be rendered at the resolution specified
-// in mResolution, which can be altered with SetResolution. The resolution
-// should always be a factor of the tile length, to avoid tiles covering
-// non-integer amounts of pixels.
 
 template<typename Derived, typename Tile>
 class TiledLayerBuffer
 {
 public:
   TiledLayerBuffer()
     : mRetainedWidth(0)
     , mRetainedHeight(0)
-    , mResolution(1)
   {}
 
   ~TiledLayerBuffer() {}
 
-  // Given a tile origin aligned to a multiple of GetScaledTileLength,
+  // Given a tile origin aligned to a multiple of GetTileLength(),
   // return the tile that describes that region.
   // NOTE: To get the valid area of that tile you must intersect
-  //       (aTileOrigin.x, aTileOrigin.y,
-  //        GetScaledTileLength(), GetScaledTileLength())
+  //       (aTileOrigin.x, aTileOrigin.y, GetTileLength(), GetTileLength())
   //       and GetValidRegion() to get the area of the tile that is valid.
   Tile GetTile(const nsIntPoint& aTileOrigin) const;
 
   // Given a tile x, y relative to the top left of the layer, this function
   // will return the tile for
-  // (x*GetScaledTileLength(), y*GetScaledTileLength(),
-  //  GetScaledTileLength(), GetScaledTileLength())
+  // (x*GetTileLength(), y*GetTileLength(), GetTileLength(), GetTileLength())
   Tile GetTile(int x, int y) const;
 
   // This operates the same as GetTile(aTileOrigin), but will also replace the
   // specified tile with the placeholder tile. This does not call ReleaseTile
   // on the removed tile.
   bool RemoveTile(const nsIntPoint& aTileOrigin, Tile& aRemovedTile);
 
   // This operates the same as GetTile(x, y), but will also replace the
   // specified tile with the placeholder tile. This does not call ReleaseTile
   // on the removed tile.
   bool RemoveTile(int x, int y, Tile& aRemovedTile);
 
   uint16_t GetTileLength() const { return TILEDLAYERBUFFER_TILE_SIZE; }
-  uint32_t GetScaledTileLength() const { return roundf(TILEDLAYERBUFFER_TILE_SIZE / mResolution); }
 
   unsigned int GetTileCount() const { return mRetainedTiles.Length(); }
 
   const nsIntRegion& GetValidRegion() const { return mValidRegion; }
   const nsIntRegion& GetPaintedRegion() const { return mPaintedRegion; }
   void ClearPaintedRegion() { mPaintedRegion.SetEmpty(); }
 
   // Given a position i, this function returns the position inside the current tile.
   int GetTileStart(int i) const {
-    return (i >= 0) ? (i % GetScaledTileLength())
-                    : ((GetScaledTileLength() - (-i % GetScaledTileLength())) %
-                       GetScaledTileLength());
+    return (i >= 0) ? (i % GetTileLength())
+                    : ((GetTileLength() - (-i % GetTileLength())) % GetTileLength());
   }
 
   // Rounds the given coordinate down to the nearest tile boundary.
   int RoundDownToTileEdge(int aX) const { return aX - GetTileStart(aX); }
 
-  // Get and set draw scaling. mResolution affects the resolution at which the
-  // contents of the buffer are drawn. mResolution has no effect on the
-  // coordinate space of the valid region, but does affect the size of an
-  // individual tile's rect in relation to the valid region.
-  // Setting the resolution will invalidate the buffer.
-  float GetResolution() const { return mResolution; }
-  void SetResolution(float aResolution) {
-    if (mResolution == aResolution) {
-      return;
-    }
-
-    Update(nsIntRegion(), nsIntRegion());
-    mResolution = aResolution;
-  }
-  bool IsLowPrecision() const { return mResolution < 1; }
-
 protected:
   // The implementor should call Update() to change
   // the new valid region. This implementation will call
   // validateTile on each tile that is dirty, which is left
   // to the implementor.
   void Update(const nsIntRegion& aNewValidRegion, const nsIntRegion& aPaintRegion);
 
   nsIntRegion     mValidRegion;
   nsIntRegion     mPaintedRegion;
 
   /**
    * mRetainedTiles is a rectangular buffer of mRetainedWidth x mRetainedHeight
    * stored as column major with the same origin as mValidRegion.GetBounds().
    * Any tile that does not intersect mValidRegion is a PlaceholderTile.
    * Only the region intersecting with mValidRegion should be read from a tile,
-   * another other region is assumed to be uninitialized. The contents of the
-   * tiles is scaled by mResolution.
+   * another other region is assumed to be uninitialized.
    */
   nsTArray<Tile>  mRetainedTiles;
   int             mRetainedWidth;  // in tiles
   int             mRetainedHeight; // in tiles
-  float           mResolution;
 
 private:
   const Derived& AsDerived() const { return *static_cast<const Derived*>(this); }
   Derived& AsDerived() { return *static_cast<Derived*>(this); }
 
   bool IsPlaceholder(Tile aTile) const { return aTile == AsDerived().GetPlaceholderTile(); }
 };
 
@@ -212,37 +182,37 @@ static inline int floor_div(int a, int b
 }
 
 template<typename Derived, typename Tile> Tile
 TiledLayerBuffer<Derived, Tile>::GetTile(const nsIntPoint& aTileOrigin) const
 {
   // TODO Cache firstTileOriginX/firstTileOriginY
   // Find the tile x/y of the first tile and the target tile relative to the (0, 0)
   // origin, the difference is the tile x/y relative to the start of the tile buffer.
-  int firstTileX = floor_div(mValidRegion.GetBounds().x, GetScaledTileLength());
-  int firstTileY = floor_div(mValidRegion.GetBounds().y, GetScaledTileLength());
-  return GetTile(floor_div(aTileOrigin.x, GetScaledTileLength()) - firstTileX,
-                 floor_div(aTileOrigin.y, GetScaledTileLength()) - firstTileY);
+  int firstTileX = floor_div(mValidRegion.GetBounds().x, GetTileLength());
+  int firstTileY = floor_div(mValidRegion.GetBounds().y, GetTileLength());
+  return GetTile(floor_div(aTileOrigin.x, GetTileLength()) - firstTileX,
+                 floor_div(aTileOrigin.y, GetTileLength()) - firstTileY);
 }
 
 template<typename Derived, typename Tile> Tile
 TiledLayerBuffer<Derived, Tile>::GetTile(int x, int y) const
 {
   int index = x * mRetainedHeight + y;
   return mRetainedTiles.SafeElementAt(index, AsDerived().GetPlaceholderTile());
 }
 
 template<typename Derived, typename Tile> bool
 TiledLayerBuffer<Derived, Tile>::RemoveTile(const nsIntPoint& aTileOrigin,
                                             Tile& aRemovedTile)
 {
-  int firstTileX = floor_div(mValidRegion.GetBounds().x, GetScaledTileLength());
-  int firstTileY = floor_div(mValidRegion.GetBounds().y, GetScaledTileLength());
-  return RemoveTile(floor_div(aTileOrigin.x, GetScaledTileLength()) - firstTileX,
-                    floor_div(aTileOrigin.y, GetScaledTileLength()) - firstTileY,
+  int firstTileX = floor_div(mValidRegion.GetBounds().x, GetTileLength());
+  int firstTileY = floor_div(mValidRegion.GetBounds().y, GetTileLength());
+  return RemoveTile(floor_div(aTileOrigin.x, GetTileLength()) - firstTileX,
+                    floor_div(aTileOrigin.y, GetTileLength()) - firstTileY,
                     aRemovedTile);
 }
 
 template<typename Derived, typename Tile> bool
 TiledLayerBuffer<Derived, Tile>::RemoveTile(int x, int y, Tile& aRemovedTile)
 {
   int index = x * mRetainedHeight + y;
   const Tile& tileToRemove = mRetainedTiles.SafeElementAt(index, AsDerived().GetPlaceholderTile());
@@ -276,35 +246,35 @@ TiledLayerBuffer<Derived, Tile>::Update(
   // which we will allocate in pass 2.
   // TODO: Add a tile pool to reduce new allocation
   int tileX = 0;
   int tileY = 0;
   // Iterate over the new drawing bounds in steps of tiles.
   for (int32_t x = newBound.x; x < newBound.XMost(); tileX++) {
     // Compute tileRect(x,y,width,height) in layer space coordinate
     // giving us the rect of the tile that hits the newBounds.
-    int width = GetScaledTileLength() - GetTileStart(x);
+    int width = GetTileLength() - GetTileStart(x);
     if (x + width > newBound.XMost()) {
       width = newBound.x + newBound.width - x;
     }
 
     tileY = 0;
     for (int32_t y = newBound.y; y < newBound.YMost(); tileY++) {
-      int height = GetScaledTileLength() - GetTileStart(y);
+      int height = GetTileLength() - GetTileStart(y);
       if (y + height > newBound.y + newBound.height) {
         height = newBound.y + newBound.height - y;
       }
 
       const nsIntRect tileRect(x,y,width,height);
       if (oldValidRegion.Intersects(tileRect) && newValidRegion.Intersects(tileRect)) {
         // This old tiles contains some valid area so move it to the new tile
         // buffer. Replace the tile in the old buffer with a placeholder
         // to leave the old buffer index unaffected.
-        int tileX = floor_div(x - oldBufferOrigin.x, GetScaledTileLength());
-        int tileY = floor_div(y - oldBufferOrigin.y, GetScaledTileLength());
+        int tileX = floor_div(x - oldBufferOrigin.x, GetTileLength());
+        int tileY = floor_div(y - oldBufferOrigin.y, GetTileLength());
         int index = tileX * oldRetainedHeight + tileY;
 
         // The tile may have been removed, skip over it in this case.
         if (IsPlaceholder(oldRetainedTiles.
                           SafeElementAt(index, AsDerived().GetPlaceholderTile()))) {
           newRetainedTiles.AppendElement(AsDerived().GetPlaceholderTile());
         } else {
           Tile tileWithPartialValidContent = oldRetainedTiles[index];
@@ -353,52 +323,52 @@ TiledLayerBuffer<Derived, Tile>::Update(
   tileX = 0;
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   printf_stderr("Update %i, %i, %i, %i\n", newBound.x, newBound.y, newBound.width, newBound.height);
 #endif
   for (int x = newBound.x; x < newBound.x + newBound.width; tileX++) {
     // Compute tileRect(x,y,width,height) in layer space coordinate
     // giving us the rect of the tile that hits the newBounds.
     int tileStartX = RoundDownToTileEdge(x);
-    int width = GetScaledTileLength() - GetTileStart(x);
+    int width = GetTileLength() - GetTileStart(x);
     if (x + width > newBound.XMost())
       width = newBound.XMost() - x;
 
     tileY = 0;
     for (int y = newBound.y; y < newBound.y + newBound.height; tileY++) {
       int tileStartY = RoundDownToTileEdge(y);
-      int height = GetScaledTileLength() - GetTileStart(y);
+      int height = GetTileLength() - GetTileStart(y);
       if (y + height > newBound.YMost()) {
         height = newBound.YMost() - y;
       }
 
       const nsIntRect tileRect(x, y, width, height);
 
       nsIntRegion tileDrawRegion;
       tileDrawRegion.And(tileRect, regionToPaint);
 
       if (tileDrawRegion.IsEmpty()) {
         // We have a tile but it doesn't hit the draw region
         // because we can reuse all of the content from the
         // previous buffer.
 #ifdef DEBUG
-        int currTileX = floor_div(x - newBufferOrigin.x, GetScaledTileLength());
-        int currTileY = floor_div(y - newBufferOrigin.y, GetScaledTileLength());
+        int currTileX = floor_div(x - newBufferOrigin.x, GetTileLength());
+        int currTileY = floor_div(y - newBufferOrigin.y, GetTileLength());
         int index = currTileX * mRetainedHeight + currTileY;
         NS_ABORT_IF_FALSE(!newValidRegion.Intersects(tileRect) ||
                           !IsPlaceholder(newRetainedTiles.
                                          SafeElementAt(index, AsDerived().GetPlaceholderTile())),
                           "If we don't draw a tile we shouldn't have a placeholder there.");
 #endif
         y += height;
         continue;
       }
 
-      int tileX = floor_div(x - newBufferOrigin.x, GetScaledTileLength());
-      int tileY = floor_div(y - newBufferOrigin.y, GetScaledTileLength());
+      int tileX = floor_div(x - newBufferOrigin.x, GetTileLength());
+      int tileY = floor_div(y - newBufferOrigin.y, GetTileLength());
       int index = tileX * mRetainedHeight + tileY;
       NS_ABORT_IF_FALSE(index >= 0 &&
                         static_cast<unsigned>(index) < newRetainedTiles.Length(),
                         "index out of range");
 
       Tile newTile = newRetainedTiles[index];
       while (IsPlaceholder(newTile) && oldRetainedTiles.Length() > 0) {
         AsDerived().SwapTiles(newTile, oldRetainedTiles[oldRetainedTiles.Length()-1]);
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -1294,39 +1294,35 @@ BasicShadowLayerManager::ClearCachedReso
   }
   BasicLayerManager::ClearCachedResources(aSubtree);
 }
 
 bool
 BasicShadowLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
                                                    gfx::Rect& aViewport,
                                                    float& aScaleX,
-                                                   float& aScaleY,
-                                                   bool aDrawingCritical)
+                                                   float& aScaleY)
 {
 #ifdef MOZ_WIDGET_ANDROID
   Layer* primaryScrollable = GetPrimaryScrollableLayer();
   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 =
-      (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);
+    gfx::Rect displayPort((metrics.mDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX,
+                          (metrics.mDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY,
+                          metrics.mDisplayPort.width * devPixelRatioX,
+                          metrics.mDisplayPort.height * devPixelRatioY);
 
     return AndroidBridge::Bridge()->ProgressiveUpdateCallback(
-      aHasPendingNewThebesContent, displayPort, devPixelRatioX, aDrawingCritical,
+      aHasPendingNewThebesContent, displayPort, devPixelRatioX,
       aViewport, aScaleX, aScaleY);
   }
 #endif
 
   return false;
 }
 
 already_AddRefed<ThebesLayer>
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -271,36 +271,33 @@ public:
 
   virtual void SetIsFirstPaint() MOZ_OVERRIDE;
 
   // Drop cached resources and ask our shadow manager to do the same,
   // if we have one.
   virtual void ClearCachedResources(Layer* aSubtree = nullptr) MOZ_OVERRIDE;
 
   void SetRepeatTransaction() { mRepeatTransaction = true; }
-  bool GetRepeatTransaction() { return mRepeatTransaction; }
 
   bool IsRepeatTransaction() { return mIsRepeatTransaction; }
 
   /**
    * Called for each iteration of a progressive tile update. Fills
    * aViewport, aScaleX and aScaleY with the current scale and viewport
    * being used to composite the layers in this manager, to determine what area
-   * intersects with the target render rectangle. aDrawingCritical will be
-   * true if the current drawing operation is using the critical displayport.
+   * intersects with the target render rectangle.
    * Returns true if the update should continue, or false if it should be
    * cancelled.
    * This is only called if gfxPlatform::UseProgressiveTilePainting() returns
    * true.
    */
   bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
                                  gfx::Rect& aViewport,
                                  float& aScaleX,
-                                 float& aScaleY,
-                                 bool aDrawingCritical);
+                                 float& aScaleY);
 
 private:
   /**
    * Forward transaction results to the parent context.
    */
   void ForwardTransaction();
 
   // The bounds of |mTarget| in device pixels.
--- a/gfx/layers/basic/BasicTiledThebesLayer.cpp
+++ b/gfx/layers/basic/BasicTiledThebesLayer.cpp
@@ -100,25 +100,21 @@ BasicTiledLayerBuffer::PaintThebes(Basic
                            GetTileStart(paintBounds.y) !=
                            GetTileStart(paintBounds.YMost() - 1);
   }
 
   if (useSinglePaintBuffer) {
     const nsIntRect bounds = aPaintRegion.GetBounds();
     {
       SAMPLE_LABEL("BasicTiledLayerBuffer", "PaintThebesSingleBufferAlloc");
-      mSinglePaintBuffer = new gfxImageSurface(
-        gfxIntSize(ceilf(bounds.width * mResolution),
-                   ceilf(bounds.height * mResolution)),
-        GetFormat(), !aLayer->CanUseOpaqueSurface());
+      mSinglePaintBuffer = new gfxImageSurface(gfxIntSize(bounds.width, bounds.height), GetFormat(), !aLayer->CanUseOpaqueSurface());
       mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y);
     }
     nsRefPtr<gfxContext> ctxt = new gfxContext(mSinglePaintBuffer);
     ctxt->NewPath();
-    ctxt->Scale(mResolution, mResolution);
     ctxt->Translate(gfxPoint(-bounds.x, -bounds.y));
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
     if (PR_IntervalNow() - start > 3) {
       printf_stderr("Slow alloc %i\n", PR_IntervalNow() - start);
     }
     start = PR_IntervalNow();
 #endif
     SAMPLE_LABEL("BasicTiledLayerBuffer", "PaintThebesSingleBufferDraw");
@@ -164,53 +160,44 @@ BasicTiledLayerBuffer::ValidateTileInter
                                             const nsIntRect& aDirtyRect)
 {
   if (aTile == GetPlaceholderTile() || aTile.mSurface->Format() != GetFormat()) {
     gfxImageSurface* tmpTile = new gfxImageSurface(gfxIntSize(GetTileLength(), GetTileLength()),
                                                    GetFormat(), !mThebesLayer->CanUseOpaqueSurface());
     aTile = BasicTiledLayerTile(tmpTile);
   }
 
+  gfxRect drawRect(aDirtyRect.x - aTileOrigin.x, aDirtyRect.y - aTileOrigin.y,
+                   aDirtyRect.width, aDirtyRect.height);
+
   // Use the gfxReusableSurfaceWrapper, which will reuse the surface
   // if the compositor no longer has a read lock, otherwise the surface
   // will be copied into a new writable surface.
   gfxImageSurface* writableSurface;
   aTile.mSurface = aTile.mSurface->GetWritable(&writableSurface);
 
   // Bug 742100, this gfxContext really should live on the stack.
   nsRefPtr<gfxContext> ctxt = new gfxContext(writableSurface);
-
   if (mSinglePaintBuffer) {
-    gfxRect drawRect(aDirtyRect.x - aTileOrigin.x, aDirtyRect.y - aTileOrigin.y,
-                     aDirtyRect.width, aDirtyRect.height);
-
     ctxt->SetOperator(gfxContext::OPERATOR_SOURCE);
     ctxt->NewPath();
     ctxt->SetSource(mSinglePaintBuffer.get(),
-                    gfxPoint((mSinglePaintBufferOffset.x - aDirtyRect.x + drawRect.x) *
-                             mResolution,
-                             (mSinglePaintBufferOffset.y - aDirtyRect.y + drawRect.y) *
-                             mResolution));
-    drawRect.Scale(mResolution, mResolution);
+                    gfxPoint(mSinglePaintBufferOffset.x - aDirtyRect.x + drawRect.x,
+                             mSinglePaintBufferOffset.y - aDirtyRect.y + drawRect.y));
     ctxt->Rectangle(drawRect, true);
     ctxt->Fill();
   } else {
     ctxt->NewPath();
-    ctxt->Scale(mResolution, mResolution);
     ctxt->Translate(gfxPoint(-aTileOrigin.x, -aTileOrigin.y));
-    nsIntPoint a = nsIntPoint(aTileOrigin.x, aTileOrigin.y);
-    mCallback(mThebesLayer, ctxt,
-              nsIntRegion(nsIntRect(a, nsIntSize(GetScaledTileLength(),
-                                                 GetScaledTileLength()))),
-              nsIntRegion(), mCallbackData);
+    nsIntPoint a = aTileOrigin;
+    mCallback(mThebesLayer, ctxt, nsIntRegion(nsIntRect(a, nsIntSize(GetTileLength(), GetTileLength()))), nsIntRegion(), mCallbackData);
   }
 
 #ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
-  DrawDebugOverlay(writableSurface, aTileOrigin.x * mResolution,
-                   aTileOrigin.y * mResolution);
+  DrawDebugOverlay(writableSurface, aTileOrigin.x, aTileOrigin.y);
 #endif
 
   return aTile;
 }
 
 BasicTiledLayerTile
 BasicTiledLayerBuffer::ValidateTile(BasicTiledLayerTile aTile,
                                     const nsIntPoint& aTileOrigin,
@@ -259,103 +246,88 @@ RoundedTransformViewportBounds(const gfx
 
   return nsIntRect((int32_t)floor(transformedViewport.x),
                    (int32_t)floor(transformedViewport.y),
                    (int32_t)ceil(transformedViewport.width),
                    (int32_t)ceil(transformedViewport.height));
 }
 
 bool
-BasicTiledThebesLayer::ComputeProgressiveUpdateRegion(BasicTiledLayerBuffer& aTiledBuffer,
-                                                      const nsIntRegion& aInvalidRegion,
+BasicTiledThebesLayer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
                                                       const nsIntRegion& aOldValidRegion,
                                                       nsIntRegion& aRegionToPaint,
                                                       const gfx3DMatrix& aTransform,
-                                                      const nsIntRect& aCompositionBounds,
                                                       const gfx::Point& aScrollOffset,
                                                       const gfxSize& aResolution,
                                                       bool aIsRepeated)
 {
   aRegionToPaint = aInvalidRegion;
 
-  // If this is a low precision buffer, we force progressive updates. The
-  // assumption is that the contents is less important, so visual coherency
-  // is lower priority than speed.
-  bool drawingLowPrecision = aTiledBuffer.IsLowPrecision();
-
   // Find out if we have any non-stale content to update.
-  nsIntRegion staleRegion;
-  staleRegion.And(aInvalidRegion, aOldValidRegion);
+  nsIntRegion freshRegion;
+  if (!mFirstPaint) {
+    freshRegion.And(aInvalidRegion, aOldValidRegion);
+    freshRegion.Sub(aInvalidRegion, freshRegion);
+  }
 
   // Find out the current view transform to determine which tiles to draw
   // first, and see if we should just abort this paint. Aborting is usually
   // caused by there being an incoming, more relevant paint.
   gfx::Rect viewport;
   float scaleX, scaleY;
-  if (BasicManager()->ProgressiveUpdateCallback(!staleRegion.Contains(aInvalidRegion),
-                                                viewport,
-                                                scaleX, scaleY, !drawingLowPrecision)) {
+  if (BasicManager()->ProgressiveUpdateCallback(!freshRegion.IsEmpty(), viewport, scaleX, scaleY)) {
     SAMPLE_MARKER("Abort painting");
     aRegionToPaint.SetEmpty();
     return aIsRepeated;
   }
 
   // Transform the screen coordinates into local layer coordinates.
   nsIntRect roundedTransformedViewport =
     RoundedTransformViewportBounds(viewport, aScrollOffset, aResolution,
                                    scaleX, scaleY, aTransform);
 
-  // Paint tiles that have stale content or that intersected with the screen
-  // at the time of issuing the draw command in a single transaction first.
-  // This is to avoid rendering glitches on animated page content, and when
-  // layers change size/shape.
-  nsIntRect criticalViewportRect = roundedTransformedViewport.Intersect(aCompositionBounds);
-  aRegionToPaint.And(aInvalidRegion, criticalViewportRect);
-  aRegionToPaint.Or(aRegionToPaint, staleRegion);
-  bool drawingStale = !aRegionToPaint.IsEmpty();
+  // Paint tiles that have no content before tiles that only have stale content.
+  bool drawingStale = freshRegion.IsEmpty();
   if (!drawingStale) {
-    aRegionToPaint = aInvalidRegion;
+    aRegionToPaint = freshRegion;
   }
 
   // Prioritise tiles that are currently visible on the screen.
   bool paintVisible = false;
   if (aRegionToPaint.Intersects(roundedTransformedViewport)) {
     aRegionToPaint.And(aRegionToPaint, roundedTransformedViewport);
     paintVisible = true;
   }
 
-  // Paint area that's visible and overlaps previously valid content to avoid
-  // visible glitches in animated elements, such as gifs.
-  bool paintInSingleTransaction = paintVisible && (drawingStale || mFirstPaint);
-
   // The following code decides what order to draw tiles in, based on the
   // current scroll direction of the primary scrollable layer.
   NS_ASSERTION(!aRegionToPaint.IsEmpty(), "Unexpectedly empty paint region!");
   nsIntRect paintBounds = aRegionToPaint.GetBounds();
 
   int startX, incX, startY, incY;
-  int tileLength = aTiledBuffer.GetScaledTileLength();
   if (aScrollOffset.x >= mLastScrollOffset.x) {
-    startX = aTiledBuffer.RoundDownToTileEdge(paintBounds.x);
-    incX = tileLength;
+    startX = mTiledBuffer.RoundDownToTileEdge(paintBounds.x);
+    incX = mTiledBuffer.GetTileLength();
   } else {
-    startX = aTiledBuffer.RoundDownToTileEdge(paintBounds.XMost() - 1);
-    incX = -tileLength;
+    startX = mTiledBuffer.RoundDownToTileEdge(paintBounds.XMost() - 1);
+    incX = -mTiledBuffer.GetTileLength();
   }
 
   if (aScrollOffset.y >= mLastScrollOffset.y) {
-    startY = aTiledBuffer.RoundDownToTileEdge(paintBounds.y);
-    incY = tileLength;
+    startY = mTiledBuffer.RoundDownToTileEdge(paintBounds.y);
+    incY = mTiledBuffer.GetTileLength();
   } else {
-    startY = aTiledBuffer.RoundDownToTileEdge(paintBounds.YMost() - 1);
-    incY = -tileLength;
+    startY = mTiledBuffer.RoundDownToTileEdge(paintBounds.YMost() - 1);
+    incY = -mTiledBuffer.GetTileLength();
   }
 
   // Find a tile to draw.
-  nsIntRect tileBounds(startX, startY, tileLength, tileLength);
+  nsIntRect tileBounds(startX, startY,
+                       mTiledBuffer.GetTileLength(),
+                       mTiledBuffer.GetTileLength());
   int32_t scrollDiffX = aScrollOffset.x - mLastScrollOffset.x;
   int32_t scrollDiffY = aScrollOffset.y - mLastScrollOffset.y;
   // This loop will always terminate, as there is at least one tile area
   // along the first/last row/column intersecting with regionToPaint, or its
   // bounds would have been smaller.
   while (true) {
     aRegionToPaint.And(aInvalidRegion, tileBounds);
     if (!aRegionToPaint.IsEmpty()) {
@@ -368,85 +340,33 @@ BasicTiledThebesLayer::ComputeProgressiv
     }
   }
 
   bool repeatImmediately = false;
   if (!aRegionToPaint.Contains(aInvalidRegion)) {
     // The region needed to paint is larger then our progressive chunk size
     // therefore update what we want to paint and ask for a new paint transaction.
 
-    // If we need to draw more than one tile to maintain coherency, make
-    // sure it happens in the same transaction by requesting this work be
-    // repeated immediately.
-    // If this is unnecessary, the remaining work will be done tile-by-tile in
-    // subsequent transactions.
-    if (!drawingLowPrecision && paintInSingleTransaction) {
+    // If we're drawing stale, visible content, make sure that it happens
+    // in one go by repeating this work without calling the painted
+    // callback. The remaining content is then drawn tile-by-tile in
+    // multiple transactions.
+    if (paintVisible && drawingStale) {
       repeatImmediately = true;
     } else {
       BasicManager()->SetRepeatTransaction();
     }
+  } else {
+    // The transaction is completed, store the last scroll offset.
+    mLastScrollOffset = aScrollOffset;
   }
 
   return repeatImmediately;
 }
 
-bool
-BasicTiledThebesLayer::ProgressiveUpdate(BasicTiledLayerBuffer& aTiledBuffer,
-                                         nsIntRegion& aValidRegion,
-                                         nsIntRegion& aInvalidRegion,
-                                         const nsIntRegion& aOldValidRegion,
-                                         const gfx3DMatrix& aTransform,
-                                         const nsIntRect& aCompositionBounds,
-                                         const gfx::Point& aScrollOffset,
-                                         const gfxSize& aResolution,
-                                         LayerManager::DrawThebesLayerCallback aCallback,
-                                         void* aCallbackData)
-{
-  bool repeat = false;
-  do {
-    // Compute the region that should be updated. Repeat as many times as
-    // is required.
-    nsIntRegion regionToPaint;
-    repeat = ComputeProgressiveUpdateRegion(aTiledBuffer,
-                                            aInvalidRegion,
-                                            aOldValidRegion,
-                                            regionToPaint,
-                                            aTransform,
-                                            aCompositionBounds,
-                                            aScrollOffset,
-                                            aResolution,
-                                            repeat);
-
-    // There's no further work to be done, return if nothing has been
-    // drawn, or give what has been drawn to the shadow layer to upload.
-    if (regionToPaint.IsEmpty()) {
-      if (repeat) {
-        break;
-      } else {
-        return false;
-      }
-    }
-
-    // Keep track of what we're about to refresh.
-    aValidRegion.Or(aValidRegion, regionToPaint);
-
-    // aValidRegion may have been altered by InvalidateRegion, but we still
-    // want to display stale content until it gets progressively updated.
-    // Create a region that includes stale content.
-    nsIntRegion validOrStale;
-    validOrStale.Or(aValidRegion, aOldValidRegion);
-
-    // Paint the computed region and subtract it from the invalid region.
-    aTiledBuffer.PaintThebes(this, validOrStale, regionToPaint, aCallback, aCallbackData);
-    aInvalidRegion.Sub(aInvalidRegion, regionToPaint);
-  } while (repeat);
-
-  return true;
-}
-
 void
 BasicTiledThebesLayer::PaintThebes(gfxContext* aContext,
                                    Layer* aMaskLayer,
                                    LayerManager::DrawThebesLayerCallback aCallback,
                                    void* aCallbackData,
                                    ReadbackProcessor* aReadback)
 {
   if (!aCallback) {
@@ -457,206 +377,121 @@ BasicTiledThebesLayer::PaintThebes(gfxCo
   if (!HasShadow()) {
     NS_ASSERTION(false, "Shadow requested for painting\n");
     return;
   }
 
   if (mTiledBuffer.HasFormatChanged(this)) {
     mValidRegion = nsIntRegion();
   }
-  if (mLowPrecisionTiledBuffer.HasFormatChanged(this)) {
-    mLowPrecisionValidRegion = nsIntRegion();
-  }
 
   nsIntRegion invalidRegion = mVisibleRegion;
   invalidRegion.Sub(invalidRegion, mValidRegion);
   if (invalidRegion.IsEmpty())
     return;
 
-  // Calculate the transform required to convert screen space into layer space
-  gfx3DMatrix transform = GetEffectiveTransform();
-  // XXX Not sure if this code for intermediate surfaces is correct.
-  //     It rarely gets hit though, and shouldn't have terrible consequences
-  //     even if it is wrong.
-  for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
-    if (parent->UseIntermediateSurface()) {
-      transform.PreMultiply(parent->GetEffectiveTransform());
-    }
-  }
-  transform.Invert();
-
-  nsIntRect layerDisplayPort;
-  nsIntRegion lowPrecisionInvalidRegion;
-  const gfx::Rect& criticalDisplayPort = GetParent()->GetFrameMetrics().mCriticalDisplayPort;
-  if (!criticalDisplayPort.IsEmpty()) {
-    // Calculate the invalid region for the low precision buffer
-    lowPrecisionInvalidRegion.Sub(mVisibleRegion, mLowPrecisionValidRegion);
-
-    // Find the critical display port in layer space.
-    gfxRect transformedCriticalDisplayPort = transform.TransformBounds(
-      gfxRect(criticalDisplayPort.x, criticalDisplayPort.y,
-              criticalDisplayPort.width, criticalDisplayPort.height));
-    transformedCriticalDisplayPort.RoundOut();
-    layerDisplayPort = nsIntRect(transformedCriticalDisplayPort.x,
-                                 transformedCriticalDisplayPort.y,
-                                 transformedCriticalDisplayPort.width,
-                                 transformedCriticalDisplayPort.height);
-
-    // Clip the invalid region to the critical display-port
-    invalidRegion.And(invalidRegion, layerDisplayPort);
-    if (invalidRegion.IsEmpty() && lowPrecisionInvalidRegion.IsEmpty()) {
-      return;
-    }
-  }
-
   gfxSize resolution(1, 1);
   for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
     const FrameMetrics& metrics = parent->GetFrameMetrics();
     resolution.width *= metrics.mResolution.width;
     resolution.height *= metrics.mResolution.height;
   }
 
-  // Calculate the scroll offset since the last transaction, and the
-  // composition bounds.
-  nsIntRect compositionBounds;
-  gfx::Point scrollOffset(0, 0);
-  Layer* primaryScrollable = BasicManager()->GetPrimaryScrollableLayer();
-  if (primaryScrollable) {
-    const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
-    scrollOffset = metrics.mScrollOffset;
-    gfxRect transformedViewport = transform.TransformBounds(
-      gfxRect(metrics.mCompositionBounds.x, metrics.mCompositionBounds.y,
-              metrics.mCompositionBounds.width, metrics.mCompositionBounds.height));
-    transformedViewport.RoundOut();
-    compositionBounds = nsIntRect(transformedViewport.x, transformedViewport.y,
-                                  transformedViewport.width, transformedViewport.height);
-  }
+  // Only draw progressively when the resolution is unchanged.
+  if (gfxPlatform::UseProgressiveTilePainting() &&
+      !BasicManager()->HasShadowTarget() &&
+      mTiledBuffer.GetResolution() == resolution) {
+    // Calculate the transform required to convert screen space into layer space
+    gfx3DMatrix transform = GetEffectiveTransform();
+    // XXX Not sure if this code for intermediate surfaces is correct.
+    //     It rarely gets hit though, and shouldn't have terrible consequences
+    //     even if it is wrong.
+    for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
+      if (parent->UseIntermediateSurface()) {
+        transform.PreMultiply(parent->GetEffectiveTransform());
+      }
+    }
+    transform.Invert();
+
+    // Store the old valid region, then clear it before painting.
+    // We clip the old valid region to the visible region, as it only gets
+    // used to decide stale content (currently valid and previously visible)
+    nsIntRegion oldValidRegion = mTiledBuffer.GetValidRegion();
+    oldValidRegion.And(oldValidRegion, mVisibleRegion);
+    mTiledBuffer.ClearPaintedRegion();
+
+    // Make sure that tiles that fall outside of the visible region are
+    // discarded on the first update.
+    if (!BasicManager()->IsRepeatTransaction()) {
+      mValidRegion.And(mValidRegion, mVisibleRegion);
+    }
 
-  if (!invalidRegion.IsEmpty()) {
-    bool updatedBuffer = false;
-    // Only draw progressively when the resolution is unchanged.
-    if (gfxPlatform::UseProgressiveTilePainting() &&
-        !BasicManager()->HasShadowTarget() &&
-        mTiledBuffer.GetFrameResolution() == resolution) {
-      // Store the old valid region, then clear it before painting.
-      // We clip the old valid region to the visible region, as it only gets
-      // used to decide stale content (currently valid and previously visible)
-      nsIntRegion oldValidRegion = mTiledBuffer.GetValidRegion();
-      oldValidRegion.And(oldValidRegion, mVisibleRegion);
-      if (!layerDisplayPort.IsEmpty()) {
-        oldValidRegion.And(oldValidRegion, layerDisplayPort);
-      }
+    // Calculate the scroll offset since the last transaction.
+    gfx::Point scrollOffset(0, 0);
+    Layer* primaryScrollable = BasicManager()->GetPrimaryScrollableLayer();
+    if (primaryScrollable) {
+      const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
+      scrollOffset = metrics.mScrollOffset;
+    }
 
-      // Make sure that tiles that fall outside of the visible region are
-      // discarded on the first update.
-      if (!BasicManager()->IsRepeatTransaction()) {
-        mValidRegion.And(mValidRegion, mVisibleRegion);
-        if (!layerDisplayPort.IsEmpty()) {
-          mValidRegion.And(mValidRegion, layerDisplayPort);
+    bool repeat = false;
+    do {
+      // Compute the region that should be updated. Repeat as many times as
+      // is required.
+      nsIntRegion regionToPaint;
+      repeat = ComputeProgressiveUpdateRegion(invalidRegion,
+                                              oldValidRegion,
+                                              regionToPaint,
+                                              transform,
+                                              scrollOffset,
+                                              resolution,
+                                              repeat);
+
+      // There's no further work to be done, return if nothing has been
+      // drawn, or give what has been drawn to the shadow layer to upload.
+      if (regionToPaint.IsEmpty()) {
+        if (repeat) {
+          break;
+        } else {
+          return;
         }
       }
 
-      updatedBuffer =
-        ProgressiveUpdate(mTiledBuffer, mValidRegion, invalidRegion,
-                          oldValidRegion, transform, compositionBounds,
-                          scrollOffset, resolution, aCallback, aCallbackData);
-    } else {
-      updatedBuffer = true;
-      mTiledBuffer.SetFrameResolution(resolution);
-      mValidRegion = mVisibleRegion;
-      if (!layerDisplayPort.IsEmpty()) {
-        mValidRegion.And(mValidRegion, layerDisplayPort);
-      }
-      mTiledBuffer.PaintThebes(this, mValidRegion, invalidRegion, aCallback, aCallbackData);
-    }
+      // Keep track of what we're about to refresh.
+      mValidRegion.Or(mValidRegion, regionToPaint);
+
+      // mValidRegion would have been altered by InvalidateRegion, but we still
+      // want to display stale content until it gets progressively updated.
+      // Create a region that includes stale content.
+      nsIntRegion validOrStale;
+      validOrStale.Or(mValidRegion, oldValidRegion);
 
-    if (updatedBuffer) {
-      mTiledBuffer.ReadLock();
-
-      // Only paint the mask layer on the first transaction.
-      if (aMaskLayer && !BasicManager()->IsRepeatTransaction()) {
-        static_cast<BasicImplData*>(aMaskLayer->ImplData())
-          ->Paint(aContext, nullptr);
-      }
-
-      // Create a heap copy owned and released by the compositor. This is needed
-      // since we're sending this over an async message and content needs to be
-      // be able to modify the tiled buffer in the next transaction.
-      // TODO: Remove me once Bug 747811 lands.
-      BasicTiledLayerBuffer *heapCopy = new BasicTiledLayerBuffer(mTiledBuffer);
-
-      BasicManager()->PaintedTiledLayerBuffer(BasicManager()->Hold(this), heapCopy);
-      mTiledBuffer.ClearPaintedRegion();
-    }
+      // Paint the computed region and subtract it from the invalid region.
+      mTiledBuffer.PaintThebes(this, validOrStale, regionToPaint, aCallback, aCallbackData);
+      invalidRegion.Sub(invalidRegion, regionToPaint);
+    } while (repeat);
+  } else {
+    mTiledBuffer.ClearPaintedRegion();
+    mTiledBuffer.SetResolution(resolution);
+    mValidRegion = mVisibleRegion;
+    mTiledBuffer.PaintThebes(this, mValidRegion, invalidRegion, aCallback, aCallbackData);
   }
 
-  // If we have a critical display-port defined, render the full display-port
-  // progressively in the low-precision tiled buffer.
-  bool updatedLowPrecision = false;
-  if (gfxPlatform::UseLowPrecisionBuffer() &&
-      !criticalDisplayPort.IsEmpty() &&
-      !nsIntRegion(layerDisplayPort).Contains(mVisibleRegion)) {
-    nsIntRegion oldValidRegion = mLowPrecisionTiledBuffer.GetValidRegion();
-    oldValidRegion.And(oldValidRegion, mVisibleRegion);
-
-    // If the frame resolution has changed, invalidate the buffer
-    if (mLowPrecisionTiledBuffer.GetFrameResolution() != resolution) {
-      if (!mLowPrecisionValidRegion.IsEmpty()) {
-        updatedLowPrecision = true;
-      }
-      oldValidRegion.SetEmpty();
-      mLowPrecisionValidRegion.SetEmpty();
-      mLowPrecisionTiledBuffer.SetFrameResolution(resolution);
-    }
-
-    // Invalidate previously valid content that is no longer visible
-    if (!BasicManager()->IsRepeatTransaction()) {
-      mLowPrecisionValidRegion.And(mLowPrecisionValidRegion, mVisibleRegion);
-    }
+  mTiledBuffer.ReadLock();
 
-    // Remove the valid high-precision region from the invalid low-precision
-    // region. We don't want to spend time drawing things twice.
-    nsIntRegion invalidHighPrecisionIntersect;
-    invalidHighPrecisionIntersect.And(lowPrecisionInvalidRegion, mValidRegion);
-    lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, invalidHighPrecisionIntersect);
-
-    if (!lowPrecisionInvalidRegion.IsEmpty()) {
-      updatedLowPrecision =
-        ProgressiveUpdate(mLowPrecisionTiledBuffer, mLowPrecisionValidRegion,
-                          lowPrecisionInvalidRegion, oldValidRegion, transform,
-                          compositionBounds, scrollOffset, resolution, aCallback,
-                          aCallbackData);
-    }
-
-    // Re-add the high-precision valid region intersection so that we can
-    // maintain coherency when the valid region changes.
-    lowPrecisionInvalidRegion.Or(lowPrecisionInvalidRegion, invalidHighPrecisionIntersect);
-  } else if (!mLowPrecisionValidRegion.IsEmpty()) {
-    // Clear the low precision tiled buffer
-    updatedLowPrecision = true;
-    mLowPrecisionValidRegion.SetEmpty();
-    mLowPrecisionTiledBuffer.PaintThebes(this, mLowPrecisionValidRegion,
-                                         mLowPrecisionValidRegion, aCallback,
-                                         aCallbackData);
+  // Only paint the mask layer on the first transaction.
+  if (aMaskLayer && !BasicManager()->IsRepeatTransaction()) {
+    static_cast<BasicImplData*>(aMaskLayer->ImplData())
+      ->Paint(aContext, nullptr);
   }
 
-  // We send a Painted callback if we clear the valid region of the low
-  // precision buffer, so that the shadow buffer's valid region can be updated
-  // and the associated resources can be freed.
-  if (updatedLowPrecision) {
-    mLowPrecisionTiledBuffer.ReadLock();
-    BasicTiledLayerBuffer *heapCopy = new BasicTiledLayerBuffer(mLowPrecisionTiledBuffer);
+  // Create a heap copy owned and released by the compositor. This is needed
+  // since we're sending this over an async message and content needs to be
+  // be able to modify the tiled buffer in the next transaction.
+  // TODO: Remove me once Bug 747811 lands.
+  BasicTiledLayerBuffer *heapCopy = new BasicTiledLayerBuffer(mTiledBuffer);
 
-    // The GL layer manager uses the buffer resolution to distinguish calls
-    // to PaintedTiledLayerBuffer.
-    BasicManager()->PaintedTiledLayerBuffer(BasicManager()->Hold(this), heapCopy);
-    mLowPrecisionTiledBuffer.ClearPaintedRegion();
-  }
-
-  // The transaction is completed, store the last scroll offset.
-  if (!BasicManager()->GetRepeatTransaction()) {
-    mLastScrollOffset = scrollOffset;
-  }
+  BasicManager()->PaintedTiledLayerBuffer(BasicManager()->Hold(this), heapCopy);
   mFirstPaint = false;
 }
 
 } // mozilla
 } // layers
--- a/gfx/layers/basic/BasicTiledThebesLayer.h
+++ b/gfx/layers/basic/BasicTiledThebesLayer.h
@@ -7,18 +7,16 @@
 
 #include "TiledLayerBuffer.h"
 #include "gfxReusableSurfaceWrapper.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "BasicLayers.h"
 #include "BasicImplData.h"
 #include <algorithm>
 
-#define LOW_PRECISION_RESOLUTION 0.25
-
 namespace mozilla {
 namespace layers {
 
 /**
  * Represent a single tile in tiled buffer. It's backed
  * by a gfxReusableSurfaceWrapper that implements a
  * copy-on-write mechanism while locked. The tile should be
  * locked before being sent to the compositor and unlocked
@@ -104,18 +102,18 @@ public:
 
   void ReadLock() {
     for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
       if (mRetainedTiles[i] == GetPlaceholderTile()) continue;
       mRetainedTiles[i].ReadLock();
     }
   }
 
-  const gfxSize& GetFrameResolution() { return mFrameResolution; }
-  void SetFrameResolution(const gfxSize& aResolution) { mFrameResolution = aResolution; }
+  const gfxSize& GetResolution() { return mResolution; }
+  void SetResolution(const gfxSize& aResolution) { mResolution = aResolution; }
 
   bool HasFormatChanged(BasicTiledThebesLayer* aThebesLayer) const;
 protected:
   BasicTiledLayerTile ValidateTile(BasicTiledLayerTile aTile,
                                    const nsIntPoint& aTileRect,
                                    const nsIntRegion& dirtyRect);
 
   // If this returns true, we perform the paint operation into a single large
@@ -130,17 +128,17 @@ protected:
     std::swap(aTileA, aTileB);
   }
 
 private:
   gfxASurface::gfxImageFormat GetFormat() const;
   BasicTiledThebesLayer* mThebesLayer;
   LayerManager::DrawThebesLayerCallback mCallback;
   void* mCallbackData;
-  gfxSize mFrameResolution;
+  gfxSize mResolution;
   bool mLastPaintOpaque;
 
   // The buffer we use when UseSinglePaintBuffer() above is true.
   nsRefPtr<gfxImageSurface>     mSinglePaintBuffer;
   nsIntPoint                    mSinglePaintBufferOffset;
 
   BasicTiledLayerTile           mPlaceholder;
 
@@ -163,31 +161,29 @@ class BasicTiledThebesLayer : public The
 
 public:
   BasicTiledThebesLayer(BasicShadowLayerManager* const aManager)
     : ThebesLayer(aManager, static_cast<BasicImplData*>(this))
     , mLastScrollOffset(0, 0)
     , mFirstPaint(true)
   {
     MOZ_COUNT_CTOR(BasicTiledThebesLayer);
-    mLowPrecisionTiledBuffer.SetResolution(LOW_PRECISION_RESOLUTION);
   }
 
   ~BasicTiledThebesLayer()
   {
     MOZ_COUNT_DTOR(BasicTiledThebesLayer);
   }
 
 
   // Thebes Layer
   virtual Layer* AsLayer() { return this; }
   virtual void InvalidateRegion(const nsIntRegion& aRegion) {
     mInvalidRegion.Or(mInvalidRegion, aRegion);
     mValidRegion.Sub(mValidRegion, aRegion);
-    mLowPrecisionValidRegion.Sub(mLowPrecisionValidRegion, aRegion);
   }
 
   // Shadow methods
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs);
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
 
   virtual void Disconnect()
   {
@@ -219,61 +215,40 @@ private:
 
   /**
    * Calculates the region to update in a single progressive update transaction.
    * This employs some heuristics to update the most 'sensible' region to
    * update at this point in time, and how large an update should be performed
    * at once to maintain visual coherency.
    *
    * aInvalidRegion is the current invalid region.
-   * aOldValidRegion is the valid region of aTiledBuffer at the beginning of the
+   * aOldValidRegion is the valid region of mTiledBuffer at the beginning of the
    * current transaction.
    * aRegionToPaint will be filled with the region to update. This may be empty,
    * which indicates that there is no more work to do.
    * aTransform is the transform required to convert from screen-space to
    * layer-space.
-   * aCompositionBounds is the composition bounds from the primary scrollable
-   * layer, transformed into layer coordinates.
    * aScrollOffset is the current scroll offset of the primary scrollable layer.
    * aResolution is the render resolution of the layer.
    * aIsRepeated should be true if this function has already been called during
    * this transaction.
    *
    * Returns true if it should be called again, false otherwise. In the case
    * that aRegionToPaint is empty, this will return aIsRepeated for convenience.
    */
-  bool ComputeProgressiveUpdateRegion(BasicTiledLayerBuffer& aTiledBuffer,
-                                      const nsIntRegion& aInvalidRegion,
+  bool ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
                                       const nsIntRegion& aOldValidRegion,
                                       nsIntRegion& aRegionToPaint,
                                       const gfx3DMatrix& aTransform,
-                                      const nsIntRect& aCompositionBounds,
                                       const gfx::Point& aScrollOffset,
                                       const gfxSize& aResolution,
                                       bool aIsRepeated);
 
-  /**
-   * Performs a progressive update of a given tiled buffer.
-   * See ComputeProgressiveUpdateRegion above for parameter documentation.
-   */
-  bool ProgressiveUpdate(BasicTiledLayerBuffer& aTiledBuffer,
-                         nsIntRegion& aValidRegion,
-                         nsIntRegion& aInvalidRegion,
-                         const nsIntRegion& aOldValidRegion,
-                         const gfx3DMatrix& aTransform,
-                         const nsIntRect& aCompositionBounds,
-                         const gfx::Point& aScrollOffset,
-                         const gfxSize& aResolution,
-                         LayerManager::DrawThebesLayerCallback aCallback,
-                         void* aCallbackData);
-
   // Members
   BasicTiledLayerBuffer mTiledBuffer;
-  BasicTiledLayerBuffer mLowPrecisionTiledBuffer;
-  nsIntRegion mLowPrecisionValidRegion;
   gfx::Point mLastScrollOffset;
   bool mFirstPaint;
 };
 
 } // layers
 } // mozilla
 
 #endif
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -870,18 +870,17 @@ CompositorParent::TransformShadowTree(Ti
     } 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
-    gfx::Rect displayPortLayersPixels(metrics.mCriticalDisplayPort.IsEmpty() ?
-                                      metrics.mDisplayPort : metrics.mCriticalDisplayPort);
+    gfx::Rect displayPortLayersPixels(metrics.mDisplayPort);
     nsIntRect displayPortDevPixels(
       NS_lround(displayPortLayersPixels.x * devPixelRatioX),
       NS_lround(displayPortLayersPixels.y * devPixelRatioY),
       NS_lround(displayPortLayersPixels.width * devPixelRatioX),
       NS_lround(displayPortLayersPixels.height * devPixelRatioY));
 
     displayPortDevPixels.x += scrollOffsetDevPixels.x;
     displayPortDevPixels.y += scrollOffsetDevPixels.y;
--- a/gfx/layers/opengl/ReusableTileStoreOGL.cpp
+++ b/gfx/layers/opengl/ReusableTileStoreOGL.cpp
@@ -131,19 +131,16 @@ ReusableTileStoreOGL::InvalidateTiles(Ti
 void
 ReusableTileStoreOGL::HarvestTiles(TiledThebesLayerOGL* aLayer,
                                    TiledLayerBufferOGL* aVideoMemoryTiledBuffer,
                                    const nsIntRegion& aOldValidRegion,
                                    const nsIntRegion& aNewValidRegion,
                                    const gfxSize& aOldResolution,
                                    const gfxSize& aNewResolution)
 {
-  NS_ASSERTION(aVideoMemoryTiledBuffer->GetResolution() == 1.0f,
-               "ReusableTileStoreOGL cannot harvest scaled tiles!");
-
   gfxSize scaleFactor = gfxSize(aNewResolution.width / aOldResolution.width,
                                 aNewResolution.height / aOldResolution.height);
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   printf_stderr("Seeing if there are any tiles we can reuse\n");
 #endif
 
   // Iterate over the tiles and decide which ones we're going to harvest.
--- a/gfx/layers/opengl/TiledThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/TiledThebesLayerOGL.cpp
@@ -2,17 +2,16 @@
  * 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/. */
 
 #include "mozilla/layers/PLayersChild.h"
 #include "TiledThebesLayerOGL.h"
 #include "ReusableTileStoreOGL.h"
 #include "BasicTiledThebesLayer.h"
 #include "gfxImageSurface.h"
-#include "gfxPlatform.h"
 
 namespace mozilla {
 namespace layers {
 
 using mozilla::gl::GLContext;
 
 TiledLayerBufferOGL::~TiledLayerBufferOGL()
 {
@@ -42,17 +41,17 @@ TiledLayerBufferOGL::Upload(const BasicT
                             const nsIntRegion& aInvalidateRegion,
                             const gfxSize& aResolution)
 {
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   printf_stderr("Upload %i, %i, %i, %i\n", aInvalidateRegion.GetBounds().x, aInvalidateRegion.GetBounds().y, aInvalidateRegion.GetBounds().width, aInvalidateRegion.GetBounds().height);
   long start = PR_IntervalNow();
 #endif
 
-  mFrameResolution = aResolution;
+  mResolution = aResolution;
   mMainMemoryTiledBuffer = aMainMemoryTiledBuffer;
   mContext->MakeCurrent();
   Update(aNewValidRegion, aInvalidateRegion);
   mMainMemoryTiledBuffer = nullptr;
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   if (PR_IntervalNow() - start > 10) {
     printf_stderr("Time to upload %i\n", PR_IntervalNow() - start);
   }
@@ -111,104 +110,63 @@ TiledLayerBufferOGL::ValidateTile(TiledT
 #endif
   return aTile;
 }
 
 TiledThebesLayerOGL::TiledThebesLayerOGL(LayerManagerOGL *aManager)
   : ShadowThebesLayer(aManager, nullptr)
   , LayerOGL(aManager)
   , mVideoMemoryTiledBuffer(aManager->gl())
-  , mLowPrecisionVideoMemoryTiledBuffer(aManager->gl())
   , mReusableTileStore(nullptr)
-  , mPendingUpload(false)
-  , mPendingLowPrecisionUpload(false)
 {
   mImplData = static_cast<LayerOGL*>(this);
 }
 
 TiledThebesLayerOGL::~TiledThebesLayerOGL()
 {
   mMainMemoryTiledBuffer.ReadUnlock();
-  mLowPrecisionMainMemoryTiledBuffer.ReadUnlock();
   if (mReusableTileStore)
     delete mReusableTileStore;
 }
 
 void
 TiledThebesLayerOGL::MemoryPressure()
 {
   if (mReusableTileStore) {
     delete mReusableTileStore;
     mReusableTileStore = new ReusableTileStoreOGL(gl(), 1);
   }
 }
 
 void
 TiledThebesLayerOGL::PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer)
 {
-  if (mTiledBuffer->IsLowPrecision()) {
-    mLowPrecisionMainMemoryTiledBuffer.ReadUnlock();
-    mLowPrecisionMainMemoryTiledBuffer = *mTiledBuffer;
-    mLowPrecisionRegionToUpload.Or(mLowPrecisionRegionToUpload,
-                                   mLowPrecisionMainMemoryTiledBuffer.GetPaintedRegion());
-    mLowPrecisionMainMemoryTiledBuffer.ClearPaintedRegion();
-    mPendingLowPrecisionUpload = true;
-  } else {
-    mMainMemoryTiledBuffer.ReadUnlock();
-    mMainMemoryTiledBuffer = *mTiledBuffer;
-    mRegionToUpload.Or(mRegionToUpload, mMainMemoryTiledBuffer.GetPaintedRegion());
-    mMainMemoryTiledBuffer.ClearPaintedRegion();
-    mPendingUpload = true;
-  }
-
+  mMainMemoryTiledBuffer.ReadUnlock();
+  mMainMemoryTiledBuffer = *mTiledBuffer;
   // TODO: Remove me once Bug 747811 lands.
   delete mTiledBuffer;
-}
-
-void
-TiledThebesLayerOGL::ProcessLowPrecisionUploadQueue()
-{
-  if (!mPendingLowPrecisionUpload)
-    return;
-
-  mLowPrecisionRegionToUpload.And(mLowPrecisionRegionToUpload,
-                                  mLowPrecisionMainMemoryTiledBuffer.GetValidRegion());
-  // XXX The aResolution parameter of Upload is unused here - this is normally
-  //     set so that ReusableTileStoreOGL knows the frame resolution of tiles
-  //     it's harvesting.
-  mLowPrecisionVideoMemoryTiledBuffer.SetResolution(
-    mLowPrecisionMainMemoryTiledBuffer.GetResolution());
-  mLowPrecisionVideoMemoryTiledBuffer.Upload(&mLowPrecisionMainMemoryTiledBuffer,
-                                 mLowPrecisionMainMemoryTiledBuffer.GetValidRegion(),
-                                 mLowPrecisionRegionToUpload, gfxSize(1, 1));
-  nsIntRegion validRegion = mLowPrecisionVideoMemoryTiledBuffer.GetValidRegion();
-
-  mLowPrecisionMainMemoryTiledBuffer.ReadUnlock();
-
-  mLowPrecisionMainMemoryTiledBuffer = BasicTiledLayerBuffer();
-  mLowPrecisionRegionToUpload = nsIntRegion();
-  mPendingLowPrecisionUpload = false;
+  mRegionToUpload.Or(mRegionToUpload, mMainMemoryTiledBuffer.GetPaintedRegion());
+  mMainMemoryTiledBuffer.ClearPaintedRegion();
 }
 
 void
 TiledThebesLayerOGL::ProcessUploadQueue()
 {
-  if (!mPendingUpload)
+  if (mRegionToUpload.IsEmpty())
     return;
 
   // We should only be retaining old tiles if we're not fixed position.
   // Fixed position layers don't/shouldn't move on the screen, so retaining
   // tiles is not useful and often results in rendering artifacts.
   if (mReusableTileStore && mIsFixedPosition) {
     delete mReusableTileStore;
     mReusableTileStore = nullptr;
-  } else if (gfxPlatform::UseReusableTileStore() &&
-             !mReusableTileStore && !mIsFixedPosition) {
+  } else if (!mReusableTileStore && !mIsFixedPosition) {
     // XXX Add a pref for reusable tile store size
-    mReusableTileStore = new ReusableTileStoreOGL(gl(), 1);
+    mReusableTileStore = new ReusableTileStoreOGL(gl(), 2);
   }
 
   gfxSize resolution(1, 1);
   if (mReusableTileStore) {
     // Work out render resolution by multiplying the resolution of our ancestors.
     // Only container layers can have frame metrics, so we start off with a
     // resolution of 1, 1.
     // XXX For large layer trees, it would be faster to do this once from the
@@ -218,39 +176,38 @@ TiledThebesLayerOGL::ProcessUploadQueue(
       resolution.width *= metrics.mResolution.width;
       resolution.height *= metrics.mResolution.height;
     }
 
     mReusableTileStore->HarvestTiles(this,
                                      &mVideoMemoryTiledBuffer,
                                      mVideoMemoryTiledBuffer.GetValidRegion(),
                                      mMainMemoryTiledBuffer.GetValidRegion(),
-                                     mVideoMemoryTiledBuffer.GetFrameResolution(),
+                                     mVideoMemoryTiledBuffer.GetResolution(),
                                      resolution);
   }
 
   // If we coalesce uploads while the layers' valid region is changing we will
   // end up trying to upload area outside of the valid region. (bug 756555)
   mRegionToUpload.And(mRegionToUpload, mMainMemoryTiledBuffer.GetValidRegion());
 
   mVideoMemoryTiledBuffer.Upload(&mMainMemoryTiledBuffer,
                                  mMainMemoryTiledBuffer.GetValidRegion(),
                                  mRegionToUpload, resolution);
-
   mValidRegion = mVideoMemoryTiledBuffer.GetValidRegion();
 
   mMainMemoryTiledBuffer.ReadUnlock();
   // Release all the tiles by replacing the tile buffer with an empty
   // tiled buffer. This will prevent us from doing a double unlock when
   // calling  ~TiledThebesLayerOGL.
   // FIXME: This wont be needed when we do progressive upload and lock
   // tile by tile.
   mMainMemoryTiledBuffer = BasicTiledLayerBuffer();
   mRegionToUpload = nsIntRegion();
-  mPendingUpload = false;
+
 }
 
 void
 TiledThebesLayerOGL::RenderTile(const TiledTexture& aTile,
                                 const gfx3DMatrix& aTransform,
                                 const nsIntPoint& aOffset,
                                 const nsIntRegion& aScreenRegion,
                                 const nsIntPoint& aTextureOffset,
@@ -278,86 +235,65 @@ TiledThebesLayerOGL::RenderTile(const Ti
       program->SetLayerQuadRect(*rect);
       mOGLManager->BindAndDrawQuadWithTextureRect(program,
                                                   textureRect,
                                                   aTextureBounds);
     }
 }
 
 void
-TiledThebesLayerOGL::RenderLayerBuffer(TiledLayerBufferOGL& aLayerBuffer,
-                                       const nsIntRegion& aValidRegion,
-                                       const nsIntPoint& aOffset,
-                                       const nsIntRegion& aMaskRegion)
+TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset)
 {
+  gl()->MakeCurrent();
+  gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
+  ProcessUploadQueue();
+
   Layer* maskLayer = GetMaskLayer();
+
+  // Render old tiles to fill in gaps we haven't had the time to render yet.
+  if (mReusableTileStore) {
+    mReusableTileStore->DrawTiles(this,
+                                  mVideoMemoryTiledBuffer.GetValidRegion(),
+                                  mVideoMemoryTiledBuffer.GetResolution(),
+                                  GetEffectiveTransform(), aOffset, maskLayer);
+  }
+
+  // Render valid tiles.
   const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();
   const nsIntRect visibleRect = visibleRegion.GetBounds();
-  float resolution = aLayerBuffer.GetResolution();
-  gfx3DMatrix transform = GetEffectiveTransform();
-  transform.Scale(1/resolution, 1/resolution, 1);
 
   uint32_t rowCount = 0;
   uint32_t tileX = 0;
   for (int32_t x = visibleRect.x; x < visibleRect.x + visibleRect.width;) {
     rowCount++;
-    int32_t tileStartX = aLayerBuffer.GetTileStart(x);
-    int32_t w = aLayerBuffer.GetScaledTileLength() - tileStartX;
+    int32_t tileStartX = mVideoMemoryTiledBuffer.GetTileStart(x);
+    int16_t w = mVideoMemoryTiledBuffer.GetTileLength() - tileStartX;
     if (x + w > visibleRect.x + visibleRect.width)
       w = visibleRect.x + visibleRect.width - x;
     int tileY = 0;
     for (int32_t y = visibleRect.y; y < visibleRect.y + visibleRect.height;) {
-      int32_t tileStartY = aLayerBuffer.GetTileStart(y);
-      int32_t h = aLayerBuffer.GetScaledTileLength() - tileStartY;
+      int32_t tileStartY = mVideoMemoryTiledBuffer.GetTileStart(y);
+      int16_t h = mVideoMemoryTiledBuffer.GetTileLength() - tileStartY;
       if (y + h > visibleRect.y + visibleRect.height)
         h = visibleRect.y + visibleRect.height - y;
 
-      TiledTexture tileTexture = aLayerBuffer.
-        GetTile(nsIntPoint(aLayerBuffer.RoundDownToTileEdge(x),
-                           aLayerBuffer.RoundDownToTileEdge(y)));
-      if (tileTexture != aLayerBuffer.GetPlaceholderTile()) {
+      TiledTexture tileTexture = mVideoMemoryTiledBuffer.
+        GetTile(nsIntPoint(mVideoMemoryTiledBuffer.RoundDownToTileEdge(x),
+                           mVideoMemoryTiledBuffer.RoundDownToTileEdge(y)));
+      if (tileTexture != mVideoMemoryTiledBuffer.GetPlaceholderTile()) {
         nsIntRegion tileDrawRegion = nsIntRegion(nsIntRect(x, y, w, h));
-        tileDrawRegion.And(tileDrawRegion, aValidRegion);
-        tileDrawRegion.Sub(tileDrawRegion, aMaskRegion);
+        tileDrawRegion.And(tileDrawRegion, mValidRegion);
 
-        if (!tileDrawRegion.IsEmpty()) {
-          tileDrawRegion.ScaleRoundOut(resolution, resolution);
-
-          nsIntPoint tileOffset((x - tileStartX) * resolution,
-                                (y - tileStartY) * resolution);
-          uint32_t tileSize = aLayerBuffer.GetTileLength();
-          RenderTile(tileTexture, transform, aOffset, tileDrawRegion,
-                     tileOffset, nsIntSize(tileSize, tileSize), maskLayer);
-        }
+        nsIntPoint tileOffset(x - tileStartX, y - tileStartY);
+        uint16_t tileSize = mVideoMemoryTiledBuffer.GetTileLength();
+        RenderTile(tileTexture, GetEffectiveTransform(), aOffset, tileDrawRegion,
+                   tileOffset, nsIntSize(tileSize, tileSize), maskLayer);
       }
       tileY++;
       y += h;
     }
     tileX++;
     x += w;
   }
 }
 
-void
-TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset)
-{
-  gl()->MakeCurrent();
-  gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
-  ProcessUploadQueue();
-  ProcessLowPrecisionUploadQueue();
-
-  // Render old tiles to fill in gaps we haven't had the time to render yet.
-  if (mReusableTileStore) {
-    mReusableTileStore->DrawTiles(this,
-                                  mVideoMemoryTiledBuffer.GetValidRegion(),
-                                  mVideoMemoryTiledBuffer.GetFrameResolution(),
-                                  GetEffectiveTransform(), aOffset, GetMaskLayer());
-  }
-
-  // Render valid tiles.
-  RenderLayerBuffer(mLowPrecisionVideoMemoryTiledBuffer,
-                    mLowPrecisionVideoMemoryTiledBuffer.GetValidRegion(),
-                    aOffset, mValidRegion);
-  RenderLayerBuffer(mVideoMemoryTiledBuffer, mValidRegion, aOffset, nsIntRegion());
-}
-
 } // mozilla
 } // layers
--- a/gfx/layers/opengl/TiledThebesLayerOGL.h
+++ b/gfx/layers/opengl/TiledThebesLayerOGL.h
@@ -75,35 +75,33 @@ public:
 
   void Upload(const BasicTiledLayerBuffer* aMainMemoryTiledBuffer,
               const nsIntRegion& aNewValidRegion,
               const nsIntRegion& aInvalidateRegion,
               const gfxSize& aResolution);
 
   TiledTexture GetPlaceholderTile() const { return TiledTexture(); }
 
-  // Stores the absolute resolution of the containing frame, calculated
-  // by the sum of the resolutions of all parent layers' FrameMetrics.
-  const gfxSize& GetFrameResolution() { return mFrameResolution; }
+  const gfxSize& GetResolution() { return mResolution; }
 
 protected:
   TiledTexture ValidateTile(TiledTexture aTile,
                             const nsIntPoint& aTileRect,
                             const nsIntRegion& dirtyRect);
 
   void ReleaseTile(TiledTexture aTile);
 
   void SwapTiles(TiledTexture& aTileA, TiledTexture& aTileB) {
     std::swap(aTileA, aTileB);
   }
 
 private:
   nsRefPtr<gl::GLContext> mContext;
   const BasicTiledLayerBuffer* mMainMemoryTiledBuffer;
-  gfxSize mFrameResolution;
+  gfxSize mResolution;
 
   void GetFormatAndTileForImageFormat(gfxASurface::gfxImageFormat aFormat,
                                       GLenum& aOutFormat,
                                       GLenum& aOutType);
 };
 
 class TiledThebesLayerOGL : public ShadowThebesLayer,
                             public LayerOGL,
@@ -126,42 +124,31 @@ public:
   void Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
        OptionalThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
        OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion)
   {
     NS_ABORT_IF_FALSE(false, "Not supported");
   }
   void PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* mTiledBuffer);
   void ProcessUploadQueue();
-  void ProcessLowPrecisionUploadQueue();
 
   void MemoryPressure();
 
   // Renders a single given tile.
   void RenderTile(const TiledTexture& aTile,
                   const gfx3DMatrix& aTransform,
                   const nsIntPoint& aOffset,
                   const nsIntRegion& aScreenRegion,
                   const nsIntPoint& aTextureOffset,
                   const nsIntSize& aTextureBounds,
                   Layer* aMaskLayer);
 
 private:
-  void RenderLayerBuffer(TiledLayerBufferOGL& aLayerBuffer,
-                         const nsIntRegion& aValidRegion,
-                         const nsIntPoint& aOffset,
-                         const nsIntRegion& aMaskRegion);
-
   nsIntRegion                  mRegionToUpload;
-  nsIntRegion                  mLowPrecisionRegionToUpload;
   BasicTiledLayerBuffer        mMainMemoryTiledBuffer;
-  BasicTiledLayerBuffer        mLowPrecisionMainMemoryTiledBuffer;
   TiledLayerBufferOGL          mVideoMemoryTiledBuffer;
-  TiledLayerBufferOGL          mLowPrecisionVideoMemoryTiledBuffer;
   ReusableTileStoreOGL*        mReusableTileStore;
-  bool                         mPendingUpload : 1;
-  bool                         mPendingLowPrecisionUpload : 1;
 };
 
 } // layers
 } // mozilla
 
 #endif
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -1242,48 +1242,16 @@ gfxPlatform::UseProgressiveTilePainting(
                                               "layers.progressive-paint",
                                               false);
     }
 
     return sUseProgressiveTilePainting;
 }
 
 bool
-gfxPlatform::UseLowPrecisionBuffer()
-{
-    static bool sUseLowPrecisionBuffer;
-    static bool sUseLowPrecisionBufferPrefCached = false;
-
-    if (!sUseLowPrecisionBufferPrefCached) {
-        sUseLowPrecisionBufferPrefCached = true;
-        mozilla::Preferences::AddBoolVarCache(&sUseLowPrecisionBuffer,
-                                              "layers.low-precision-buffer",
-                                              false);
-    }
-
-    return sUseLowPrecisionBuffer;
-}
-
-bool
-gfxPlatform::UseReusableTileStore()
-{
-    static bool sUseReusableTileStore;
-    static bool sUseReusableTileStorePrefCached = false;
-
-    if (!sUseReusableTileStorePrefCached) {
-        sUseReusableTileStorePrefCached = true;
-        mozilla::Preferences::AddBoolVarCache(&sUseReusableTileStore,
-                                              "layers.reuse-invalid-tiles",
-                                              false);
-    }
-
-    return sUseReusableTileStore;
-}
-
-bool
 gfxPlatform::OffMainThreadCompositingEnabled()
 {
   return XRE_GetProcessType() == GeckoProcessType_Default ?
     CompositorParent::CompositorLoop() != nullptr :
     CompositorChild::ChildProcessHasCompositor();
 }
 
 eCMSMode
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -400,24 +400,16 @@ public:
                                         nsTArray<const char*>& /*aFontList*/)
     {
         // platform-specific override, by default do nothing
     }
 
     // Break large OMTC tiled thebes layer painting into small paints.
     static bool UseProgressiveTilePainting();
 
-    // When a critical display-port is set, render the visible area outside of
-    // it into a buffer at a lower precision. Requires tiled buffers.
-    static bool UseLowPrecisionBuffer();
-
-    // Retain some invalid tiles when the valid region of a layer changes and
-    // excludes previously valid tiles.
-    static bool UseReusableTileStore();
-
     static bool OffMainThreadCompositingEnabled();
 
     /**
      * Are we going to try color management?
      */
     static eCMSMode GetCMSMode();
 
     /**
--- a/ipc/glue/IPCMessageUtils.h
+++ b/ipc/glue/IPCMessageUtils.h
@@ -960,33 +960,31 @@ struct ParamTraits<mozilla::layers::Fram
 
   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);
   }
 
   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) &&
             ReadParam(aMsg, aIter, &aResult->mMayHaveTouchListeners));
   }
 };
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -569,17 +569,16 @@ static void UnmarkFrameForDisplay(nsIFra
 }
 
 static void RecordFrameMetrics(nsIFrame* aForFrame,
                                nsIFrame* aScrollFrame,
                                ContainerLayer* aRoot,
                                const nsRect& aVisibleRect,
                                const nsRect& aViewport,
                                nsRect* aDisplayPort,
-                               nsRect* aCriticalDisplayPort,
                                ViewID aScrollId,
                                const nsDisplayItem::ContainerParameters& aContainerParameters,
                                bool aMayHaveTouchListeners) {
   nsPresContext* presContext = aForFrame->PresContext();
   int32_t auPerDevPixel = presContext->AppUnitsPerDevPixel();
   float auPerCSSPixel = nsPresContext::AppUnitsPerCSSPixel();
 
   nsIntRect visible = aVisibleRect.ScaleToNearestPixels(
@@ -595,24 +594,16 @@ static void RecordFrameMetrics(nsIFrame*
     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));
-      }
   }
 
   nsIScrollableFrame* scrollableFrame = nullptr;
   if (aScrollFrame)
     scrollableFrame = aScrollFrame->GetScrollTargetFrame();
 
   if (scrollableFrame) {
     nsRect contentBounds = scrollableFrame->GetScrollRange();
@@ -1094,25 +1085,22 @@ void nsDisplayList::PaintForFrame(nsDisp
   // Root is being scaled up by the X/Y resolution. Scale it back down.
   root->SetPostScale(1.0f/containerParameters.mXScale,
                      1.0f/containerParameters.mYScale);
 
   ViewID id = presContext->IsRootContentDocument() ? FrameMetrics::ROOT_SCROLL_ID
                                                    : FrameMetrics::NULL_SCROLL_ID;
 
   nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
-  nsRect displayport, criticalDisplayport;
+  nsRect displayport;
   bool usingDisplayport = false;
-  bool usingCriticalDisplayport = false;
   if (rootScrollFrame) {
     nsIContent* content = rootScrollFrame->GetContent();
     if (content) {
       usingDisplayport = nsLayoutUtils::GetDisplayPort(content, &displayport);
-      usingCriticalDisplayport =
-        nsLayoutUtils::GetCriticalDisplayPort(content, &criticalDisplayport);
     }
   }
 
   bool mayHaveTouchListeners = false;
   if (presShell) {
     nsIDocument* document = presShell->GetDocument();
     if (document) {
       nsCOMPtr<nsPIDOMWindow> innerWin(document->GetInnerWindow());
@@ -1121,19 +1109,18 @@ void nsDisplayList::PaintForFrame(nsDisp
       }
     }
   }
 
   nsRect viewport(aBuilder->ToReferenceFrame(aForFrame), aForFrame->GetSize());
 
   RecordFrameMetrics(aForFrame, rootScrollFrame,
                      root, mVisibleRect, viewport,
-                     (usingDisplayport ? &displayport : nullptr),
-                     (usingCriticalDisplayport ? &criticalDisplayport : nullptr),
-                     id, containerParameters, mayHaveTouchListeners);
+                     (usingDisplayport ? &displayport : nullptr), id,
+                     containerParameters, mayHaveTouchListeners);
   if (usingDisplayport &&
       !(root->GetContentFlags() & Layer::CONTENT_OPAQUE)) {
     // See bug 693938, attachment 567017
     NS_WARNING("We don't support transparent content with displayports, force it to be opqaue");
     root->SetContentFlags(Layer::CONTENT_OPAQUE);
   }
 
   layerManager->SetRoot(root);
@@ -2955,27 +2942,23 @@ nsDisplayScrollLayer::BuildLayer(nsDispl
   nsIContent* content = mScrolledFrame->GetContent();
   ViewID scrollId = nsLayoutUtils::FindIDFor(content);
 
   nsRect viewport = mScrollFrame->GetRect() -
                     mScrollFrame->GetPosition() +
                     mScrollFrame->GetOffsetToCrossDoc(ReferenceFrame());
 
   bool usingDisplayport = false;
-  bool usingCriticalDisplayport = false;
-  nsRect displayport, criticalDisplayport;
+  nsRect displayport;
   if (content) {
     usingDisplayport = nsLayoutUtils::GetDisplayPort(content, &displayport);
-    usingCriticalDisplayport =
-      nsLayoutUtils::GetCriticalDisplayPort(content, &criticalDisplayport);
   }
   RecordFrameMetrics(mScrolledFrame, mScrollFrame, layer, mVisibleRect, viewport,
-                     (usingDisplayport ? &displayport : nullptr),
-                     (usingCriticalDisplayport ? &criticalDisplayport : nullptr),
-                     scrollId, aContainerParameters, false);
+                     (usingDisplayport ? &displayport : nullptr), scrollId,
+                     aContainerParameters, false);
 
   return layer.forget();
 }
 
 bool
 nsDisplayScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                         nsRegion* aVisibleRegion,
                                         const nsRect& aAllowVisibleRegionExpansion)
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -373,30 +373,16 @@ nsLayoutUtils::GetDisplayPort(nsIContent
   }
 
   if (aResult) {
     *aResult = *static_cast<nsRect*>(property);
   }
   return true;
 }
 
-bool
-nsLayoutUtils::GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult)
-{
-  void* property = aContent->GetProperty(nsGkAtoms::CriticalDisplayPort);
-  if (!property) {
-    return false;
-  }
-
-  if (aResult) {
-    *aResult = *static_cast<nsRect*>(property);
-  }
-  return true;
-}
-
 nsIFrame*
 nsLayoutUtils::GetLastContinuationWithChild(nsIFrame* aFrame)
 {
   NS_PRECONDITION(aFrame, "NULL frame pointer");
   aFrame = aFrame->GetLastContinuation();
   while (!aFrame->GetFirstPrincipalChild() &&
          aFrame->GetPrevContinuation()) {
     aFrame = aFrame->GetPrevContinuation();
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -74,21 +74,16 @@ public:
   static nsIContent* FindContentFor(ViewID aId);
 
   /**
    * Get display port for the given element.
    */
   static bool GetDisplayPort(nsIContent* aContent, nsRect *aResult);
 
   /**
-   * Get the critical display port for the given element.
-   */
-  static bool GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult);
-
-  /**
    * Use heuristics to figure out the child list that
    * aChildFrame is currently in.
    */
   static nsIFrame::ChildListID GetChildListNameFor(nsIFrame* aChildFrame);
 
   /**
    * GetBeforeFrame returns the outermost :before frame of the given frame, if
    * one exists.  This is typically O(1).  The frame passed in must be
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -518,17 +518,16 @@ pref("editor.singleLine.pasteNewlines", 
 // The names of the preferences are to be in sync with nsEventStateManager.cpp
 pref("ui.dragThresholdX", 25);
 pref("ui.dragThresholdY", 25);
 
 pref("layers.acceleration.disabled", false);
 pref("layers.offmainthreadcomposition.enabled", true);
 pref("layers.async-video.enabled", true);
 pref("layers.progressive-paint", true);
-pref("layers.low-precision-buffer", true);
 
 pref("notification.feature.enabled", true);
 
 // prevent tooltips from showing up
 pref("browser.chrome.toolbar_tips", false);
 pref("indexedDB.feature.enabled", true);
 pref("dom.indexedDB.warningQuota", 5);
 
--- a/mobile/android/base/gfx/GeckoLayerClient.java
+++ b/mobile/android/base/gfx/GeckoLayerClient.java
@@ -71,17 +71,16 @@ public class GeckoLayerClient
     /* Used by robocop for testing purposes */
     private DrawListener mDrawListener;
 
     /* Used as a temporary ViewTransform by syncViewportInfo */
     private final ViewTransform mCurrentViewTransform;
 
     /* Used as the return value of progressiveUpdateCallback */
     private final ProgressiveUpdateData mProgressiveUpdateData;
-    private boolean mProgressiveUpdateIsCurrent;
 
     /* This is written by the compositor thread and read by the UI thread. */
     private volatile boolean mCompositorCreated;
 
     private boolean mForceRedraw;
 
     /* The current viewport metrics.
      * This is volatile so that we can read and write to it from different threads.
@@ -355,51 +354,46 @@ public class GeckoLayerClient
     }
 
     // This is called on the Gecko thread to determine if we're still interested
     // in the update of this display-port to continue. We can return true here
     // to abort the current update and continue with any subsequent ones. This
     // is useful for slow-to-render pages when the display-port starts lagging
     // behind enough that continuing to draw it is wasted effort.
     public ProgressiveUpdateData progressiveUpdateCallback(boolean aHasPendingNewThebesContent,
-                                                           float x, float y, float width, float height,
-                                                           float resolution, boolean lowPrecision) {
+                                                           float x, float y, float width, float height, float resolution) {
         // Grab a local copy of the last display-port sent to Gecko and the
         // current viewport metrics to avoid races when accessing them.
         DisplayPortMetrics displayPort = mDisplayPort;
         ImmutableViewportMetrics viewportMetrics = mViewportMetrics;
         mProgressiveUpdateData.setViewport(viewportMetrics);
         mProgressiveUpdateData.abort = false;
 
+        // Always abort updates if the resolution has changed. There's no use
+        // in drawing at the incorrect resolution.
+        if (!FloatUtils.fuzzyEquals(resolution, displayPort.resolution)) {
+            Log.d(LOGTAG, "Aborting draw due to resolution change");
+            mProgressiveUpdateData.abort = true;
+            return mProgressiveUpdateData;
+        }
+
         // XXX All sorts of rounding happens inside Gecko that becomes hard to
         //     account exactly for. Given we align the display-port to tile
         //     boundaries (and so they rarely vary by sub-pixel amounts), just
         //     check that values are within a couple of pixels of the
         //     display-port bounds.
 
         // Never abort drawing if we can't be sure we've sent a more recent
         // display-port. If we abort updating when we shouldn't, we can end up
         // with blank regions on the screen and we open up the risk of entering
         // an endless updating cycle.
-        if (!lowPrecision) {
-            mProgressiveUpdateIsCurrent =
-              Math.abs(displayPort.getLeft() - x) <= 2 &&
-              Math.abs(displayPort.getTop() - y) <= 2 &&
-              Math.abs(displayPort.getBottom() - (y + height)) <= 2 &&
-              Math.abs(displayPort.getRight() - (x + width)) <= 2;
-        }
-        if (mProgressiveUpdateIsCurrent) {
-            return mProgressiveUpdateData;
-        }
-
-        // Always abort updates if the resolution has changed. There's no use
-        // in drawing at the incorrect resolution.
-        if (!FloatUtils.fuzzyEquals(resolution, displayPort.resolution)) {
-            Log.d(LOGTAG, "Aborting draw due to resolution change");
-            mProgressiveUpdateData.abort = true;
+        if (Math.abs(displayPort.getLeft() - x) <= 2 &&
+            Math.abs(displayPort.getTop() - y) <= 2 &&
+            Math.abs(displayPort.getBottom() - (y + height)) <= 2 &&
+            Math.abs(displayPort.getRight() - (x + width)) <= 2) {
             return mProgressiveUpdateData;
         }
 
         // Abort updates when the display-port no longer contains the visible
         // area of the page (that is, the viewport cropped by the page
         // boundaries).
         // XXX This makes the assumption that we never let the visible area of
         //     the page fall outside of the display-port.
@@ -407,16 +401,28 @@ public class GeckoLayerClient
             Math.max(viewportMetrics.viewportRectTop, viewportMetrics.pageRectTop) + 1 < y ||
             Math.min(viewportMetrics.viewportRectRight, viewportMetrics.pageRectRight) - 1 > x + width ||
             Math.min(viewportMetrics.viewportRectBottom, viewportMetrics.pageRectBottom) - 1 > y + height) {
             Log.d(LOGTAG, "Aborting update due to viewport not in display-port");
             mProgressiveUpdateData.abort = true;
             return mProgressiveUpdateData;
         }
 
+        // There's no new content (where new content is considered to be an
+        // update in a region that wasn't previously visible), and we've sent a
+        // more recent display-port.
+        // Aborting in this situation helps us recover more quickly when the
+        // user starts scrolling on a page that contains animated content that
+        // is slow to draw.
+        if (!aHasPendingNewThebesContent) {
+            Log.d(LOGTAG, "Aborting update due to more relevant display-port in event queue");
+            mProgressiveUpdateData.abort = true;
+            return mProgressiveUpdateData;
+        }
+
         return mProgressiveUpdateData;
     }
 
     /** Implementation of GeckoEventResponder/GeckoEventListener. */
     public void handleMessage(String event, JSONObject message) {
         try {
             if ("Checkerboard:Toggle".equals(event)) {
                 mView.setCheckerboardShouldShowChecks(message.getBoolean("value"));
--- a/mobile/android/base/gfx/ProgressiveUpdateData.java
+++ b/mobile/android/base/gfx/ProgressiveUpdateData.java
@@ -18,13 +18,13 @@ public class ProgressiveUpdateData {
     public float height;
     public float scale;
     public boolean abort;
 
     public void setViewport(ImmutableViewportMetrics viewport) {
         this.x = viewport.viewportRectLeft;
         this.y = viewport.viewportRectTop;
         this.width = viewport.viewportRectRight - this.x;
-        this.height = viewport.viewportRectBottom - this.y;
+        this.height = viewport.viewportRectBottom - this.x;
         this.scale = viewport.zoomFactor;
     }
 }
 
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2740,36 +2740,17 @@ Tab.prototype = {
     };
 
     let epsilon = 0.001;
     if (this._oldDisplayPort == null ||
         Math.abs(displayPort.x - this._oldDisplayPort.x) > epsilon ||
         Math.abs(displayPort.y - this._oldDisplayPort.y) > epsilon ||
         Math.abs(displayPort.width - this._oldDisplayPort.width) > epsilon ||
         Math.abs(displayPort.height - this._oldDisplayPort.height) > epsilon) {
-      // Set the display-port to be 4x the size of the critical display-port,
-      // on each dimension, giving us a 0.25x lower precision buffer around the
-      // critical display-port. Spare area is *not* redistributed to the other
-      // axis, as display-list building and invalidation cost scales with the
-      // size of the display-port.
-      let pageRect = cwu.getRootBounds();
-      let pageXMost = pageRect.right - geckoScrollX;
-      let pageYMost = pageRect.bottom - geckoScrollY;
-
-      let dpW = Math.min(pageRect.right - pageRect.left, displayPort.width * 4);
-      let dpH = Math.min(pageRect.bottom - pageRect.top, displayPort.height * 4);
-
-      let dpX = Math.min(Math.max(displayPort.x - displayPort.width * 1.5,
-                                  pageRect.left - geckoScrollX), pageXMost - dpW);
-      let dpY = Math.min(Math.max(displayPort.y - displayPort.height * 1.5,
-                                  pageRect.top - geckoScrollY), pageYMost - dpH);
-      cwu.setDisplayPortForElement(dpX, dpY, dpW, dpH, element);
-      cwu.setCriticalDisplayPortForElement(displayPort.x, displayPort.y,
-                                           displayPort.width, displayPort.height,
-                                           element);
+      cwu.setDisplayPortForElement(displayPort.x, displayPort.y, displayPort.width, displayPort.height, element);
     }
 
     this._oldDisplayPort = displayPort;
   },
 
   /*
    * Yes, this is ugly. But it's currently the safest way to account for the rounding errors that occur
    * when we pump the displayport coordinates through gecko and they pop out in the compositor.
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -2588,23 +2588,23 @@ AndroidBridge::GetDisplayPort(bool aPage
         return NS_OK;
     AutoLocalJNIFrame jniFrame(env, 0);
     mLayerClient->GetDisplayPort(&jniFrame, aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, metrics, displayPort);
 
     return NS_OK;
 }
 
 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 gfx::Rect& aDisplayPort, float aDisplayResolution, gfx::Rect& aViewport, float& aScaleX, float& aScaleY)
 {
     AndroidGeckoLayerClient *client = mLayerClient;
     if (!client)
         return false;
 
-    return client->ProgressiveUpdateCallback(aHasPendingNewThebesContent, aDisplayPort, aDisplayResolution, aDrawingCritical, aViewport, aScaleX, aScaleY);
+    return client->ProgressiveUpdateCallback(aHasPendingNewThebesContent, aDisplayPort, aDisplayResolution, aViewport, aScaleX, aScaleY);
 }
 
 void
 AndroidBridge::NotifyPaintedRect(float top, float left, float bottom, float right)
 {
     JNIEnv* env = GetJNIEnv();
     if (!env)
         return;
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -155,17 +155,17 @@ public:
     static void NotifyIMEEnabled(int aState, const nsAString& aTypeHint,
                                  const nsAString& aModeHint, const nsAString& aActionHint);
 
     static void NotifyIMEChange(const PRUnichar *aText, uint32_t aTextLen, int aStart, int aEnd, int aNewEnd);
 
     nsresult TakeScreenshot(nsIDOMWindow *window, int32_t srcX, int32_t srcY, int32_t srcW, int32_t srcH, int32_t dstY, int32_t dstX, int32_t dstW, int32_t dstH, int32_t bufW, int32_t bufH, int32_t tabId, int32_t token, jobject buffer);
     nsresult GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort);
 
-    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const gfx::Rect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
+    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const gfx::Rect& aDisplayPort, float aDisplayResolution, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
 
     static void NotifyPaintedRect(float top, float left, float bottom, float right);
 
     void AcknowledgeEventSync();
 
     void EnableLocation(bool aEnable);
     void EnableLocationHighAccuracy(bool aEnable);
 
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -359,17 +359,17 @@ AndroidGeckoLayerClient::InitGeckoLayerC
 
     jViewportClass = GetClassGlobalRef(jEnv, "org/mozilla/gecko/gfx/ImmutableViewportMetrics");
     jViewportCtor = GetMethodID(jEnv, jViewportClass, "<init>", "(FFFFFFFFFFFFF)V");
 
     jDisplayportClass = GetClassGlobalRef(jEnv, "org/mozilla/gecko/gfx/DisplayPortMetrics");
     jDisplayportPosition = GetFieldID(jEnv, jDisplayportClass, "mPosition", "Landroid/graphics/RectF;");
     jDisplayportResolution = GetFieldID(jEnv, jDisplayportClass, "resolution", "F");
     jProgressiveUpdateCallbackMethod = getMethod("progressiveUpdateCallback",
-                                                 "(ZFFFFFZ)Lorg/mozilla/gecko/gfx/ProgressiveUpdateData;");
+                                                 "(ZFFFFF)Lorg/mozilla/gecko/gfx/ProgressiveUpdateData;");
 
 #endif
 }
 
 void
 AndroidLayerRendererFrame::InitLayerRendererFrameClass(JNIEnv *jEnv)
 {
 #ifdef MOZ_ANDROID_OMTC
@@ -848,34 +848,32 @@ AndroidGeckoLayerClient::SyncViewportInf
     aScrollOffset = nsIntPoint(viewTransform.GetX(env), viewTransform.GetY(env));
     aScaleX = aScaleY = viewTransform.GetScale(env);
 }
 
 bool
 AndroidGeckoLayerClient::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
                                                    const gfx::Rect& aDisplayPort,
                                                    float aDisplayResolution,
-                                                   bool aDrawingCritical,
                                                    gfx::Rect& aViewport,
                                                    float& aScaleX,
                                                    float& aScaleY)
 {
     JNIEnv *env = AndroidBridge::GetJNIEnv();
     if (!env)
         return false;
 
     AutoJObject progressiveUpdateDataJObj(env, env->CallObjectMethod(wrapped_obj,
                                                                      jProgressiveUpdateCallbackMethod,
                                                                      aHasPendingNewThebesContent,
                                                                      (float)aDisplayPort.x,
                                                                      (float)aDisplayPort.y,
                                                                      (float)aDisplayPort.width,
                                                                      (float)aDisplayPort.height,
-                                                                     aDisplayResolution,
-                                                                     !aDrawingCritical));
+                                                                     aDisplayResolution));
     if (env->ExceptionCheck()) {
         env->ExceptionDescribe();
         env->ExceptionClear();
         return false;
     }
 
     NS_ABORT_IF_FALSE(progressiveUpdateDataJObj, "No progressive update data!");
 
--- a/widget/android/AndroidJavaWrappers.h
+++ b/widget/android/AndroidJavaWrappers.h
@@ -254,17 +254,17 @@ public:
 
     AndroidGeckoLayerClient() {}
     AndroidGeckoLayerClient(jobject jobj) { Init(jobj); }
 
     void SetFirstPaintViewport(const nsIntPoint& aOffset, float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect);
     void SetPageRect(const gfx::Rect& aCssPageRect);
     void SyncViewportInfo(const nsIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated,
                           nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY);
-    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const gfx::Rect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
+    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const gfx::Rect& aDisplayPort, float aDisplayResolution, 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);
 
 protected:
     static jclass jGeckoLayerClientClass;
     static jmethodID jSetFirstPaintViewport;