[chromium] Do not multiply bounds by contentsScale in TiledLayerChromium and CanvasLa...
authordanakj@chromium.org <danakj@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Jun 2012 16:35:33 +0000 (16:35 +0000)
committerdanakj@chromium.org <danakj@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Jun 2012 16:35:33 +0000 (16:35 +0000)
https://bugs.webkit.org/show_bug.cgi?id=90103

Reviewed by Adrienne Walker.

Source/WebCore:

Non-integer scale factors can scale the bounds of a layer such that
different rounding is applied to the width and height in the content
bounds. We should never multiply bounds by contentsScale in order to
work correctly with non-integer scale factors. Instead, always use the
contentBounds/bounds ratio for width and height independently.

Tests: TiledLayerChromiumTest.nonIntegerContentsScaleIsNotDistortedDuringPaint
       TiledLayerChromiumTest.nonIntegerContentsScaleIsNotDistortedDuringInvalidation

* platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp:
(WebCore::BitmapCanvasLayerTextureUpdater::prepareToUpdate):
* platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h:
(BitmapCanvasLayerTextureUpdater):
* platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp:
(WebCore::BitmapSkPictureCanvasLayerTextureUpdater::prepareToUpdate):
* platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h:
(BitmapSkPictureCanvasLayerTextureUpdater):
* platform/graphics/chromium/CanvasLayerTextureUpdater.cpp:
(WebCore::CanvasLayerTextureUpdater::paintContents):
* platform/graphics/chromium/CanvasLayerTextureUpdater.h:
(CanvasLayerTextureUpdater):
* platform/graphics/chromium/LayerTextureUpdater.h:
(WebCore::LayerTextureUpdater::prepareToUpdate):
* platform/graphics/chromium/ScrollbarLayerChromium.cpp:
(WebCore::ScrollbarLayerChromium::updatePart):
* platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp:
(WebCore::SkPictureCanvasLayerTextureUpdater::prepareToUpdate):
* platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h:
(SkPictureCanvasLayerTextureUpdater):
* platform/graphics/chromium/TiledLayerChromium.cpp:
(WebCore::TiledLayerChromium::setNeedsDisplayRect):
(WebCore::TiledLayerChromium::updateTiles):

Source/WebKit/chromium:

* tests/CCTiledLayerTestCommon.cpp:
(WebKitTests::FakeLayerTextureUpdater::prepareToUpdate):
* tests/CCTiledLayerTestCommon.h:
(FakeTiledLayerChromium):
* tests/TiledLayerChromiumTest.cpp:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@121436 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp
Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h
Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp
Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h
Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp
Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h
Source/WebCore/platform/graphics/chromium/LayerTextureUpdater.h
Source/WebCore/platform/graphics/chromium/ScrollbarLayerChromium.cpp
Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp
Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h
Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/tests/CCTiledLayerTestCommon.cpp
Source/WebKit/chromium/tests/CCTiledLayerTestCommon.h
Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp

index ed6b30e..4ecf36b 100644 (file)
@@ -1,3 +1,43 @@
+2012-06-27  Dana Jansens  <danakj@chromium.org>
+
+        [chromium] Do not multiply bounds by contentsScale in TiledLayerChromium and CanvasLayerTextureUpdater
+        https://bugs.webkit.org/show_bug.cgi?id=90103
+
+        Reviewed by Adrienne Walker.
+
+        Non-integer scale factors can scale the bounds of a layer such that
+        different rounding is applied to the width and height in the content
+        bounds. We should never multiply bounds by contentsScale in order to
+        work correctly with non-integer scale factors. Instead, always use the
+        contentBounds/bounds ratio for width and height independently.
+
+        Tests: TiledLayerChromiumTest.nonIntegerContentsScaleIsNotDistortedDuringPaint
+               TiledLayerChromiumTest.nonIntegerContentsScaleIsNotDistortedDuringInvalidation
+
+        * platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp:
+        (WebCore::BitmapCanvasLayerTextureUpdater::prepareToUpdate):
+        * platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.h:
+        (BitmapCanvasLayerTextureUpdater):
+        * platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp:
+        (WebCore::BitmapSkPictureCanvasLayerTextureUpdater::prepareToUpdate):
+        * platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h:
+        (BitmapSkPictureCanvasLayerTextureUpdater):
+        * platform/graphics/chromium/CanvasLayerTextureUpdater.cpp:
+        (WebCore::CanvasLayerTextureUpdater::paintContents):
+        * platform/graphics/chromium/CanvasLayerTextureUpdater.h:
+        (CanvasLayerTextureUpdater):
+        * platform/graphics/chromium/LayerTextureUpdater.h:
+        (WebCore::LayerTextureUpdater::prepareToUpdate):
+        * platform/graphics/chromium/ScrollbarLayerChromium.cpp:
+        (WebCore::ScrollbarLayerChromium::updatePart):
+        * platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp:
+        (WebCore::SkPictureCanvasLayerTextureUpdater::prepareToUpdate):
+        * platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.h:
+        (SkPictureCanvasLayerTextureUpdater):
+        * platform/graphics/chromium/TiledLayerChromium.cpp:
+        (WebCore::TiledLayerChromium::setNeedsDisplayRect):
+        (WebCore::TiledLayerChromium::updateTiles):
+
 2012-06-28  Bruno de Oliveira Abinader  <bruno.abinader@basyskom.com>
 
         [Qt] Make GC's fill{Rounded}Rect use optimized shadow blur code
