Modified: trunk/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp (104779 => 104780)
--- trunk/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp 2012-01-12 02:03:36 UTC (rev 104779)
+++ trunk/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp 2012-01-12 02:26:02 UTC (rev 104780)
@@ -59,7 +59,11 @@
ManagedTexture* managedTexture() { return m_texture->texture(); }
bool isDirty() const { return !m_dirtyRect.isEmpty(); }
- void clearDirty() { m_dirtyRect = IntRect(); }
+ void copyAndClearDirty()
+ {
+ m_updateRect = m_dirtyRect;
+ m_dirtyRect = IntRect();
+ }
IntRect m_dirtyRect;
IntRect m_updateRect;
@@ -366,7 +370,9 @@
}
// Create tiles as needed, expanding a dirty rect to contain all
- // the dirty regions currently being drawn.
+ // the dirty regions currently being drawn. All dirty tiles that are to be painted
+ // get their m_updateRect set to m_dirtyRect and m_dirtyRect cleared. This way if
+ // invalidateRect is invoked during prepareToUpdate we don't lose the request.
IntRect dirtyLayerRect;
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
@@ -387,6 +393,7 @@
}
dirtyLayerRect.unite(tile->m_dirtyRect);
+ tile->copyAndClearDirty();
}
}
@@ -414,19 +421,17 @@
if (!tile)
CRASH();
- if (!tile->isDirty())
+ // Use m_updateRect as copyAndClearDirty above moved the existing dirty rect to m_updateRect.
+ const IntRect& dirtyRect = tile->m_updateRect;
+ if (dirtyRect.isEmpty())
continue;
IntRect sourceRect = m_tiler->tileRect(tile);
- sourceRect.intersect(tile->m_dirtyRect);
+ sourceRect.intersect(dirtyRect);
// Paint rect not guaranteed to line up on tile boundaries, so
// make sure that sourceRect doesn't extend outside of it.
sourceRect.intersect(m_paintRect);
- // updateCompositorResources() uses m_updateRect to determine
- // the tiles to update so we can clear the dirty rectangle here.
- tile->clearDirty();
-
tile->m_updateRect = sourceRect;
if (sourceRect.isEmpty())
continue;
Modified: trunk/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp (104779 => 104780)
--- trunk/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp 2012-01-12 02:03:36 UTC (rev 104779)
+++ trunk/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp 2012-01-12 02:26:02 UTC (rev 104780)
@@ -44,6 +44,8 @@
virtual void deleteTexture(unsigned, const IntSize&, GC3Denum) { }
};
+class FakeTiledLayerChromium;
+
class FakeLayerTextureUpdater : public LayerTextureUpdater {
public:
class Texture : public LayerTextureUpdater::Texture {
@@ -54,12 +56,29 @@
virtual void updateRect(GraphicsContext3D*, TextureAllocator*, const IntRect&, const IntRect&) { }
};
- FakeLayerTextureUpdater() { }
+ FakeLayerTextureUpdater() : m_prepareCount(0) { }
virtual ~FakeLayerTextureUpdater() { }
+ // Sets the rect to invalidate during the next call to prepareToUpdate(). After the next
+ // call to prepareToUpdate() the rect is reset.
+ void setRectToInvalidate(const IntRect&, FakeTiledLayerChromium*);
+
+ // Number of times prepareToUpdate has been invoked.
+ int prepareCount() const { return m_prepareCount; }
+ void clearPrepareCount() { m_prepareCount = 0; }
+
+ // Last rect passed to prepareToUpdate().
+ const IntRect& lastUpdateRect() const { return m_lastUpdateRect; }
+
virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager* manager) { return adoptPtr(new Texture(ManagedTexture::create(manager))); }
virtual SampledTexelFormat sampledTexelFormat(GC3Denum) { return SampledTexelFormatRGBA; }
- virtual void prepareToUpdate(const IntRect&, const IntSize&, int, float) { }
+ virtual void prepareToUpdate(const IntRect& contentRect, const IntSize&, int, float);
+
+private:
+ int m_prepareCount;
+ IntRect m_rectToInvalidate;
+ IntRect m_lastUpdateRect;
+ RefPtr<FakeTiledLayerChromium> m_layer;
};
class FakeCCTiledLayerImpl : public CCTiledLayerImpl {
@@ -108,6 +127,8 @@
return TiledLayerChromium::needsIdlePaint(rect);
}
+ FakeLayerTextureUpdater* fakeLayerTextureUpdater() { return m_fakeTextureUpdater.get(); }
+
virtual TextureManager* textureManager() const { return m_textureManager; }
private:
@@ -122,6 +143,23 @@
TextureManager* m_textureManager;
};
+void FakeLayerTextureUpdater::setRectToInvalidate(const IntRect& rect, FakeTiledLayerChromium* layer)
+{
+ m_rectToInvalidate = rect;
+ m_layer = layer;
+}
+
+void FakeLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize&, int, float)
+{
+ m_prepareCount++;
+ m_lastUpdateRect = contentRect;
+ if (!m_rectToInvalidate.isEmpty()) {
+ m_layer->invalidateRect(m_rectToInvalidate);
+ m_rectToInvalidate = IntRect();
+ m_layer = 0;
+ }
+}
+
TEST(TiledLayerChromiumTest, pushDirtyTiles)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
@@ -259,4 +297,45 @@
layer->pushPropertiesTo(layerImpl.get());
}
+TEST(TiledLayerChromiumTest, invalidateFromPrepare)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ DebugScopedSetImplThread implThread;
+ RefPtr<FakeCCTiledLayerImpl> layerImpl = adoptRef(new FakeCCTiledLayerImpl(0));
+
+ FakeTextureAllocator textureAllocator;
+ CCTextureUpdater updater(&textureAllocator);
+
+ // The tile size is 100x100, so this invalidates and then paints two tiles.
+ layer->setBounds(IntSize(100, 200));
+ layer->invalidateRect(IntRect(0, 0, 100, 200));
+ layer->prepareToUpdate(IntRect(0, 0, 100, 200));
+ layer->updateCompositorResources(0, updater);
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should have both tiles on the impl side.
+ EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
+ EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
+
+ textureManager->unprotectAllTextures();
+
+ layer->fakeLayerTextureUpdater()->clearPrepareCount();
+ // Invoke prepareToUpdate again. As the layer is valid prepareToUpdate shouldn't be invoked on
+ // the LayerTextureUpdater.
+ layer->prepareToUpdate(IntRect(0, 0, 100, 200));
+ EXPECT_EQ(0, layer->fakeLayerTextureUpdater()->prepareCount());
+
+ layer->invalidateRect(IntRect(0, 0, 50, 50));
+ // setRectToInvalidate triggers invalidateRect() being invoked from prepareToUpdate.
+ layer->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(25, 25, 50, 50), layer.get());
+ layer->fakeLayerTextureUpdater()->clearPrepareCount();
+ layer->prepareToUpdate(IntRect(0, 0, 100, 200));
+ EXPECT_EQ(1, layer->fakeLayerTextureUpdater()->prepareCount());
+ layer->fakeLayerTextureUpdater()->clearPrepareCount();
+ // The layer should still be invalid as prepareToUpdate invoked invalidate.
+ layer->prepareToUpdate(IntRect(0, 0, 100, 200));
+ EXPECT_EQ(1, layer->fakeLayerTextureUpdater()->prepareCount());
+}
+
} // namespace