Bug 637852. Part 9: Remove resolution support from BasicLayers, ShadowLayers and GL layers. r=mattwoodrow
authorRobert O'Callahan <robert@ocallahan.org>
Thu, 23 Jun 2011 00:11:28 +1200
changeset 71798 123d2c2f626066e8b5d393ea13da451e09594ea3
parent 71797 602d13dcab537ff844d20e9698658619d35f24fa
child 71799 5b2a58c9c279d1a6e27c8fba6cb24c931063dcf5
push idunknown
push userunknown
push dateunknown
reviewersmattwoodrow
bugs637852
milestone7.0a1
Bug 637852. Part 9: Remove resolution support from BasicLayers, ShadowLayers and GL layers. r=mattwoodrow This is not needed anymore.
gfx/layers/ThebesLayerBuffer.cpp
gfx/layers/ThebesLayerBuffer.h
gfx/layers/basic/BasicLayers.cpp
gfx/layers/basic/BasicLayers.h
gfx/layers/ipc/PLayers.ipdl
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
gfx/layers/ipc/ShadowLayersParent.cpp
gfx/layers/opengl/ThebesLayerOGL.cpp
gfx/layers/opengl/ThebesLayerOGL.h
--- a/gfx/layers/ThebesLayerBuffer.cpp
+++ b/gfx/layers/ThebesLayerBuffer.cpp
@@ -40,29 +40,16 @@
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include "gfxUtils.h"
 #include "nsDeviceContext.h"
 
 namespace mozilla {
 namespace layers {
 
-static nsIntSize
-ScaledSize(const nsIntSize& aSize, float aXScale, float aYScale)
-{
-  if (aXScale == 1.0 && aYScale == 1.0) {
-    return aSize;
-  }
-
-  gfxRect rect(0, 0, aSize.width, aSize.height);
-  rect.Scale(aXScale, aYScale);
-  rect.RoundOut();
-  return nsIntSize(rect.Width(), rect.Height());
-}
-
 nsIntRect
 ThebesLayerBuffer::GetQuadrantRectangle(XSide aXSide, YSide aYSide)
 {
   // quadrantTranslation is the amount we translate the top-left
   // of the quadrant by to get coordinates relative to the layer
   nsIntPoint quadrantTranslation = -mBufferRotation;
   quadrantTranslation.x += aXSide == LEFT ? mBufferRect.width : 0;
   quadrantTranslation.y += aYSide == TOP ? mBufferRect.height : 0;
@@ -77,18 +64,17 @@ ThebesLayerBuffer::GetQuadrantRectangle(
  * @param aYSide TOP means we draw from the top side of the buffer (which
  * is drawn on the bottom side of mBufferRect). BOTTOM means we draw from
  * the bottom side of the buffer (which is drawn on the top side of
  * mBufferRect).
  */
 void
 ThebesLayerBuffer::DrawBufferQuadrant(gfxContext* aTarget,
                                       XSide aXSide, YSide aYSide,
-                                      float aOpacity,
-                                      float aXRes, float aYRes)
+                                      float aOpacity)
 {
   // The rectangle that we're going to fill. Basically we're going to
   // render the buffer at mBufferRect + quadrantTranslation to get the
   // pixels in the right place, but we're only going to paint within
   // mBufferRect
   nsIntRect quadrantRect = GetQuadrantRectangle(aXSide, aYSide);
   nsIntRect fillRect;
   if (!fillRect.IntersectRect(mBufferRect, quadrantRect))
@@ -106,153 +92,89 @@ ThebesLayerBuffer::DrawBufferQuadrant(gf
   gfxPattern::GraphicsFilter filter = gfxPattern::FILTER_NEAREST;
   pattern->SetFilter(filter);
 #endif
 
   gfxContextMatrixAutoSaveRestore saveMatrix(aTarget);
 
   // Transform from user -> buffer space.
   gfxMatrix transform;
-  transform.Scale(aXRes, aYRes);
   transform.Translate(-quadrantTranslation);
 
-  // in common cases the matrix after scaling by 1/aRes is close to 1.0,
-  // so we want to make it 1.0 in both cases
-  transform.Scale(1.0 / aXRes, 1.0 / aYRes);
-  transform.NudgeToIntegers();
-
-  gfxMatrix ctxMatrix = aTarget->CurrentMatrix();
-  ctxMatrix.Scale(1.0 / aXRes, 1.0 / aYRes);
-  ctxMatrix.NudgeToIntegers();
-  aTarget->SetMatrix(ctxMatrix);
-
   pattern->SetMatrix(transform);
   aTarget->SetPattern(pattern);
 
   if (aOpacity != 1.0) {
     aTarget->Save();
     aTarget->Clip();
     aTarget->Paint(aOpacity);
     aTarget->Restore();
   } else {
     aTarget->Fill();
   }
 }
 
 void
-ThebesLayerBuffer::DrawBufferWithRotation(gfxContext* aTarget, float aOpacity,
-                                          float aXRes, float aYRes)
+ThebesLayerBuffer::DrawBufferWithRotation(gfxContext* aTarget, float aOpacity)
 {
   // Draw four quadrants. We could use REPEAT_, but it's probably better
   // not to, to be performance-safe.
-  DrawBufferQuadrant(aTarget, LEFT, TOP, aOpacity, aXRes, aYRes);
-  DrawBufferQuadrant(aTarget, RIGHT, TOP, aOpacity, aXRes, aYRes);
-  DrawBufferQuadrant(aTarget, LEFT, BOTTOM, aOpacity, aXRes, aYRes);
-  DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aOpacity, aXRes, aYRes);
+  DrawBufferQuadrant(aTarget, LEFT, TOP, aOpacity);
+  DrawBufferQuadrant(aTarget, RIGHT, TOP, aOpacity);
+  DrawBufferQuadrant(aTarget, LEFT, BOTTOM, aOpacity);
+  DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aOpacity);
 }
 
 already_AddRefed<gfxContext>
-ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds,
-                                               float aXResolution,
-                                               float aYResolution)
+ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds)
 {
   nsRefPtr<gfxContext> ctx = new gfxContext(mBuffer);
 
   // Figure out which quadrant to draw in
   PRInt32 xBoundary = mBufferRect.XMost() - mBufferRotation.x;
   PRInt32 yBoundary = mBufferRect.YMost() - mBufferRotation.y;
   XSide sideX = aBounds.XMost() <= xBoundary ? RIGHT : LEFT;
   YSide sideY = aBounds.YMost() <= yBoundary ? BOTTOM : TOP;
   nsIntRect quadrantRect = GetQuadrantRectangle(sideX, sideY);
   NS_ASSERTION(quadrantRect.Contains(aBounds), "Messed up quadrants");
-  ctx->Scale(aXResolution, aYResolution);
   ctx->Translate(-gfxPoint(quadrantRect.x, quadrantRect.y));
 
   return ctx.forget();
 }
 
-// Move the pixels in aBuffer specified by |aSourceRect| to |aDest|.
-// |aSourceRect| and |aDest| are in the space of |aBuffer|, but
-// unscaled by the resolution.  This helper does the scaling.
-static void
-MovePixels(gfxASurface* aBuffer,
-           const nsIntRect& aSourceRect, const nsIntPoint& aDest,
-           float aXResolution, float aYResolution)
-{
-  gfxRect src(aSourceRect.x, aSourceRect.y, aSourceRect.width, aSourceRect.height);
-  gfxRect dest(aDest.x, aDest.y,  aSourceRect.width, aSourceRect.height);
-  src.Scale(aXResolution, aYResolution);
-  dest.Scale(aXResolution, aYResolution);
-
-#ifdef DEBUG
-  // If we're doing a self-copy, enforce that the rects we're copying
-  // were computed in order to round to device pixels.  If the rects
-  // we're moving *weren't* computed to round, then glitches like
-  // seaming are likely.  Assume that the precision of these
-  // computations is 1 app unit, and toss in a fudge factor of 2.0.
-  static const gfxFloat kPrecision =
-    1.0 / gfxFloat(nsDeviceContext::AppUnitsPerCSSPixel());
-  // FIXME/bug 637852: we've decided to live with transient glitches
-  // during fast-panning for the time being.
-  NS_WARN_IF_FALSE(
-    src.WithinEpsilonOfIntegerPixels(2.0 * kPrecision * aXResolution) &&
-    dest.WithinEpsilonOfIntegerPixels(2.0 * kPrecision * aXResolution),
-    "Rects don't round to device pixels within precision; glitches likely to follow");
-#endif
-
-  src.Round();
-  dest.Round();
-
-  aBuffer->MovePixels(nsIntRect(src.X(), src.Y(),
-                                src.Width(), src.Height()),
-                      nsIntPoint(dest.X(), dest.Y()));
-}
-
 static void
 WrapRotationAxis(PRInt32* aRotationPoint, PRInt32 aSize)
 {
   if (*aRotationPoint < 0) {
     *aRotationPoint += aSize;
   } else if (*aRotationPoint >= aSize) {
     *aRotationPoint -= aSize;
   }
 }
 
 ThebesLayerBuffer::PaintState
 ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