index 526bd30..f5df26f 100644 (file)
@@ -79,7 +79,7 @@ LayerTextureUpdater::SampledTexelFormat BitmapCanvasLayerTextureUpdater::sampled
             LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA;
 }
 
-void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsScale, IntRect& resultingOpaqueRect)
+void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect)
 {
     m_texSubImage.setSubImageSize(tileSize);
 
@@ -88,7 +88,7 @@ void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect
         m_canvas = adoptPtr(skia::CreateBitmapCanvas(m_canvasSize.width(), m_canvasSize.height(), m_opaque));
     }
 
-    paintContents(m_canvas.get(), contentRect, contentsScale, resultingOpaqueRect);
+    paintContents(m_canvas.get(), contentRect, contentsWidthScale, contentsHeightScale, resultingOpaqueRect);
 }
 
 void BitmapCanvasLayerTextureUpdater::updateTextureRect(CCGraphicsContext* context, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect)
index 3c95380..28d2ba1 100644 (file)
@@ -61,7 +61,7 @@ public:
 
     virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager*);
     virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat);
-    virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsScale, IntRect& resultingOpaqueRect) OVERRIDE;
+    virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect) OVERRIDE;
     void updateTextureRect(CCGraphicsContext*, TextureAllocator*, ManagedTexture*, const IntRect& sourceRect, const IntRect& destRect);
 
     virtual void setOpaque(bool) OVERRIDE;
index 71b390f..a854050 100644 (file)
@@ -90,10 +90,10 @@ LayerTextureUpdater::SampledTexelFormat BitmapSkPictureCanvasLayerTextureUpdater
             LayerTextureUpdater::SampledTexelFormatRGBA : LayerTextureUpdater::SampledTexelFormatBGRA;
 }
 
-void BitmapSkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsScale, IntRect& resultingOpaqueRect)
+void BitmapSkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect)
 {
     m_texSubImage.setSubImageSize(tileSize);
-    SkPictureCanvasLayerTextureUpdater::prepareToUpdate(contentRect, tileSize, contentsScale, resultingOpaqueRect);
+    SkPictureCanvasLayerTextureUpdater::prepareToUpdate(contentRect, tileSize, contentsWidthScale, contentsHeightScale, resultingOpaqueRect);
 }
 
 void BitmapSkPictureCanvasLayerTextureUpdater::paintContentsRect(SkCanvas* canvas, const IntRect& sourceRect)
index 09481d2..0824c90 100644 (file)
@@ -57,7 +57,7 @@ public:
 
     virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager*) OVERRIDE;
     virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) OVERRIDE;
-    virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsScale, IntRect& resultingOpaqueRect) OVERRIDE;
+    virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect) OVERRIDE;
     void paintContentsRect(SkCanvas*, const IntRect& sourceRect);
     void updateTextureRect(CCGraphicsContext*, GC3Denum format, const IntRect& destRect, const uint8_t* pixels);
 
index 93dd7df..7bd0040 100644 (file)
@@ -48,7 +48,7 @@ CanvasLayerTextureUpdater::~CanvasLayerTextureUpdater()
 {
 }
 