-                              float aXResolution, float aYResolution,
                               PRUint32 aFlags)
 {
   PaintState result;
-  result.mDidSelfCopy = PR_FALSE;
-  float curXRes = aLayer->GetXResolution();
-  float curYRes = aLayer->GetYResolution();
-  // If we have non-identity resolution then mBufferRotation might not fall
-  // on a buffer pixel boundary, in which case that row of pixels will contain
-  // a mix of two completely different rows of the layer, which would be
-  // a catastrophe. So disable rotation in that case.
-  // We also need to disable rotation if we're going to be resampled when
+  // We need to disable rotation if we're going to be resampled when
   // drawing, because we might sample across the rotation boundary.
-  PRBool canHaveRotation =
-    !(aFlags & PAINT_WILL_RESAMPLE) && aXResolution == 1.0 && aYResolution == 1.0;
+  PRBool canHaveRotation = !(aFlags & PAINT_WILL_RESAMPLE);
 
   nsIntRegion validRegion = aLayer->GetValidRegion();
 
   ContentType contentType;
   nsIntRegion neededRegion;
-  nsIntSize destBufferDims;
   PRBool canReuseBuffer;
   nsIntRect destBufferRect;
 
   while (PR_TRUE) {
     contentType = aContentType;
     neededRegion = aLayer->GetVisibleRegion();
-    destBufferDims = ScaledSize(neededRegion.GetBounds().Size(),
-                                aXResolution, aYResolution);
-    canReuseBuffer = mBuffer && BufferSizeOkFor(destBufferDims);
+    canReuseBuffer = mBuffer && BufferSizeOkFor(neededRegion.GetBounds().Size());
 
     if (canReuseBuffer) {
       if (mBufferRect.Contains(neededRegion.GetBounds())) {
         // We don't need to adjust mBufferRect.
         destBufferRect = mBufferRect;
       } else if (neededRegion.GetBounds().Size() <= mBufferRect.Size()) {
         // The buffer's big enough but doesn't contain everything that's
         // going to be visible. We'll move it.
@@ -268,32 +190,21 @@ ThebesLayerBuffer::BeginPaint(ThebesLaye
         (!neededRegion.GetBounds().IsEqualInterior(destBufferRect) ||
          neededRegion.GetNumRects() > 1)) {
       // The area we add to neededRegion might not be painted opaquely
       contentType = gfxASurface::CONTENT_COLOR_ALPHA;
 
       // We need to validate the entire buffer, to make sure that only valid
       // pixels are sampled
       neededRegion = destBufferRect;
-      destBufferDims = ScaledSize(neededRegion.GetBounds().Size(),
-                                  aXResolution, aYResolution);
     }
 
-    if (mBuffer &&
-        (contentType != mBuffer->GetContentType() ||
-         aXResolution != curXRes || aYResolution != curYRes)) {
+    if (mBuffer && contentType != mBuffer->GetContentType()) {
       // We're effectively clearing the valid region, so we need to draw
       // the entire needed region now.
-      //
-      // XXX/cjones: a possibly worthwhile optimization to keep in mind
-      // is to re-use buffers when the resolution and visible region
-      // have changed in such a way that the buffer size stays the same.
-      // It might make even more sense to allocate buffers from a
-      // recyclable pool, so that we could keep this logic simple and
-      // still get back the same buffer.
       result.mRegionToInvalidate = aLayer->GetValidRegion();
       validRegion.SetEmpty();
       Clear();
       // Restart decision process with the cleared buffer. We can only go
       // around the loop one more iteration, since mBuffer is null now.
       continue;
     }
 
@@ -304,22 +215,18 @@ ThebesLayerBuffer::BeginPaint(ThebesLaye
                "Destination rect doesn't contain what we need to paint");
 
   result.mRegionToDraw.Sub(neededRegion, validRegion);
   if (result.mRegionToDraw.IsEmpty())
     return result;
 
   nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
   nsRefPtr<gfxASurface> destBuffer;
-  PRBool bufferDimsChanged = PR_FALSE;
   PRUint32 bufferFlags = canHaveRotation ? ALLOW_REPEAT : 0;
   if (canReuseBuffer) {
-    NS_ASSERTION(curXRes == aXResolution && curYRes == aYResolution,
-                 "resolution changes must Clear()!");
-
     nsIntRect keepArea;
     if (keepArea.IntersectRect(destBufferRect, mBufferRect)) {
       // Set mBufferRotation so that the pixels currently in mBuffer
       // will still be rendered in the right place when mBufferRect
       // changes to destBufferRect.
       nsIntPoint newRotation = mBufferRotation +
         (destBufferRect.TopLeft() - mBufferRect.TopLeft());
       WrapRotationAxis(&newRotation.x, mBufferRect.width);
@@ -332,84 +239,75 @@ ThebesLayerBuffer::BeginPaint(ThebesLaye
           (drawBounds.y < yBoundary && yBoundary < drawBounds.YMost()) ||
           (newRotation != nsIntPoint(0,0) && !canHaveRotation)) {
         // The stuff we need to redraw will wrap around an edge of the
         // buffer, so move the pixels we can keep into a position that
         // lets us redraw in just one quadrant.
         if (mBufferRotation == nsIntPoint(0,0)) {
           nsIntRect srcRect(nsIntPoint(0, 0), mBufferRect.Size());
           nsIntPoint dest = mBufferRect.TopLeft() - destBufferRect.TopLeft();
-          MovePixels(mBuffer, srcRect, dest, curXRes, curYRes);
+          mBuffer->MovePixels(srcRect, dest);
           result.mDidSelfCopy = PR_TRUE;
           // Don't set destBuffer; we special-case self-copies, and
           // just did the necessary work above.
           mBufferRect = destBufferRect;
         } else {
           // We can't do a real self-copy because the buffer is rotated.
           // So allocate a new buffer for the destination.
           destBufferRect = neededRegion.GetBounds();
-          bufferDimsChanged = PR_TRUE;
-          destBuffer = CreateBuffer(contentType, destBufferDims, bufferFlags);
+          destBuffer = CreateBuffer(contentType, destBufferRect.Size(), bufferFlags);
           if (!destBuffer)
             return result;
         }
       } else {
         mBufferRect = destBufferRect;
         mBufferRotation = newRotation;
       }
     } else {
       // No pixels are going to be kept. The whole visible region
       // will be redrawn, so we don't need to copy anything, so we don't
       // set destBuffer.
       mBufferRect = destBufferRect;
       mBufferRotation = nsIntPoint(0,0);
     }
   } else {
     // The buffer's not big enough, so allocate a new one
-    bufferDimsChanged = PR_TRUE;
-    destBuffer = CreateBuffer(contentType, destBufferDims, bufferFlags);
+    destBuffer = CreateBuffer(contentType, destBufferRect.Size(), bufferFlags);
     if (!destBuffer)
       return result;
   }
   NS_ASSERTION(!(aFlags & PAINT_WILL_RESAMPLE) || destBufferRect == neededRegion.GetBounds(),
                "If we're resampling, we need to validate the entire buffer");
 
   // If we have no buffered data already, then destBuffer will be a fresh buffer
   // and we do not need to clear it below.
   PRBool isClear = mBuffer == nsnull;
 
   if (destBuffer) {
     if (mBuffer) {
       // Copy the bits
       nsRefPtr<gfxContext> tmpCtx = new gfxContext(destBuffer);
       nsIntPoint offset = -destBufferRect.TopLeft();
       tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
-      tmpCtx->Scale(aXResolution, aYResolution);
       tmpCtx->Translate(gfxPoint(offset.x, offset.y));
-      NS_ASSERTION(curXRes == aXResolution && curYRes == aYResolution,
-                   "resolution changes must Clear()!");
-      DrawBufferWithRotation(tmpCtx, 1.0, aXResolution, aYResolution);
+      DrawBufferWithRotation(tmpCtx, 1.0);
     }
 
     mBuffer = destBuffer.forget();
     mBufferRect = destBufferRect;
     mBufferRotation = nsIntPoint(0,0);
   }
-  if (bufferDimsChanged) {
-    mBufferDims = destBufferDims;
-  }
   NS_ASSERTION(canHaveRotation || mBufferRotation == nsIntPoint(0,0),
                "Rotation disabled, but we have nonzero rotation?");
 
   nsIntRegion invalidate;
   invalidate.Sub(aLayer->GetValidRegion(), destBufferRect);
   result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate);
 
-  result.mContext = GetContextForQuadrantUpdate(drawBounds,
-                                                aXResolution, aYResolution);
+  result.mContext = GetContextForQuadrantUpdate(drawBounds);
 
   gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw);
   if (contentType == gfxASurface::CONTENT_COLOR_ALPHA && !isClear) {
     result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR);
     result.mContext->Paint();
     result.mContext->SetOperator(gfxContext::OPERATOR_OVER);
   }
   return result;
--- a/gfx/layers/ThebesLayerBuffer.h
+++ b/gfx/layers/ThebesLayerBuffer.h
@@ -77,35 +77,33 @@ public:
    *   fit visible bounds.  May be larger.
    */
   enum BufferSizePolicy {
     SizedToVisibleBounds,
     ContainsVisibleBounds
   };
 
   ThebesLayerBuffer(BufferSizePolicy aBufferSizePolicy)
-    : mBufferDims(0,0)
-    , mBufferRotation(0,0)
+    : mBufferRotation(0,0)
     , mBufferSizePolicy(aBufferSizePolicy)
   {
     MOZ_COUNT_CTOR(ThebesLayerBuffer);
   }
   virtual ~ThebesLayerBuffer()
   {
     MOZ_COUNT_DTOR(ThebesLayerBuffer);
   }
 
   /**
    * Wipe out all retained contents. Call this when the entire
    * buffer becomes invalid.
    */
   void Clear()
   {
     mBuffer = nsnull;
-    mBufferDims.SizeTo(0, 0);
     mBufferRect.SetEmpty();
   }
 
   /**
    * This is returned by BeginPaint. The caller should draw into mContext.
    * mRegionToDraw must be drawn. mRegionToInvalidate has been invalidated
    * by ThebesLayerBuffer and must be redrawn on the screen.
    * mRegionToInvalidate is set when the buffer has changed from
@@ -135,17 +133,16 @@ public:
    * combined with the scale for the resolution is not just an integer
    * translation). This will disable buffer rotation (since we don't want
    * to resample across the rotation boundary) and will ensure that we
    * make the entire buffer contents valid (since we don't want to sample
    * invalid pixels outside the visible region, if the visible region doesn't
    * fill the buffer bounds).
    */
   PaintState BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
-                        float aXResolution, float aYResolution,
                         PRUint32 aFlags);
 
   enum {
     ALLOW_REPEAT = 0x01
   };
   /**
    * Return a new surface of |aSize| and |aType|.
    * @param aFlags if ALLOW_REPEAT is set, then the buffer should be configured
@@ -165,70 +162,54 @@ protected:
   enum XSide {
     LEFT, RIGHT
   };
   enum YSide {
     TOP, BOTTOM
   };
   nsIntRect GetQuadrantRectangle(XSide aXSide, YSide aYSide);
   void DrawBufferQuadrant(gfxContext* aTarget, XSide aXSide, YSide aYSide,
-                          float aOpacity, float aXRes, float aYRes);
-  void DrawBufferWithRotation(gfxContext* aTarget, float aOpacity,
-                              float aXRes, float aYRes);
+                          float aOpacity);
+  void DrawBufferWithRotation(gfxContext* aTarget, float aOpacity);
 
   /**
    * |BufferRect()| is the rect of device pixels that this
    * ThebesLayerBuffer covers.  That is what DrawBufferWithRotation()
    * will paint when it's called.
-   *
-   * |BufferDims()| is the actual dimensions of the underlying surface
-   * maintained by this, also in device pixels.  It is *not*
-   * necessarily true that |BufferRect().Size() == BufferDims()|.
-   * They may differ if a ThebesLayer is drawn at a non-1.0
-   * resolution.
    */
-  const nsIntSize& BufferDims() const { return mBufferDims; }
   const nsIntRect& BufferRect() const { return mBufferRect; }
   const nsIntPoint& BufferRotation() const { return mBufferRotation; }
 
   already_AddRefed<gfxASurface>
-  SetBuffer(gfxASurface* aBuffer, const nsIntSize& aBufferDims,
+  SetBuffer(gfxASurface* aBuffer,
             const nsIntRect& aBufferRect, const nsIntPoint& aBufferRotation)
   {
     nsRefPtr<gfxASurface> tmp = mBuffer.forget();
     mBuffer = aBuffer;
-    mBufferDims = aBufferDims;
     mBufferRect = aBufferRect;
     mBufferRotation = aBufferRotation;
     return tmp.forget();
   }
 
   /**
    * Get a context at the specified resolution for updating |aBounds|,
    * which must be contained within a single quadrant.
    */
   already_AddRefed<gfxContext>
-  GetContextForQuadrantUpdate(const nsIntRect& aBounds,
-                              float aXResolution, float aYResolution);
+  GetContextForQuadrantUpdate(const nsIntRect& aBounds);
 
 private:
   PRBool BufferSizeOkFor(const nsIntSize& aSize)
   {
-    return (aSize == mBufferDims ||
+    return (aSize == mBufferRect.Size() ||
             (SizedToVisibleBounds != mBufferSizePolicy &&
-             aSize < mBufferDims));
+             aSize < mBufferRect.Size()));
   }
 
   nsRefPtr<gfxASurface> mBuffer;
-  /**
-   * The actual dimensions of mBuffer.  For the ContainsVisibleBounds
-   * policy or with resolution-scaled drawing, mBufferDims might be
-   * different than mBufferRect.Size().
-   */
-  nsIntSize             mBufferDims;
   /** The area of the ThebesLayer that is covered by the buffer as a whole */
   nsIntRect             mBufferRect;
   /**
    * The x and y rotation of the buffer. Conceptually the buffer
    * has its origin translated to mBufferRect.TopLeft() - mBufferRotation,
    * is tiled to fill the plane, and the result is clipped to mBufferRect.
    * So the pixel at mBufferRotation within the buffer is what gets painted at
    * mBufferRect.TopLeft().
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -411,39 +411,37 @@ public:
   CreateBuffer(ContentType aType, const nsIntSize& aSize, PRUint32 aFlags);
 
   /**
    * Swap out the old backing buffer for |aBuffer| and attributes.
    */
   void SetBackingBuffer(gfxASurface* aBuffer,
                         const nsIntRect& aRect, const nsIntPoint& aRotation)
   {
-    gfxIntSize prevSize = gfxIntSize(BufferDims().width, BufferDims().height);
+    gfxIntSize prevSize = gfxIntSize(BufferRect().width, BufferRect().height);
     gfxIntSize newSize = aBuffer->GetSize();
     NS_ABORT_IF_FALSE(newSize == prevSize,
                       "Swapped-in buffer size doesn't match old buffer's!");
     nsRefPtr<gfxASurface> oldBuffer;
-    oldBuffer = SetBuffer(aBuffer, nsIntSize(newSize.width, newSize.height),
-                          aRect, aRotation);
+    oldBuffer = SetBuffer(aBuffer, aRect, aRotation);
   }
 
   void SetBackingBufferAndUpdateFrom(
     gfxASurface* aBuffer,
     gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
-    const nsIntRegion& aUpdateRegion, float aXResolution, float aYResolution);
+    const nsIntRegion& aUpdateRegion);
 
 private:
   BasicThebesLayerBuffer(gfxASurface* aBuffer,
                          const nsIntRect& aRect, const nsIntPoint& aRotation)
     // The size policy doesn't really matter here; this constructor is
     // intended to be used for creating temporaries
     : ThebesLayerBuffer(ContainsVisibleBounds)
   {
-    gfxIntSize sz = aBuffer->GetSize();
-    SetBuffer(aBuffer, nsIntSize(sz.width, sz.height), aRect, aRotation);
+    SetBuffer(aBuffer, aRect, aRotation);
   }
 
   BasicThebesLayer* mLayer;
 };
 
 class BasicThebesLayer : public ThebesLayer, public BasicImplData {
 public:
   typedef BasicThebesLayerBuffer Buffer;
@@ -686,41 +684,35 @@ BasicThebesLayer::PaintThebes(gfxContext
       }
 
       aContext->Restore();
     }
     return;
   }
 
   {
-    gfxSize scale = aContext->CurrentMatrix().ScaleFactors(PR_TRUE);
-    float paintXRes = BasicManager()->XResolution() * gfxUtils::ClampToScaleFactor(scale.width);
-    float paintYRes = BasicManager()->YResolution() * gfxUtils::ClampToScaleFactor(scale.height);
     PRUint32 flags = 0;
     gfxMatrix transform;
     if (!GetEffectiveTransform().Is2D(&transform) ||
         transform.HasNonIntegerTranslation() ||
         MustRetainContent() /*<=> has shadow layer*/) {
       flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
     }
     Buffer::PaintState state =
-      mBuffer.BeginPaint(this, contentType, paintXRes, paintYRes, flags);
+      mBuffer.BeginPaint(this, contentType, flags);
     mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
 
     if (state.mContext) {
       // The area that became invalid and is visible needs to be repainted
       // (this could be the whole visible area if our buffer switched
       // from RGB to RGBA, because we might need to repaint with
       // subpixel AA)
       state.mRegionToInvalidate.And(state.mRegionToInvalidate,
                                     GetEffectiveVisibleRegion());
       nsIntRegion extendedDrawRegion = state.mRegionToDraw;
-      extendedDrawRegion.ExtendForScaling(paintXRes, paintYRes);
-      mXResolution = paintXRes;
-      mYResolution = paintYRes;
       SetAntialiasingFlags(this, state.mContext);
       PaintBuffer(state.mContext,
                   state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
                   state.mDidSelfCopy,
                   aCallback, aCallbackData);
       Mutated();
     } else {
       // It's possible that state.mRegionToInvalidate is nonempty here,
@@ -772,45 +764,43 @@ BasicThebesLayerBuffer::DrawTo(ThebesLay
       IsClippingCheap(aTarget, aLayer->GetEffectiveVisibleRegion())) {
     // We don't want to draw invalid stuff, so we need to clip. Might as
     // well clip to the smallest area possible --- the visible region.
     // Bug 599189 if there is a non-integer-translation transform in aTarget,
     // we might sample pixels outside GetEffectiveVisibleRegion(), which is wrong
     // and may cause gray lines.
     gfxUtils::ClipToRegionSnapped(aTarget, aLayer->GetEffectiveVisibleRegion());
   }
-  DrawBufferWithRotation(aTarget, aOpacity,
-                         aLayer->GetXResolution(), aLayer->GetYResolution());
+  DrawBufferWithRotation(aTarget, aOpacity);
   aTarget->Restore();
 }
 
 already_AddRefed<gfxASurface>
 BasicThebesLayerBuffer::CreateBuffer(ContentType aType, 
                                      const nsIntSize& aSize, PRUint32 aFlags)
 {
   return mLayer->CreateBuffer(aType, aSize);
 }
 
 void
 BasicThebesLayerBuffer::SetBackingBufferAndUpdateFrom(
   gfxASurface* aBuffer,
   gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
-  const nsIntRegion& aUpdateRegion, float aXResolution, float aYResolution)
+  const nsIntRegion& aUpdateRegion)
 {
   SetBackingBuffer(aBuffer, aRect, aRotation);
   nsRefPtr<gfxContext> destCtx =
-    GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(),
-                                aXResolution, aYResolution);
+    GetContextForQuadrantUpdate(aUpdateRegion.GetBounds());
   destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
   if (IsClippingCheap(destCtx, aUpdateRegion)) {
     gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
   }
 
   BasicThebesLayerBuffer srcBuffer(aSource, aRect, aRotation);