-void CanvasLayerTextureUpdater::paintContents(SkCanvas* canvas, const IntRect& contentRect, float contentsScale, IntRect& resultingOpaqueRect)
+void CanvasLayerTextureUpdater::paintContents(SkCanvas* canvas, const IntRect& contentRect, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect)
 {
     TRACE_EVENT0("cc", "CanvasLayerTextureUpdater::paintContents");
     canvas->save();
@@ -56,11 +56,11 @@ void CanvasLayerTextureUpdater::paintContents(SkCanvas* canvas, const IntRect& c
 
     IntRect scaledContentRect = contentRect;
 
-    if (contentsScale != 1.0) {
-        canvas->scale(WebCoreFloatToSkScalar(contentsScale), WebCoreFloatToSkScalar(contentsScale));
+    if (contentsWidthScale != 1 || contentsHeightScale != 1) {
+        canvas->scale(WebCoreFloatToSkScalar(contentsWidthScale), WebCoreFloatToSkScalar(contentsHeightScale));
 
         FloatRect rect = contentRect;
-        rect.scale(1 / contentsScale);
+        rect.scale(1 / contentsWidthScale, 1 / contentsHeightScale);
         scaledContentRect = enclosingIntRect(rect);
     }
 
index c951e93..b441e4e 100644 (file)
@@ -47,7 +47,7 @@ public:
 protected:
     explicit CanvasLayerTextureUpdater(PassOwnPtr<LayerPainterChromium>);
 
-    void paintContents(SkCanvas*, const IntRect& contentRect, float contentsScale, IntRect& resultingOpaqueRect);
+    void paintContents(SkCanvas*, const IntRect& contentRect, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect);
     const IntRect& contentRect() const { return m_contentRect; }
 
 private:
index cec8ebc..6130e91 100644 (file)
@@ -73,7 +73,7 @@ public:
     virtual SampledTexelFormat sampledTexelFormat(GC3Denum textureFormat) = 0;
     // The |resultingOpaqueRect| gives back a region of the layer that was painted opaque. If the layer is marked opaque in the updater,
     // then this region should be ignored in preference for the entire layer's area.
-    virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsScale, IntRect& resultingOpaqueRect) { }
+    virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect) { }
 
     // Set true by the layer when it is known that the entire output is going to be opaque.
     virtual void setOpaque(bool) { }
index 1e1d1f3..1c47f0f 100644 (file)
@@ -247,7 +247,7 @@ void ScrollbarLayerChromium::updatePart(LayerTextureUpdater* painter, LayerTextu
 
     // Paint and upload the entire part.
     IntRect paintedOpaqueRect;
-    painter->prepareToUpdate(rect, rect.size(), 1, paintedOpaqueRect);
+    painter->prepareToUpdate(rect, rect.size(), 1, 1, paintedOpaqueRect);
     texture->prepareRect(rect);
 
     IntRect destRect(IntPoint(), rect.size());
index 3924d42..f7bdb6f 100644 (file)
@@ -46,10 +46,10 @@ SkPictureCanvasLayerTextureUpdater::~SkPictureCanvasLayerTextureUpdater()
 {
 }
 
-void SkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize&, float contentsScale, IntRect& resultingOpaqueRect)
+void SkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize&, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect)
 {
     SkCanvas* canvas = m_picture.beginRecording(contentRect.width(), contentRect.height());
-    paintContents(canvas, contentRect, contentsScale, resultingOpaqueRect);
+    paintContents(canvas, contentRect, contentsWidthScale, contentsHeightScale, resultingOpaqueRect);
     m_picture.endRecording();
 }
 
index e297e05..a51f44f 100644 (file)
@@ -52,7 +52,7 @@ public:
 protected:
     explicit SkPictureCanvasLayerTextureUpdater(PassOwnPtr<LayerPainterChromium>);
 
-    virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsScale, IntRect& resultingOpaqueRect) OVERRIDE;
+    virtual void prepareToUpdate(const IntRect& contentRect, const IntSize& tileSize, float contentsWidthScale, float contentsHeightScale, IntRect& resultingOpaqueRect) OVERRIDE;
     void drawPicture(SkCanvas*);
 
     bool layerIsOpaque() const { return m_layerIsOpaque; }