-  srcBuffer.DrawBufferWithRotation(destCtx, 1.0, aXResolution, aYResolution);
+  srcBuffer.DrawBufferWithRotation(destCtx, 1.0);
 }
 
 class BasicImageLayer : public ImageLayer, public BasicImplData {
 public:
   BasicImageLayer(BasicLayerManager* aLayerManager) :
     ImageLayer(aLayerManager, static_cast<BasicImplData*>(this)),
     mSize(-1, -1)
   {
@@ -1211,19 +1201,17 @@ ToInsideIntRect(const gfxRect& aRect)
   r.RoundIn();
   return nsIntRect(r.X(), r.Y(), r.Width(), r.Height());
 }
 
 BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
 #ifdef DEBUG
   mPhase(PHASE_NONE),
 #endif
-  mXResolution(1.0)
-  , mYResolution(1.0)
-  , mWidget(aWidget)
+  mWidget(aWidget)
   , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(PR_FALSE)
   , mCachedSurfaceInUse(PR_FALSE)
   , mTransactionIncomplete(false)
 {
   MOZ_COUNT_CTOR(BasicLayerManager);
   NS_ASSERTION(aWidget, "Must provide a widget");
 }
 
@@ -1927,27 +1915,25 @@ public:
   {
     if (IsSurfaceDescriptorValid(mBackBuffer))
       BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
     MOZ_COUNT_DTOR(BasicShadowableThebesLayer);
   }
 
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
   {
-    aAttrs = ThebesLayerAttributes(GetValidRegion(),
-                                   mXResolution, mYResolution);
+    aAttrs = ThebesLayerAttributes(GetValidRegion());
   }
 
   virtual Layer* AsLayer() { return this; }
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
   virtual bool MustRetainContent() { return HasShadow(); }
 
   void SetBackBufferAndAttrs(const ThebesBuffer& aBuffer,
                              const nsIntRegion& aValidRegion,
-                             float aXResolution, float aYResolution,
                              const OptionalThebesBuffer& aReadOnlyFrontBuffer,
                              const nsIntRegion& aFrontUpdatedRegion);
 
   virtual void Disconnect()
   {
     mBackBuffer = SurfaceDescriptor();
     BasicShadowableLayer::Disconnect();
   }
@@ -1978,49 +1964,45 @@ private:
   SurfaceDescriptor mBackBuffer;
 
   PRPackedBool mIsNewBuffer;
 };
 
 void
 BasicShadowableThebesLayer::SetBackBufferAndAttrs(const ThebesBuffer& aBuffer,
                                                   const nsIntRegion& aValidRegion,
-                                                  float aXResolution,
-                                                  float aYResolution,
                                                   const OptionalThebesBuffer& aReadOnlyFrontBuffer,
                                                   const nsIntRegion& aFrontUpdatedRegion)
 {
   mBackBuffer = aBuffer.buffer();
   nsRefPtr<gfxASurface> backBuffer = BasicManager()->OpenDescriptor(mBackBuffer);
 
   if (OptionalThebesBuffer::Tnull_t == aReadOnlyFrontBuffer.type()) {
     // We didn't get back a read-only ref to our old back buffer (the
     // parent's new front buffer).  If the parent is pushing updates
     // to a texture it owns, then we probably got back the same buffer
     // we pushed in the update and all is well.  If not, ...
     mValidRegion = aValidRegion;
-    mXResolution = aXResolution;
-    mYResolution = aYResolution;
     mBuffer.SetBackingBuffer(backBuffer, aBuffer.rect(), aBuffer.rotation());
     return;
   }
 
   MOZ_LAYERS_LOG(("BasicShadowableThebes(%p): reading back <x=%d,y=%d,w=%d,h=%d>",
                   this,
                   aFrontUpdatedRegion.GetBounds().x,
                   aFrontUpdatedRegion.GetBounds().y,
                   aFrontUpdatedRegion.GetBounds().width,
                   aFrontUpdatedRegion.GetBounds().height));
 
   const ThebesBuffer roFront = aReadOnlyFrontBuffer.get_ThebesBuffer();
   nsRefPtr<gfxASurface> roFrontBuffer = BasicManager()->OpenDescriptor(roFront.buffer());
   mBuffer.SetBackingBufferAndUpdateFrom(
     backBuffer,
     roFrontBuffer, roFront.rect(), roFront.rotation(),
-    aFrontUpdatedRegion, mXResolution, mYResolution);
+    aFrontUpdatedRegion);
   // Now the new back buffer has the same (interesting) pixels as the
   // new front buffer, and mValidRegion et al. are correct wrt the new
   // back buffer (i.e. as they were for the old back buffer)
 }
 
 void
 BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext,
                                         const nsIntRegion& aRegionToDraw,
@@ -2100,17 +2082,16 @@ BasicShadowableThebesLayer::CreateBuffer
   }
 
   NS_ABORT_IF_FALSE(!mIsNewBuffer,
                     "Bad! Did we create a buffer twice without painting?");
   mIsNewBuffer = true;
 
   BasicManager()->CreatedThebesBuffer(BasicManager()->Hold(this),
                                       nsIntRegion(),
-                                      1.0, 1.0,
                                       nsIntRect(),
                                       tmpFront);
   return BasicManager()->OpenDescriptor(mBackBuffer);
 }
 
 
 class BasicShadowableImageLayer : public BasicImageLayer,
                                   public BasicShadowableLayer
@@ -2435,20 +2416,18 @@ public:
   void Swap(gfxASurface* aNewBuffer,
             const nsIntRect& aNewRect, const nsIntPoint& aNewRotation,
             gfxASurface** aOldBuffer,
             nsIntRect* aOldRect, nsIntPoint* aOldRotation)
   {
     *aOldRect = BufferRect();
     *aOldRotation = BufferRotation();
 
-    gfxIntSize newSize = aNewBuffer->GetSize();
     nsRefPtr<gfxASurface> oldBuffer;
     oldBuffer = SetBuffer(aNewBuffer,
-                          nsIntSize(newSize.width, newSize.height),
                           aNewRect, aNewRotation);
     oldBuffer.forget(aOldBuffer);
   }
 
 protected:
   virtual already_AddRefed<gfxASurface>
   CreateBuffer(ContentType aType, const nsIntSize& aSize)
   {
@@ -2457,65 +2436,52 @@ protected:
   }
 };
 
 
 class BasicShadowThebesLayer : public ShadowThebesLayer, public BasicImplData {
 public:
   BasicShadowThebesLayer(BasicShadowLayerManager* aLayerManager)
     : ShadowThebesLayer(aLayerManager, static_cast<BasicImplData*>(this))
-    , mOldXResolution(1.0)
-    , mOldYResolution(1.0)
   {
     MOZ_COUNT_CTOR(BasicShadowThebesLayer);
   }
   virtual ~BasicShadowThebesLayer()
   {
     // If Disconnect() wasn't called on us, then we assume that the
     // remote side shut down and IPC is disconnected, so we let IPDL
     // clean up our front surface Shmem.
     MOZ_COUNT_DTOR(BasicShadowThebesLayer);
   }
 
   virtual void SetFrontBuffer(const OptionalThebesBuffer& aNewFront,
-                              const nsIntRegion& aValidRegion,
-                              float aXResolution, float aYResolution);
+                              const nsIntRegion& aValidRegion);
 
   virtual void SetValidRegion(const nsIntRegion& aRegion)
   {
     mOldValidRegion = mValidRegion;
     ShadowThebesLayer::SetValidRegion(aRegion);
   }
 
-  virtual void SetResolution(float aXResolution, float aYResolution)
-  {
-    mOldXResolution = mXResolution;
-    mOldYResolution = mYResolution;
-    ShadowThebesLayer::SetResolution(aXResolution, aYResolution);
-  }
-
   virtual void Disconnect()
   {
     DestroyFrontBuffer();
     ShadowThebesLayer::Disconnect();
   }
 
   virtual void
   Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
        ThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