index 71f2fae..c4de329 100644 (file)
@@ -279,8 +279,10 @@ UpdatableTile* TiledLayerChromium::createTile(int i, int j)
 
 void TiledLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect)
 {
+    float contentsWidthScale = static_cast<float>(contentBounds().width()) / bounds().width();
+    float contentsHeightScale = static_cast<float>(contentBounds().height()) / bounds().height();
     FloatRect scaledDirtyRect(dirtyRect);
-    scaledDirtyRect.scale(contentsScale());
+    scaledDirtyRect.scale(contentsWidthScale, contentsHeightScale);
     IntRect dirty = enclosingIntRect(scaledDirtyRect);
     invalidateRect(dirty);
     LayerChromium::setNeedsDisplayRect(dirtyRect);
@@ -455,7 +457,7 @@ void TiledLayerChromium::updateTiles(bool idle, int left, int top, int right, in
     // so we grab a local reference here to hold the updater alive until the paint completes.
     RefPtr<LayerTextureUpdater> protector(textureUpdater());
     IntRect paintedOpaqueRect;
-    textureUpdater()->prepareToUpdate(paintRect, m_tiler->tileSize(), contentsScale(), paintedOpaqueRect);
+    textureUpdater()->prepareToUpdate(paintRect, m_tiler->tileSize(), 1 / widthScale, 1 / heightScale, paintedOpaqueRect);
     m_didPaint = true;
 
     for (int j = top; j <= bottom; ++j) {
index 4f31359..f5518b6 100644 (file)
@@ -1,3 +1,16 @@
+2012-06-27  Dana Jansens  <danakj@chromium.org>
+
+        [chromium] Do not multiply bounds by contentsScale in TiledLayerChromium and CanvasLayerTextureUpdater
+        https://bugs.webkit.org/show_bug.cgi?id=90103
+
+        Reviewed by Adrienne Walker.
+
+        * tests/CCTiledLayerTestCommon.cpp:
+        (WebKitTests::FakeLayerTextureUpdater::prepareToUpdate):
+        * tests/CCTiledLayerTestCommon.h:
+        (FakeTiledLayerChromium):
+        * tests/TiledLayerChromiumTest.cpp:
+
 2012-06-28  Dan Alcantara  <dfalcantara@chromium.org>
 
         [chromium] Introduce way to reload a page using the original request URL
index 7484b70..f014dd4 100644 (file)
@@ -63,7 +63,7 @@ FakeLayerTextureUpdater::~FakeLayerTextureUpdater()
 {
 }
 
-void FakeLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize&, float, IntRect& resultingOpaqueRect)
+void FakeLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize&, float, float, IntRect& resultingOpaqueRect)
 {
     m_prepareCount++;
     m_lastUpdateRect = contentRect;
index 614e1ee..172ab25 100644 (file)
@@ -61,7 +61,7 @@ public:
     virtual PassOwnPtr<WebCore::LayerTextureUpdater::Texture> createTexture(WebCore::TextureManager*) OVERRIDE;
     virtual SampledTexelFormat sampledTexelFormat(GC3Denum) OVERRIDE { return SampledTexelFormatRGBA; }
 
-    virtual void prepareToUpdate(const WebCore::IntRect& contentRect, const WebCore::IntSize&, float, WebCore::IntRect& resultingOpaqueRect) OVERRIDE;
+    virtual void prepareToUpdate(const WebCore::IntRect& contentRect, const WebCore::IntSize&, float, float, WebCore::IntRect& resultingOpaqueRect) OVERRIDE;
     // Sets the rect to invalidate during the next call to prepareToUpdate(). After the next
     // call to prepareToUpdate() the rect is reset.
     void setRectToInvalidate(const WebCore::IntRect&, FakeTiledLayerChromium*);
@@ -128,10 +128,11 @@ public:
     FakeLayerTextureUpdater* fakeLayerTextureUpdater() { return m_fakeTextureUpdater.get(); }
     WebCore::FloatRect updateRect() { return m_updateRect; }
 
-private:
+protected:
     virtual WebCore::LayerTextureUpdater* textureUpdater() const OVERRIDE { return m_fakeTextureUpdater.get(); }
     virtual void createTextureUpdaterIfNeeded() OVERRIDE { }
 
+private:
     RefPtr<FakeLayerTextureUpdater> m_fakeTextureUpdater;
     WebCore::TextureManager* m_textureManager;
     WebCore::FloatRect m_lastNeedsDisplayRect;
index 04b3c38..f09106d 100644 (file)
 
 #include "TiledLayerChromium.h"
 
+#include "BitmapCanvasLayerTextureUpdater.h"
 #include "CCAnimationTestCommon.h"
 #include "CCLayerTreeTestCommon.h"
 #include "CCTiledLayerTestCommon.h"
 #include "FakeCCLayerTreeHostClient.h"
+#include "LayerPainterChromium.h"
 #include "WebCompositor.h"
 #include "cc/CCOverdrawMetrics.h"
 #include "cc/CCSingleThreadProxy.h" // For DebugScopedSetImplThread
@@ -1377,4 +1379,99 @@ TEST(TiledLayerChromiumTest, pixelsPaintedMetrics)
     EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
 }
 
+class TrackingLayerPainter : public LayerPainterChromium {
+public:
+    static PassOwnPtr<TrackingLayerPainter> create() { return adoptPtr(new TrackingLayerPainter()); }
+
+    virtual void paint(SkCanvas*, const IntRect& contentRect, IntRect&)
+    {
+        m_paintedRect = contentRect;
+    }
+
+    const IntRect& paintedRect() const { return m_paintedRect; }
+    void resetPaintedRect() { m_paintedRect = IntRect(); }
+
+private:
+    TrackingLayerPainter() { }
+
+    IntRect m_paintedRect;
+};
+
+class UpdateTrackingTiledLayerChromium : public FakeTiledLayerChromium {
+public:
+    explicit UpdateTrackingTiledLayerChromium(WebCore::TextureManager* manager)
+        : FakeTiledLayerChromium(manager)
+    {
+        OwnPtr<TrackingLayerPainter> trackingLayerPainter(TrackingLayerPainter::create());
+        m_trackingLayerPainter = trackingLayerPainter.get();
+        m_layerTextureUpdater = BitmapCanvasLayerTextureUpdater::create(trackingLayerPainter.release(), false);
+    }
+    virtual ~UpdateTrackingTiledLayerChromium() { }
+
+    TrackingLayerPainter* trackingLayerPainter() const { return m_trackingLayerPainter; }
+
+protected:
+    virtual WebCore::LayerTextureUpdater* textureUpdater() const OVERRIDE { return m_layerTextureUpdater.get(); }
+
+private:
+    TrackingLayerPainter* m_trackingLayerPainter;
+    RefPtr<BitmapCanvasLayerTextureUpdater> m_layerTextureUpdater;
+};
+
+TEST(TiledLayerChromiumTest, nonIntegerContentsScaleIsNotDistortedDuringPaint)
+{
+    OwnPtr<TextureManager> textureManager(TextureManager::create(4000000, 4000000, 4000000));
+    CCTextureUpdater updater;
+
+    RefPtr<UpdateTrackingTiledLayerChromium> layer = adoptRef(new UpdateTrackingTiledLayerChromium(textureManager.get()));
+
+    IntRect layerRect(0, 0, 30, 31);
+    layer->setPosition(layerRect.location());
+    layer->setBounds(layerRect.size());
+    layer->setContentsScale(1.5);
+
+    IntRect contentRect(0, 0, 45, 47);
+    EXPECT_EQ(contentRect.size(), layer->contentBounds());
+    layer->setVisibleLayerRect(contentRect);
+
+    // Update the whole tile.
+    layer->updateLayerRect(updater, contentRect, 0);
+    layer->trackingLayerPainter()->resetPaintedRect();
+
+    EXPECT_INT_RECT_EQ(IntRect(), layer->trackingLayerPainter()->paintedRect());
+
+    // Invalidate the entire layer in content space. When painting, the rect given to webkit should match the layer's bounds.
+    layer->invalidateRect(contentRect);
+    layer->updateLayerRect(updater, contentRect, 0);
+
+    EXPECT_INT_RECT_EQ(layerRect, layer->trackingLayerPainter()->paintedRect());
+}
+
+TEST(TiledLayerChromiumTest, nonIntegerContentsScaleIsNotDistortedDuringInvalidation)
+{
+    OwnPtr<TextureManager> textureManager(TextureManager::create(4000000, 4000000, 4000000));
+    CCTextureUpdater updater;
+
+    RefPtr<UpdateTrackingTiledLayerChromium> layer = adoptRef(new UpdateTrackingTiledLayerChromium(textureManager.get()));
+
+    IntRect layerRect(0, 0, 30, 31);
+    layer->setPosition(layerRect.location());
+    layer->setBounds(layerRect.size());
+    layer->setContentsScale(1.3);
+
+    IntRect contentRect(IntPoint(), layer->contentBounds());
+
+    // Update the whole tile.
+    layer->updateLayerRect(updater, contentRect, 0);
+    layer->trackingLayerPainter()->resetPaintedRect();
+
+    EXPECT_INT_RECT_EQ(IntRect(), layer->trackingLayerPainter()->paintedRect());
+
+    // Invalidate the entire layer in layer space. When painting, the rect given to webkit should match the layer's bounds.
+    layer->setNeedsDisplayRect(layerRect);
+    layer->updateLayerRect(updater, contentRect, 0);
+
+    EXPECT_INT_RECT_EQ(layerRect, layer->trackingLayerPainter()->paintedRect());
+}
+
 } // namespace