-       float* aNewXResolution, float* aNewYResolution,
        OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion);
 
   virtual void DestroyFrontBuffer()
   {
     mFrontBuffer.Clear();
     mValidRegion.SetEmpty();
     mOldValidRegion.SetEmpty();
-    mOldXResolution = 1.0;
-    mOldYResolution = 1.0;
 
     if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
       BasicManager()->ShadowLayerManager::DestroySharedSurface(&mFrontBufferDescriptor, mAllocator);
     }
   }
 
   virtual void PaintThebes(gfxContext* aContext,
                            LayerManager::DrawThebesLayerCallback aCallback,
@@ -2531,28 +2497,23 @@ private:
   ShadowThebesLayerBuffer mFrontBuffer;
   // Describes the gfxASurface we hand out to |mFrontBuffer|.
   SurfaceDescriptor mFrontBufferDescriptor;
   // When we receive an update from our remote partner, we stow away
   // our previous parameters that described our previous front buffer.
   // Then when we Swap() back/front buffers, we can return these
   // parameters to our partner (adjusted as needed).
   nsIntRegion mOldValidRegion;
-  float mOldXResolution;
-  float mOldYResolution;
 };
 
 void
 BasicShadowThebesLayer::SetFrontBuffer(const OptionalThebesBuffer& aNewFront,
-                                       const nsIntRegion& aValidRegion,
-                                       float aXResolution, float aYResolution)
+                                       const nsIntRegion& aValidRegion)
 {
   mValidRegion = mOldValidRegion = aValidRegion;
-  mXResolution = mOldXResolution = aXResolution;
-  mYResolution = mOldYResolution = aYResolution;
 
   NS_ABORT_IF_FALSE(OptionalThebesBuffer::Tnull_t != aNewFront.type(),
                     "aNewFront must be valid here!");
 
   const ThebesBuffer newFront = aNewFront.get_ThebesBuffer();
   nsRefPtr<gfxASurface> newFrontBuffer =
     BasicManager()->OpenDescriptor(newFront.buffer());
 
@@ -2564,43 +2525,24 @@ BasicShadowThebesLayer::SetFrontBuffer(c
   mFrontBufferDescriptor = newFront.buffer();
 }
 
 void
 BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
                              const nsIntRegion& aUpdatedRegion,
                              ThebesBuffer* aNewBack,
                              nsIntRegion* aNewBackValidRegion,
-                             float* aNewXResolution, float* aNewYResolution,
                              OptionalThebesBuffer* aReadOnlyFront,
                              nsIntRegion* aFrontUpdatedRegion)
 {
   // This code relies on Swap() arriving *after* attribute mutations.
   aNewBack->buffer() = mFrontBufferDescriptor;
   // We have to invalidate the pixels painted into the new buffer.
   // They might overlap with our old pixels.
-  if (mOldXResolution == mXResolution && mOldYResolution == mYResolution) {
-    aNewBackValidRegion->Sub(mOldValidRegion, aUpdatedRegion);
-  } else {
-    // On resolution changes, pretend that our buffer has the new
-    // resolution, but just has no valid content.  This can avoid
-    // unnecessary buffer reallocs.
-    // 
-    // FIXME/bug 598866: when we start re-using buffers after
-    // resolution changes, we're going to need to implement
-    // front->back copies to avoid thrashing our valid region by
-    // always nullifying it.
-    aNewBackValidRegion->SetEmpty();
-    mOldXResolution = mXResolution;
-    mOldYResolution = mYResolution;
-  }
-  NS_ASSERTION(mXResolution == mOldXResolution && mYResolution == mOldYResolution,
-               "Uh-oh, buffer allocation thrash forthcoming!");
-  *aNewXResolution = mXResolution;
-  *aNewYResolution = mYResolution;
+  aNewBackValidRegion->Sub(mOldValidRegion, aUpdatedRegion);
 
   nsRefPtr<gfxASurface> newFrontBuffer =
     BasicManager()->OpenDescriptor(aNewFront.buffer());
 
   nsRefPtr<gfxASurface> unused;
   mFrontBuffer.Swap(
     newFrontBuffer, aNewFront.rect(), aNewFront.rotation(),
     getter_AddRefs(unused), &aNewBack->rect(), &aNewBack->rotation());
@@ -3083,18 +3025,17 @@ BasicShadowLayerManager::ForwardTransact
 
       switch (reply.type()) {
       case EditReply::TOpThebesBufferSwap: {
         MOZ_LAYERS_LOG(("[LayersForwarder] ThebesBufferSwap"));
 
         const OpThebesBufferSwap& obs = reply.get_OpThebesBufferSwap();
         BasicShadowableThebesLayer* thebes = GetBasicShadowable(obs)->AsThebes();
         thebes->SetBackBufferAndAttrs(
-          obs.newBackBuffer(),
-          obs.newValidRegion(), obs.newXResolution(), obs.newYResolution(),
+          obs.newBackBuffer(), obs.newValidRegion(),
           obs.readOnlyFrontBuffer(), obs.frontUpdatedRegion());
         break;
       }
       case EditReply::TOpBufferSwap: {
         MOZ_LAYERS_LOG(("[LayersForwarder] BufferSwap"));
 
         const OpBufferSwap& obs = reply.get_OpBufferSwap();
         const SurfaceDescriptor& descr = obs.newBackBuffer();
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -110,31 +110,16 @@ public:
    */
   enum BufferMode {
     BUFFER_NONE,
     BUFFER_BUFFERED
   };
   void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering);
   gfxContext* GetDefaultTarget() { return mDefaultTarget; }
 
-  /**
-   * Set a target resolution for managed layers that are scalable.  It
-   * might make sense to call this outside of a transaction, but
-   * currently it's only allowed during the construction phase of
-   * transactions.
-   */
-  void SetResolution(float aXResolution, float aYResolution)
-  {
-    NS_ASSERTION(InConstruction(), "resolution must be set before drawing");
-    mXResolution = aXResolution;
-    mYResolution = aYResolution;
-  }
-  float XResolution() const { return mXResolution; }
-  float YResolution() const { return mYResolution; }
-
   nsIWidget* GetRetainerWidget() { return mWidget; }
   void ClearRetainerWidget() { mWidget = nsnull; }
 
   virtual void BeginTransaction();
   virtual void BeginTransactionWithTarget(gfxContext* aTarget);
   virtual bool EndEmptyTransaction();
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
                               void* aCallbackData);
@@ -207,20 +192,16 @@ protected:
                   ReadbackProcessor* aReadback);
 
   // Clear the contents of a layer
   void ClearLayer(Layer* aLayer);
 
   bool EndTransactionInternal(DrawThebesLayerCallback aCallback,
                               void* aCallbackData);
 
-  // Target resolution for scalable content.
-  float mXResolution;
-  float mYResolution;
-
   // Widget whose surface should be used as the basis for ThebesLayer
   // buffers.
   nsIWidget* mWidget;
   // The default context for BeginTransaction.
   nsRefPtr<gfxContext> mDefaultTarget;
   // The context to draw into.
   nsRefPtr<gfxContext> mTarget;
 
--- a/gfx/layers/ipc/PLayers.ipdl
+++ b/gfx/layers/ipc/PLayers.ipdl
@@ -100,18 +100,16 @@ struct ThebesBuffer {
   nsIntPoint rotation; 
 };
 union OptionalThebesBuffer { ThebesBuffer; null_t; };
 
 struct OpCreateThebesBuffer {
   PLayer layer;
   OptionalThebesBuffer initialFront;
   nsIntRegion frontValidRegion;
-  float xResolution;
-  float yResolution;
 };
 struct OpDestroyThebesFrontBuffer { PLayer layer; };
 
 struct OpCreateCanvasBuffer {
   PLayer layer;
   nsIntSize size;
   SurfaceDescriptor initialFront;
   bool needYFlip;
@@ -136,18 +134,16 @@ struct CommonLayerAttributes {
   nsIntRect clipRect;
   bool useTileSourceRect;
   nsIntRect tileSourceRect;
   bool isFixedPosition;
 };
 
 struct ThebesLayerAttributes {
   nsIntRegion validRegion;
-  float xResolution;
-  float yResolution;
 };
 struct ContainerLayerAttributes{ FrameMetrics metrics; };
 struct ColorLayerAttributes    { gfxRGBA color; };
 struct CanvasLayerAttributes   { GraphicsFilterType filter; };
 struct ImageLayerAttributes    { GraphicsFilterType filter; };
 
 union SpecificLayerAttributes {
   null_t;
@@ -225,18 +221,16 @@ union Edit {
 struct OpBufferSwap   { PLayer layer; SurfaceDescriptor newBackBuffer; };
 
 struct OpImageSwap { PLayer layer; SharedImage newBackImage; };
 
 struct OpThebesBufferSwap {
   PLayer layer;
   ThebesBuffer newBackBuffer;
   nsIntRegion newValidRegion;
-  float newXResolution;
-  float newYResolution;
   // If the parent took the child's old back buffer and returned its
   // old front buffer, |readOnlyFrontBuffer| may (if non-null) contain
   // the child's old back buffer (parent's new front buffer).  This
   // buffer can be used to read back the newly updated region into the
   // child's new back buffer.  This buffer must be considered
   // read-only, but sadly that's not enforced.
   OptionalThebesBuffer readOnlyFrontBuffer;
   nsIntRegion frontUpdatedRegion;
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -181,32 +181,28 @@ void
 ShadowLayerForwarder::CreatedCanvasLayer(ShadowableLayer* aCanvas)
 {
   CreatedLayer<OpCreateCanvasLayer>(mTxn, aCanvas);
 }
 
 void
 ShadowLayerForwarder::CreatedThebesBuffer(ShadowableLayer* aThebes,
                                           const nsIntRegion& aFrontValidRegion,
-                                          float aXResolution,
-                                          float aYResolution,
                                           const nsIntRect& aBufferRect,
                                           const SurfaceDescriptor& aTempFrontBuffer)
 {
   OptionalThebesBuffer buffer = null_t();
   if (IsSurfaceDescriptorValid(aTempFrontBuffer)) {
     buffer = ThebesBuffer(aTempFrontBuffer,
                           aBufferRect,
                           nsIntPoint(0, 0));
   }
   mTxn->AddEdit(OpCreateThebesBuffer(NULL, Shadow(aThebes),
                                      buffer,
-                                     aFrontValidRegion,
-                                     aXResolution,
-                                     aYResolution));
+                                     aFrontValidRegion));
 }
 
 void
 ShadowLayerForwarder::CreatedImageBuffer(ShadowableLayer* aImage,
                                          nsIntSize aSize,
                                          const SharedImage& aTempFrontImage)
 {
   mTxn->AddEdit(OpCreateImageBuffer(NULL, Shadow(aImage),
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -152,17 +152,16 @@ public:
    * |aInitialFrontBuffer| is never actually drawn to screen.  It is
    * OK if it is drawn though.
    */
   /**
    * |aBufferRect| is the screen rect covered by |aInitialFrontBuffer|.
    */
   void CreatedThebesBuffer(ShadowableLayer* aThebes,
                            const nsIntRegion& aFrontValidRegion,
-                           float aXResolution, float aYResolution,
                            const nsIntRect& aBufferRect,
                            const SurfaceDescriptor& aInitialFrontBuffer);
   /**
    * For the next two methods, |aSize| is the size of
    * |aInitialFrontSurface|.
    */
   void CreatedImageBuffer(ShadowableLayer* aImage,
                           nsIntSize aSize,
@@ -489,18 +488,17 @@ class ShadowThebesLayer : public ShadowL
 public:
   /**
    * CONSTRUCTION PHASE ONLY
    *
    * Override the front buffer and its valid region with the specified
    * values.  This is called when a new buffer has been created.
    */
   virtual void SetFrontBuffer(const OptionalThebesBuffer& aNewFront,
-                              const nsIntRegion& aValidRegion,
-                              float aXResolution, float aYResolution) = 0;
+                              const nsIntRegion& aValidRegion) = 0;
 
   virtual void InvalidateRegion(const nsIntRegion& aRegion)
   {
     NS_RUNTIMEABORT("ShadowThebesLayers can't fill invalidated regions");
   }
 
   /**
    * CONSTRUCTION PHASE ONLY
@@ -508,35 +506,24 @@ public:
   virtual void SetValidRegion(const nsIntRegion& aRegion)
   {
     mValidRegion = aRegion;
     Mutated();
   }
 
   /**
    * CONSTRUCTION PHASE ONLY
-   */
-  virtual void SetResolution(float aXResolution, float aYResolution)
-  {
-    mXResolution = aXResolution;
-    mYResolution = aYResolution;
-    Mutated();
-  }
-
-  /**
-   * CONSTRUCTION PHASE ONLY
    *
    * Publish the remote layer's back ThebesLayerBuffer to this shadow,
    * swapping out the old front ThebesLayerBuffer (the new back buffer
    * for the remote layer).
    */
   virtual void
   Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
        ThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
-       float* aNewXResolution, float* aNewYResolution,
        OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion) = 0;
 
   /**
    * CONSTRUCTION PHASE ONLY
    *
    * Destroy the current front buffer.
    */
   virtual void DestroyFrontBuffer() = 0;
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -206,18 +206,17 @@ ShadowLayersParent::RecvUpdate(const Inf
     }
     case Edit::TOpCreateThebesBuffer: {
       MOZ_LAYERS_LOG(("[ParentSide] CreateThebesBuffer"));
 
       const OpCreateThebesBuffer& otb = edit.get_OpCreateThebesBuffer();
       ShadowThebesLayer* thebes = static_cast<ShadowThebesLayer*>(
         AsShadowLayer(otb)->AsLayer());
 
-      thebes->SetFrontBuffer(otb.initialFront(), otb.frontValidRegion(),
-                             otb.xResolution(), otb.yResolution());
+      thebes->SetFrontBuffer(otb.initialFront(), otb.frontValidRegion());
 
       break;
     }
     case Edit::TOpCreateCanvasBuffer: {
       MOZ_LAYERS_LOG(("[ParentSide] CreateCanvasBuffer"));
 
       const OpCreateCanvasBuffer& ocb = edit.get_OpCreateCanvasBuffer();
       ShadowCanvasLayer* canvas = static_cast<ShadowCanvasLayer*>(
@@ -305,17 +304,16 @@ ShadowLayersParent::RecvUpdate(const Inf
         MOZ_LAYERS_LOG(("[ParentSide]   thebes layer"));
 
         ShadowThebesLayer* thebesLayer =
           static_cast<ShadowThebesLayer*>(layer);
         const ThebesLayerAttributes& attrs =
           specific.get_ThebesLayerAttributes();
 
         thebesLayer->SetValidRegion(attrs.validRegion());
-        thebesLayer->SetResolution(attrs.xResolution(), attrs.yResolution());
 
         break;
       }
       case Specific::TContainerLayerAttributes:
         MOZ_LAYERS_LOG(("[ParentSide]   container layer"));
 
         static_cast<ContainerLayer*>(layer)->SetFrameMetrics(
           specific.get_ContainerLayerAttributes().metrics());
@@ -386,26 +384,25 @@ ShadowLayersParent::RecvUpdate(const Inf
       const OpPaintThebesBuffer& op = edit.get_OpPaintThebesBuffer();
       ShadowLayerParent* shadow = AsShadowLayer(op);
       ShadowThebesLayer* thebes =
         static_cast<ShadowThebesLayer*>(shadow->AsLayer());
       const ThebesBuffer& newFront = op.newFrontBuffer();
 
       ThebesBuffer newBack;
       nsIntRegion newValidRegion;
-      float newXResolution, newYResolution;
       OptionalThebesBuffer readonlyFront;
       nsIntRegion frontUpdatedRegion;
       thebes->Swap(newFront, op.updatedRegion(),
-                   &newBack, &newValidRegion, &newXResolution, &newYResolution,
+                   &newBack, &newValidRegion,
                    &readonlyFront, &frontUpdatedRegion);
       replyv.push_back(
         OpThebesBufferSwap(
           shadow, NULL,
-          newBack, newValidRegion, newXResolution, newYResolution,
+          newBack, newValidRegion,
           readonlyFront, frontUpdatedRegion));
       break;
     }
     case Edit::TOpPaintCanvas: {
       MOZ_LAYERS_LOG(("[ParentSide] Paint CanvasLayer"));
 
       const OpPaintCanvas& op = edit.get_OpPaintCanvas();
       ShadowLayerParent* shadow = AsShadowLayer(op);
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -166,18 +166,16 @@ public:
   ThebesLayerBufferOGL(ThebesLayer* aLayer, LayerOGL* aOGLLayer)
     : mLayer(aLayer)
     , mOGLLayer(aOGLLayer)
   {}
   virtual ~ThebesLayerBufferOGL() {}
 
   enum { PAINT_WILL_RESAMPLE = ThebesLayerBuffer::PAINT_WILL_RESAMPLE };
   virtual PaintState BeginPaint(ContentType aContentType,
-                                float aXResolution,
-                                float aYResolution,
                                 PRUint32 aFlags) = 0;
 
   void RenderTo(const nsIntPoint& aOffset, LayerManagerOGL* aManager,
                 PRUint32 aFlags);
 
   nsIntSize GetSize() {
     if (mTexImage)
       return mTexImage->GetSize();
@@ -210,19 +208,16 @@ ThebesLayerBufferOGL::RenderTo(const nsI
   if (mTexImageOnWhite && mTexImageOnWhite->InUpdate()) {
     mTexImageOnWhite->EndUpdate();
   }
 
   // Bind textures.
   TextureImage::ScopedBindTexture texBind(mTexImage, LOCAL_GL_TEXTURE0);
   TextureImage::ScopedBindTexture texOnWhiteBind(mTexImageOnWhite, LOCAL_GL_TEXTURE1);
 
-  float xres = mLayer->GetXResolution();
-  float yres = mLayer->GetYResolution();
-
   PRInt32 passes = mTexImageOnWhite ? 2 : 1;
   for (PRInt32 pass = 1; pass <= passes; ++pass) {
     LayerProgram *program;
 
     if (passes == 2) {
       ComponentAlphaTextureLayerProgram *alphaProgram;
       NS_ASSERTION(!mTexImage->IsRGB() && !mTexImageOnWhite->IsRGB(),
                    "Only BGR image surported with component alpha (currently!)");
@@ -269,22 +264,16 @@ ThebesLayerBufferOGL::RenderTo(const nsI
     }
     nsIntRegionRectIterator iter(*renderRegion);
     while (const nsIntRect *iterRect = iter.Next()) {
       nsIntRect quadRect = *iterRect;
       program->SetLayerQuadRect(quadRect);
 
       quadRect.MoveBy(-GetOriginOffset());
 
-      // The buffer rect and rotation are resolution-neutral; with a
-      // non-1.0 resolution, only the texture size is scaled by the
-      // resolution.  So map the quadrent rect into the space scaled to
-      // the texture size and let GL do the rest.
-      quadRect.ScaleRoundOut(xres, yres);
-
       BindAndDrawQuadWithTextureRect(gl(), program, quadRect,
                                      mTexImage->GetSize(),
                                      mTexImage->GetWrapMode());
     }
   }
 
   if (mTexImageOnWhite) {
     // Restore defaults
@@ -307,25 +296,21 @@ public:
     : ThebesLayerBufferOGL(aLayer, aLayer)
     , ThebesLayerBuffer(SizedToVisibleBounds)
   {
   }
   virtual ~SurfaceBufferOGL() {}
 
   // ThebesLayerBufferOGL interface
   virtual PaintState BeginPaint(ContentType aContentType, 
-                                float aXResolution, 
-                                float aYResolution,
                                 PRUint32 aFlags)
   {
     // Let ThebesLayerBuffer do all the hard work for us! :D
     return ThebesLayerBuffer::BeginPaint(mLayer, 
                                          aContentType, 
-                                         aXResolution, 
-                                         aYResolution,
                                          aFlags);
   }
 
   // ThebesLayerBuffer interface
   virtual already_AddRefed<gfxASurface>
   CreateBuffer(ContentType aType, const nsIntSize& aSize, PRUint32 aFlags)
   {
     NS_ASSERTION(gfxASurface::CONTENT_ALPHA != aType,"ThebesBuffer has color");
@@ -351,18 +336,16 @@ public:
   BasicBufferOGL(ThebesLayerOGL* aLayer)
     : ThebesLayerBufferOGL(aLayer, aLayer)
     , mBufferRect(0,0,0,0)
     , mBufferRotation(0,0)
   {}
   virtual ~BasicBufferOGL() {}
 
   virtual PaintState BeginPaint(ContentType aContentType,
-                                float aXResolution,
-                                float aYResolution,
                                 PRUint32 aFlags);
 
 protected:
   enum XSide {
     LEFT, RIGHT
   };
   enum YSide {
     TOP, BOTTOM
@@ -405,61 +388,37 @@ FillSurface(gfxASurface* aSurface, const
 {
   nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
   ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
   gfxUtils::ClipToRegion(ctx, aRegion);
   ctx->SetColor(aColor);
   ctx->Paint();
 }
 
-static nsIntSize
-ScaledSize(const nsIntSize& aSize, float aXScale, float aYScale)
-{
-  if (aXScale == 1.0 && aYScale == 1.0) {
-    return aSize;
-  }
-
-  nsIntRect rect(0, 0, aSize.width, aSize.height);
-  rect.ScaleRoundOut(aXScale, aYScale);
-  return rect.Size();
-}
-
 BasicBufferOGL::PaintState
 BasicBufferOGL::BeginPaint(ContentType aContentType,
-                           float aXResolution,
-                           float aYResolution,
                            PRUint32 aFlags)
 {
   PaintState result;
-  float curXRes = mLayer->GetXResolution();
-  float curYRes = mLayer->GetYResolution();
-  // If we have non-identity resolution then mBufferRotation might not fall
-  // on a buffer pixel boundary, in which case that row of pixels will contain
-  // a mix of two completely different rows of the layer, which would be
-  // a catastrophe. So disable rotation in that case.
-  // We also need to disable rotation if we're going to be resampled when
+  // We need to disable rotation if we're going to be resampled when
   // drawing, because we might sample across the rotation boundary.
-  PRBool canHaveRotation =
-    !(aFlags & PAINT_WILL_RESAMPLE) && aXResolution == 1.0 && aYResolution == 1.0;
+  PRBool canHaveRotation =  !(aFlags & PAINT_WILL_RESAMPLE);
 
   nsIntRegion validRegion = mLayer->GetValidRegion();
 
   Layer::SurfaceMode mode;
   ContentType contentType;
   nsIntRegion neededRegion;
-  nsIntSize destBufferDims;
   PRBool canReuseBuffer;
   nsIntRect destBufferRect;
 
   while (PR_TRUE) {
     mode = mLayer->GetSurfaceMode();
     contentType = aContentType;
     neededRegion = mLayer->GetVisibleRegion();
-    destBufferDims = ScaledSize(neededRegion.GetBounds().Size(),
-                                aXResolution, aYResolution);
     // If we're going to resample, we need a buffer that's in clamp mode.
     canReuseBuffer = neededRegion.GetBounds().Size() <= mBufferRect.Size() &&
       mTexImage &&
       (!(aFlags & PAINT_WILL_RESAMPLE) ||
        mTexImage->GetWrapMode() == LOCAL_GL_CLAMP_TO_EDGE);
 
     if (canReuseBuffer) {
       if (mBufferRect.Contains(neededRegion.GetBounds())) {
@@ -494,33 +453,23 @@ BasicBufferOGL::BeginPaint(ContentType a
         contentType = gfxASurface::CONTENT_COLOR_ALPHA;
         mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA;
       }
       // For component alpha layers, we leave contentType as CONTENT_COLOR.
 
       // We need to validate the entire buffer, to make sure that only valid
       // pixels are sampled
       neededRegion = destBufferRect;
-      destBufferDims = ScaledSize(neededRegion.GetBounds().Size(),
-                                  aXResolution, aYResolution);
     }
 
     if (mTexImage &&
         (mTexImage->GetContentType() != contentType ||
-         aXResolution != curXRes || aYResolution != curYRes ||
          (mode == Layer::SURFACE_COMPONENT_ALPHA) != (mTexImageOnWhite != nsnull))) {
       // We're effectively clearing the valid region, so we need to draw
       // the entire needed region now.
-      //
-      // XXX/cjones: a possibly worthwhile optimization to keep in mind
-      // is to re-use buffers when the resolution and visible region
-      // have changed in such a way that the buffer size stays the same.
-      // It might make even more sense to allocate buffers from a
-      // recyclable pool, so that we could keep this logic simple and
-      // still get back the same buffer.
       result.mRegionToInvalidate = mLayer->GetValidRegion();
       validRegion.SetEmpty();
       mTexImage = nsnull;
       mTexImageOnWhite = nsnull;
       mBufferRect.SetRect(0, 0, 0, 0);
       mBufferRotation.MoveTo(0, 0);
       // Restart decision process with the cleared buffer. We can only go
       // around the loop one more iteration, since mTexImage is null now.
@@ -529,30 +478,27 @@ BasicBufferOGL::BeginPaint(ContentType a
 
     break;
   }
 
   result.mRegionToDraw.Sub(neededRegion, validRegion);
   if (result.mRegionToDraw.IsEmpty())
     return result;
 
-  if (destBufferDims.width > gl()->GetMaxTextureSize() ||
-      destBufferDims.height > gl()->GetMaxTextureSize()) {
+  if (destBufferRect.width > gl()->GetMaxTextureSize() ||
+      destBufferRect.height > gl()->GetMaxTextureSize()) {
     return result;
   }
 
   nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
   nsRefPtr<TextureImage> destBuffer;
   nsRefPtr<TextureImage> destBufferOnWhite;
 
   PRUint32 bufferFlags = canHaveRotation ? ALLOW_REPEAT : 0;
   if (canReuseBuffer) {
-    NS_ASSERTION(curXRes == aXResolution && curYRes == aYResolution,
-                 "resolution changes must clear the buffer!");
-
     nsIntRect keepArea;
     if (keepArea.IntersectRect(destBufferRect, mBufferRect)) {
       // Set mBufferRotation so that the pixels currently in mBuffer
       // will still be rendered in the right place when mBufferRect
       // changes to destBufferRect.
       nsIntPoint newRotation = mBufferRotation +
         (destBufferRect.TopLeft() - mBufferRect.TopLeft());
       WrapRotationAxis(&newRotation.x, mBufferRect.width);
@@ -566,45 +512,45 @@ BasicBufferOGL::BeginPaint(ContentType a
           (newRotation != nsIntPoint(0,0) && !canHaveRotation)) {
         // The stuff we need to redraw will wrap around an edge of the
         // buffer, so we will need to do a self-copy
         // If mBufferRotation == nsIntPoint(0,0) we could do a real
         // self-copy but we're not going to do that in GL yet.
         // We can't do a real self-copy because the buffer is rotated.
         // So allocate a new buffer for the destination.
         destBufferRect = neededRegion.GetBounds();
-        destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferDims, contentType, bufferFlags);
+        destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
         if (!destBuffer)
           return result;
         if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
           destBufferOnWhite =
-            CreateClampOrRepeatTextureImage(gl(), destBufferDims, contentType, bufferFlags);
+            CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
           if (!destBufferOnWhite)
             return result;
         }
       } else {
         mBufferRect = destBufferRect;
         mBufferRotation = newRotation;
       }
     } else {
       // No pixels are going to be kept. The whole visible region
       // will be redrawn, so we don't need to copy anything, so we don't
       // set destBuffer.
       mBufferRect = destBufferRect;
       mBufferRotation = nsIntPoint(0,0);
     }
   } else {
     // The buffer's not big enough, so allocate a new one
-    destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferDims, contentType, bufferFlags);
+    destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
     if (!destBuffer)
       return result;
 
     if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
       destBufferOnWhite = 
-        CreateClampOrRepeatTextureImage(gl(), destBufferDims, contentType, bufferFlags);
+        CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
       if (!destBufferOnWhite)
         return result;
     }
   }
   NS_ASSERTION(!(aFlags & PAINT_WILL_RESAMPLE) || destBufferRect == neededRegion.GetBounds(),
                "If we're resampling, we need to validate the entire buffer");
 
   if (!destBuffer && !mTexImage) {
@@ -618,34 +564,31 @@ BasicBufferOGL::BeginPaint(ContentType a
       if (mOGLLayer->OGLManager()->FBOTextureTarget() == LOCAL_GL_TEXTURE_2D) {
         nsIntRect overlap;
         overlap.IntersectRect(mBufferRect, destBufferRect);
 
         nsIntRect srcRect(overlap), dstRect(overlap);
         srcRect.MoveBy(- mBufferRect.TopLeft() + mBufferRotation);
         dstRect.MoveBy(- destBufferRect.TopLeft());
 
-        nsIntSize size = ScaledSize(destBufferRect.Size(), aXResolution, aYResolution);
-        destBuffer->Resize(size);
-        srcRect.ScaleRoundOut(aXResolution, aYResolution);
-        dstRect.ScaleRoundOut(aXResolution, aYResolution);
+        destBuffer->Resize(destBufferRect.Size());
 
         gl()->BlitTextureImage(mTexImage, srcRect,
                                destBuffer, dstRect);
         if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
-          destBufferOnWhite->Resize(size);
+          destBufferOnWhite->Resize(destBufferRect.Size());
           gl()->BlitTextureImage(mTexImageOnWhite, srcRect,
                                  destBufferOnWhite, dstRect);
         }
       } else {
         // can't blit, just draw everything
-        destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferDims, contentType, bufferFlags);
+        destBuffer = CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
         if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
           destBufferOnWhite = 
-            CreateClampOrRepeatTextureImage(gl(), destBufferDims, contentType, bufferFlags);
+            CreateClampOrRepeatTextureImage(gl(), destBufferRect.Size(), contentType, bufferFlags);
         }
       }
     }
 
     mTexImage = destBuffer.forget();
     if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
       mTexImageOnWhite = destBufferOnWhite.forget();
     }
@@ -667,17 +610,16 @@ BasicBufferOGL::BeginPaint(ContentType a
   nsIntRect quadrantRect = GetQuadrantRectangle(sideX, sideY);
   NS_ASSERTION(quadrantRect.Contains(drawBounds), "Messed up quadrants");
 
   nsIntPoint offset = -nsIntPoint(quadrantRect.x, quadrantRect.y);
 
   // Make the region to draw relative to the buffer, before
   // passing to BeginUpdate.
   result.mRegionToDraw.MoveBy(offset);
-  result.mRegionToDraw.ScaleRoundOut(aXResolution, aYResolution);
   // BeginUpdate is allowed to modify the given region,
   // if it wants more to be repainted than we request.
   if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
     nsIntRegion drawRegionCopy = result.mRegionToDraw;
     gfxASurface *onBlack = mTexImage->BeginUpdate(drawRegionCopy);
     gfxASurface *onWhite = mTexImageOnWhite->BeginUpdate(result.mRegionToDraw);
     NS_ASSERTION(result.mRegionToDraw == drawRegionCopy,
                  "BeginUpdate should always modify the draw region in the same way!");
@@ -706,25 +648,20 @@ BasicBufferOGL::BeginPaint(ContentType a
       result.mContext->Paint();
       result.mContext->SetOperator(gfxContext::OPERATOR_OVER);
     }
   }
   if (!result.mContext) {
     NS_WARNING("unable to get context for update");
     return result;
   }
-  result.mContext->Scale(aXResolution, aYResolution);
   result.mContext->Translate(-gfxPoint(quadrantRect.x, quadrantRect.y));
   // Move rgnToPaint back into position so that the thebes callback
   // gets the right coordintes.
-  result.mRegionToDraw.ScaleRoundOut(1/aXResolution, 1/aYResolution);
   result.mRegionToDraw.MoveBy(-offset);
-  // Round our region out to values that will scale cleanly by the given
-  // resolution.
-  result.mRegionToDraw.ExtendForScaling(aXResolution, aYResolution);
   
   return result;
 }
 
 ThebesLayerOGL::ThebesLayerOGL(LayerManagerOGL *aManager)
   : ThebesLayer(aManager, nsnull)
   , LayerOGL(aManager)
   , mBuffer(nsnull)
@@ -790,40 +727,30 @@ ThebesLayerOGL::RenderLayer(int aPreviou
   mOGLManager->MakeCurrent();
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
 
   TextureImage::ContentType contentType =
     CanUseOpaqueSurface() ? gfxASurface::CONTENT_COLOR :
                             gfxASurface::CONTENT_COLOR_ALPHA;
 
   gfxMatrix transform2d;
-  gfxSize scale(1.0, 1.0);
-  float paintXRes = 1.0;
-  float paintYRes = 1.0;
   PRUint32 flags = 0;
   if (GetEffectiveTransform().Is2D(&transform2d)) {
-    scale = transform2d.ScaleFactors(PR_TRUE);
-    paintXRes = gfxUtils::ClampToScaleFactor(scale.width);
-    paintYRes = gfxUtils::ClampToScaleFactor(scale.height);
-    transform2d.Scale(1.0/paintXRes, 1.0/paintYRes);
     if (transform2d.HasNonIntegerTranslation()) {
       flags |= ThebesLayerBufferOGL::PAINT_WILL_RESAMPLE;
     }
   } else {
     flags |= ThebesLayerBufferOGL::PAINT_WILL_RESAMPLE;
   }
 
-  Buffer::PaintState state =
-    mBuffer->BeginPaint(contentType, paintXRes, paintYRes, flags);
+  Buffer::PaintState state = mBuffer->BeginPaint(contentType, flags);
   mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
 
   if (state.mContext) {
     state.mRegionToInvalidate.And(state.mRegionToInvalidate, mVisibleRegion);
-    mXResolution = paintXRes;
-    mYResolution = paintYRes;
 
     LayerManager::DrawThebesLayerCallback callback =
       mOGLManager->GetThebesLayerCallback();
     if (!callback) {
       NS_ERROR("GL should never need to update ThebesLayers in an empty transaction");
     } else {
       void* callbackData = mOGLManager->GetThebesLayerCallbackData();
       SetAntialiasingFlags(this, state.mContext);
@@ -861,18 +788,17 @@ ThebesLayerOGL::IsEmpty()
 
 class ShadowBufferOGL : public ThebesLayerBufferOGL
 {
 public:
   ShadowBufferOGL(ShadowThebesLayerOGL* aLayer)
     : ThebesLayerBufferOGL(aLayer, aLayer)
   {}
 
-  virtual PaintState BeginPaint(ContentType aContentType,
-                                float, float, PRUint32) {
+  virtual PaintState BeginPaint(ContentType aContentType, PRUint32) {
     NS_RUNTIMEABORT("can't BeginPaint for a shadow layer");
     return PaintState();
   }
 
   void Upload(gfxASurface* aUpdate, const nsIntRegion& aUpdated,
               const nsIntRect& aRect, const nsIntPoint& aRotation);
 
 protected:
@@ -898,36 +824,18 @@ ShadowBufferOGL::Upload(gfxASurface* aUp
   }
 
   nsIntRegion destRegion(aUpdated);
   // aUpdated is in screen coordinates.  Move it so that the layer's
   // top-left is 0,0
   nsIntPoint visTopLeft = mLayer->GetVisibleRegion().GetBounds().TopLeft();
   destRegion.MoveBy(-visTopLeft);
 
-  // |aUpdated|, |aRect|, and |aRotation| are in thebes-layer space,
-  // unadjusted for resolution.  The texture is in device space, so
-  // first we need to map the update params to device space.
-  //
-  // XXX this prematurely commits us to updating rects instead of
-  // regions here.  This will be a perf penalty on platforms that
-  // support region updates.  This is OK for now because the
-  // TextureImage backends we care about need to update contiguous
-  // rects anyway, and would do this conversion internally.  To fix
-  // this, we would need to scale the region instead of its bounds
-  // here.
-  nsIntRect destBounds = destRegion.GetBounds();
-  gfxRect destRect(destBounds.x, destBounds.y, destBounds.width, destBounds.height);
-  destRect.Scale(mLayer->GetXResolution(), mLayer->GetYResolution());
-  destRect.RoundOut();
-
   // NB: this gfxContext must not escape EndUpdate() below
-  nsIntRegion scaledDestRegion(nsIntRect(destRect.X(), destRect.Y(),
-                                         destRect.Width(), destRect.Height()));
-  mTexImage->DirectUpdate(aUpdate, scaledDestRegion);
+  mTexImage->DirectUpdate(aUpdate, destRegion);
 
   mBufferRect = aRect;
   mBufferRotation = aRotation;
 }
 
 ShadowThebesLayerOGL::ShadowThebesLayerOGL(LayerManagerOGL *aManager)
   : ShadowThebesLayer(aManager, nsnull)
   , LayerOGL(aManager)
@@ -935,18 +843,17 @@ ShadowThebesLayerOGL::ShadowThebesLayerO
   mImplData = static_cast<LayerOGL*>(this);
 }
 
 ShadowThebesLayerOGL::~ShadowThebesLayerOGL()
 {}
 
 void
 ShadowThebesLayerOGL::SetFrontBuffer(const OptionalThebesBuffer& aNewFront,
-                                     const nsIntRegion& aValidRegion,
-                                     float aXResolution, float aYResolution)
+                                     const nsIntRegion& aValidRegion)
 {
   if (mDestroyed) {
     return;
   }
 
   if (!mBuffer) {
     mBuffer = new ShadowBufferOGL(this);
   }
@@ -955,29 +862,26 @@ ShadowThebesLayerOGL::SetFrontBuffer(con
                "Only one system-memory buffer expected");
 }
 
 void
 ShadowThebesLayerOGL::Swap(const ThebesBuffer& aNewFront,
                            const nsIntRegion& aUpdatedRegion,
                            ThebesBuffer* aNewBack,
                            nsIntRegion* aNewBackValidRegion,
-                           float* aNewXResolution, float* aNewYResolution,
                            OptionalThebesBuffer* aReadOnlyFront,
                            nsIntRegion* aFrontUpdatedRegion)
 {
   if (!mDestroyed && mBuffer) {
     nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront.buffer());
     mBuffer->Upload(surf, aUpdatedRegion, aNewFront.rect(), aNewFront.rotation());
   }
 
   *aNewBack = aNewFront;
   *aNewBackValidRegion = mValidRegion;
-  *aNewXResolution = mXResolution;
-  *aNewYResolution = mYResolution;
   *aReadOnlyFront = null_t();
   aFrontUpdatedRegion->SetEmpty();
 }
 
 void
 ShadowThebesLayerOGL::DestroyFrontBuffer()
 {
   mBuffer = nsnull;
--- a/gfx/layers/opengl/ThebesLayerOGL.h
+++ b/gfx/layers/opengl/ThebesLayerOGL.h
@@ -88,22 +88,20 @@ class ShadowThebesLayerOGL : public Shad
                              public LayerOGL
 {
 public:
   ShadowThebesLayerOGL(LayerManagerOGL *aManager);
   virtual ~ShadowThebesLayerOGL();
 
   // ShadowThebesLayer impl
   virtual void SetFrontBuffer(const OptionalThebesBuffer& aNewFront,
-                              const nsIntRegion& aValidRegion,
-                              float aXResolution, float aYResolution);
+                              const nsIntRegion& aValidRegion);
   virtual void
   Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
        ThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
-       float* aNewXResolution, float* aNewYResolution,
        OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion);
   virtual void DestroyFrontBuffer();
 
   virtual void Disconnect();
 
   // LayerOGL impl
   void Destroy();
   Layer* GetLayer();