summaryrefslogtreecommitdiff
path: root/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
commit2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch)
tree988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
parentdd91e772430dc294e3bf478c119ef8d43c0a3358 (diff)
downloadqtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp')
-rw-r--r--Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp1046
1 files changed, 693 insertions, 353 deletions
diff --git a/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp b/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
index 2523230e0..5b7cb0df7 100644
--- a/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
+++ b/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp
@@ -26,18 +26,16 @@
#include "TiledLayerChromium.h"
+#include "CCAnimationTestCommon.h"
#include "CCLayerTreeTestCommon.h"
+#include "CCTiledLayerTestCommon.h"
#include "FakeCCLayerTreeHostClient.h"
-#include "LayerTextureUpdater.h"
-#include "Region.h"
-#include "TextureManager.h"
#include "WebCompositor.h"
#include "cc/CCSingleThreadProxy.h" // For DebugScopedSetImplThread
-#include "cc/CCTextureUpdater.h"
-#include "cc/CCTiledLayerImpl.h"
#include <gtest/gtest.h>
using namespace WebCore;
+using namespace WebKitTests;
using namespace WTF;
#define EXPECT_EQ_RECT(a, b) \
@@ -48,208 +46,38 @@ using namespace WTF;
namespace {
-class FakeTextureAllocator : public TextureAllocator {
+class TestCCOcclusionTracker : public CCOcclusionTracker {
public:
- virtual unsigned createTexture(const IntSize&, GC3Denum) { return 0; }
- virtual void deleteTexture(unsigned, const IntSize&, GC3Denum) { }
-};
-
-class FakeTiledLayerChromium;
-
-class FakeLayerTextureUpdater : public LayerTextureUpdater {
-public:
- class Texture : public LayerTextureUpdater::Texture {
- public:
- Texture(FakeLayerTextureUpdater* layer, PassOwnPtr<ManagedTexture> texture)
- : LayerTextureUpdater::Texture(texture)
- , m_layer(layer)
- {
- }
- virtual ~Texture() { }
-
- virtual void updateRect(GraphicsContext3D*, TextureAllocator*, const IntRect&, const IntRect&) { m_layer->updateRect(); }
- virtual void prepareRect(const IntRect&) { m_layer->prepareRect(); }
-
- private:
- FakeLayerTextureUpdater* m_layer;
- };
-
- FakeLayerTextureUpdater()
- : m_prepareCount(0)
- , m_updateCount(0)
- , m_prepareRectCount(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; }
-
- // Number of times updateRect has been invoked.
- int updateCount() const { return m_updateCount; }
- void clearUpdateCount() { m_updateCount = 0; }
- void updateRect() { m_updateCount++; }
-
- // Number of times prepareRect() has been invoked on a texture.
- int prepareRectCount() const { return m_prepareRectCount; }
- void clearPrepareRectCount() { m_prepareRectCount = 0; }
- void prepareRect() { m_prepareRectCount++; }
-
- void setOpaquePaintRect(const IntRect& opaquePaintRect) { m_opaquePaintRect = opaquePaintRect; }
-
- // Last rect passed to prepareToUpdate().
- const IntRect& lastUpdateRect() const { return m_lastUpdateRect; }
-
- virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager* manager) { return adoptPtr(new Texture(this, ManagedTexture::create(manager))); }
- virtual SampledTexelFormat sampledTexelFormat(GC3Denum) { return SampledTexelFormatRGBA; }
- virtual void prepareToUpdate(const IntRect& contentRect, const IntSize&, int, float, IntRect* resultingOpaqueRect);
-
-private:
- int m_prepareCount;
- int m_updateCount;
- int m_prepareRectCount;
- IntRect m_rectToInvalidate;
- IntRect m_lastUpdateRect;
- IntRect m_opaquePaintRect;
- RefPtr<FakeTiledLayerChromium> m_layer;
-};
-
-class FakeCCTiledLayerImpl : public CCTiledLayerImpl {
-public:
- explicit FakeCCTiledLayerImpl(int id)
- : CCTiledLayerImpl(id) { }
- virtual ~FakeCCTiledLayerImpl() { }
-
- bool hasTileAt(int i, int j)
+ TestCCOcclusionTracker()
+ : CCOcclusionTracker(IntRect(0, 0, 1000, 1000), true)
+ , m_scissorRectInScreen(IntRect(0, 0, 1000, 1000))
{
- return CCTiledLayerImpl::hasTileAt(i, j);
+ // Pretend we have visited a render surface.
+ m_stack.append(StackObject());
}
-};
-class FakeTiledLayerChromium : public TiledLayerChromium {
-public:
- explicit FakeTiledLayerChromium(TextureManager* textureManager)
- : TiledLayerChromium()
- , m_fakeTextureUpdater(adoptRef(new FakeLayerTextureUpdater))
- , m_textureManager(textureManager)
- {
- setTileSize(IntSize(100, 100));
- setTextureFormat(GraphicsContext3D::RGBA);
- setBorderTexelOption(CCLayerTilingData::NoBorderTexels);
- setIsDrawable(true); // So that we don't get false positives if any of these tests expect to return false from drawsContent() for other reasons.
- }
- virtual ~FakeTiledLayerChromium() { }
+ void setOcclusion(const Region& occlusion) { m_stack.last().occlusionInScreen = occlusion; }
- void invalidateRect(const IntRect& rect)
- {
- TiledLayerChromium::invalidateRect(rect);
- }
-
- void prepareToUpdate(const IntRect& rect, const Region& occluded)
- {
- TiledLayerChromium::prepareToUpdate(rect, occluded);
- }
-
- void prepareToUpdateIdle(const IntRect& rect, const Region& occluded)
- {
- TiledLayerChromium::prepareToUpdateIdle(rect, occluded);
- }
-
- bool needsIdlePaint(const IntRect& rect)
- {
- return TiledLayerChromium::needsIdlePaint(rect);
- }
-
- bool skipsDraw() const
- {
- return TiledLayerChromium::skipsDraw();
- }
-
- virtual void setNeedsDisplayRect(const FloatRect& rect)
- {
- m_lastNeedsDisplayRect = rect;
- TiledLayerChromium::setNeedsDisplayRect(rect);
- }
-
- const FloatRect& lastNeedsDisplayRect() const { return m_lastNeedsDisplayRect; }
-
- FakeLayerTextureUpdater* fakeLayerTextureUpdater() { return m_fakeTextureUpdater.get(); }
-
- virtual TextureManager* textureManager() const { return m_textureManager; }
-
- virtual void paintContentsIfDirty(const Region& occludedScreenSpace)
- {
- prepareToUpdate(visibleLayerRect(), occludedScreenSpace);
- }
+protected:
+ virtual IntRect layerScissorRectInTargetSurface(const LayerChromium* layer) const { return m_scissorRectInScreen; }
private:
- virtual LayerTextureUpdater* textureUpdater() const
- {
- return m_fakeTextureUpdater.get();
- }
-
- virtual void createTextureUpdaterIfNeeded() { }
-
- RefPtr<FakeLayerTextureUpdater> m_fakeTextureUpdater;
- TextureManager* m_textureManager;
- FloatRect m_lastNeedsDisplayRect;
+ IntRect m_scissorRectInScreen;
};
-class FakeTiledLayerWithScaledBounds : public FakeTiledLayerChromium {
-public:
- explicit FakeTiledLayerWithScaledBounds(TextureManager* textureManager)
- : FakeTiledLayerChromium(textureManager)
- {
- }
-
- void setContentBounds(const IntSize& contentBounds) { m_forcedContentBounds = contentBounds; }
- virtual IntSize contentBounds() const { return m_forcedContentBounds; }
-
- FloatRect updateRect() { return m_updateRect; }
-
-protected:
- IntSize m_forcedContentBounds;
-};
-
-void FakeLayerTextureUpdater::setRectToInvalidate(const IntRect& rect, FakeTiledLayerChromium* layer)
-{
- m_rectToInvalidate = rect;
- m_layer = layer;
-}
-
-void FakeLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize&, int, float, IntRect* resultingOpaqueRect)
-{
- m_prepareCount++;
- m_lastUpdateRect = contentRect;
- if (!m_rectToInvalidate.isEmpty()) {
- m_layer->invalidateRect(m_rectToInvalidate);
- m_rectToInvalidate = IntRect();
- m_layer = 0;
- }
- *resultingOpaqueRect = m_opaquePaintRect;
-}
-
TEST(TiledLayerChromiumTest, pushDirtyTiles)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
DebugScopedSetImplThread implThread;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- Region noOcclusion;
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
// 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), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
layer->pushPropertiesTo(layerImpl.get());
// We should have both tiles on the impl side.
@@ -261,8 +89,7 @@ TEST(TiledLayerChromiumTest, pushDirtyTiles)
// Invalidates both tiles...
layer->invalidateRect(IntRect(0, 0, 100, 200));
// ....but then only update one of them.
- layer->prepareToUpdate(IntRect(0, 0, 100, 100), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 100), 0);
layer->pushPropertiesTo(layerImpl.get());
// We should only have the first tile since the other tile was invalidated but not painted.
@@ -276,18 +103,22 @@ TEST(TiledLayerChromiumTest, pushOccludedDirtyTiles)
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
DebugScopedSetImplThread implThread;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- Region noOcclusion;
+ TestCCOcclusionTracker occluded;
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
// The tile size is 100x100, so this invalidates and then paints two tiles.
layer->setBounds(IntSize(100, 200));
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
+ layer->setVisibleLayerRect(IntRect(0, 0, 100, 200));
layer->invalidateRect(IntRect(0, 0, 100, 200));
- layer->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), &occluded);
layer->pushPropertiesTo(layerImpl.get());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
// We should have both tiles on the impl side.
EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
@@ -297,16 +128,59 @@ TEST(TiledLayerChromiumTest, pushOccludedDirtyTiles)
// Invalidates part of the top tile...
layer->invalidateRect(IntRect(0, 0, 50, 50));
// ....but the area is occluded.
- Region occlusion(IntRect(0, 0, 50, 50));
- layer->prepareToUpdate(IntRect(0, 0, 100, 100), occlusion);
- layer->updateCompositorResources(0, updater);
+ occluded.setOcclusion(IntRect(0, 0, 50, 50));
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 100), &occluded);
layer->pushPropertiesTo(layerImpl.get());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 + 2500, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
// We should still have both tiles, as part of the top tile is still unoccluded.
EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
}
+TEST(TiledLayerChromiumTest, pushDeletedTiles)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+
+ CCTextureUpdater updater;
+ FakeTextureAllocator allocator;
+
+ // 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->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
+ 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->evictAndDeleteAllTextures(&allocator);
+ textureManager->setMaxMemoryLimitBytes(4*1024*1024);
+ textureManager->setPreferredMemoryLimitBytes(4*1024*1024);
+
+ // This should drop the tiles on the impl thread.
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should now have no textures on the impl thread.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
+
+ // This should recreate and update the deleted textures.
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 100), 0);
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should only have the first tile since the other tile was invalidated but not painted.
+ EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
+}
+
TEST(TiledLayerChromiumTest, pushIdlePaintTiles)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
@@ -314,25 +188,22 @@ TEST(TiledLayerChromiumTest, pushIdlePaintTiles)
DebugScopedSetImplThread implThread;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
// The tile size is 100x100. Setup 5x5 tiles with one visible tile in the center.
IntSize contentBounds(500, 500);
IntRect contentRect(IntPoint::zero(), contentBounds);
IntRect visibleRect(200, 200, 100, 100);
- Region noOcclusion;
// This invalidates 25 tiles and then paints one visible tile.
layer->setBounds(contentBounds);
layer->setVisibleLayerRect(visibleRect);
layer->invalidateRect(contentRect);
- layer->prepareToUpdate(visibleRect, noOcclusion);
+ layer->updateLayerRect(updater, visibleRect, 0);
// We should need idle-painting for 3x3 tiles in the center.
EXPECT_TRUE(layer->needsIdlePaint(visibleRect));
- layer->updateCompositorResources(0, updater);
layer->pushPropertiesTo(layerImpl.get());
// We should have one tile on the impl side.
@@ -342,10 +213,9 @@ TEST(TiledLayerChromiumTest, pushIdlePaintTiles)
// For the next four updates, we should detect we still need idle painting.
for (int i = 0; i < 4; i++) {
- layer->prepareToUpdate(visibleRect, noOcclusion);
+ layer->updateLayerRect(updater, visibleRect, 0);
EXPECT_TRUE(layer->needsIdlePaint(visibleRect));
- layer->prepareToUpdateIdle(visibleRect, noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->idleUpdateLayerRect(updater, visibleRect, 0);
layer->pushPropertiesTo(layerImpl.get());
textureManager->unprotectAllTextures();
}
@@ -365,6 +235,109 @@ TEST(TiledLayerChromiumTest, pushIdlePaintTiles)
}
}
+TEST(TiledLayerChromiumTest, pushTilesAfterIdlePaintFailed)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(1024*1024, 1024*1024, 1024);
+ DebugScopedSetImplThread implThread;
+ RefPtr<FakeTiledLayerChromium> layer1 = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl1(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ RefPtr<FakeTiledLayerChromium> layer2 = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl2(adoptPtr(new FakeCCTiledLayerImpl(0)));
+
+ CCTextureUpdater updater;
+ FakeTextureAllocator allocator;
+ FakeTextureCopier copier;
+ FakeTextureUploader uploader;
+
+ // For this test we have two layers. layer1 exhausts most texture memory, leaving room for 2 more tiles from
+ // layer2, but not all three tiles. First we paint layer1, and one tile from layer2. Then when we idle paint
+ // layer2, we will fail on the third tile of layer2, and this should not leave the second tile in a bad state.
+
+ // This requires 4*30000 bytes of memory.
+ IntRect layer2Rect(0, 0, 100, 300);
+ layer2->setBounds(layer2Rect.size());
+ layer2->setVisibleLayerRect(layer2Rect);
+ layer2->invalidateRect(layer2Rect);
+
+ // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enough for 2 tiles only in the other layer.
+ IntRect layerRect(IntPoint::zero(), IntSize(100, 2400));
+ layer1->setBounds(layerRect.size());
+ layer1->setVisibleLayerRect(layerRect);
+ layer1->invalidateRect(layerRect);
+ layer1->updateLayerRect(updater, layerRect, 0);
+
+ // Paint a single tile in layer2 so that it will idle paint.
+ layer2->updateLayerRect(updater, IntRect(0, 0, 100, 100), 0);
+
+ // We should need idle-painting for both remaining tiles in layer2.
+ EXPECT_TRUE(layer2->needsIdlePaint(layer2Rect));
+
+ // Commit the frame over to impl.
+ updater.update(0, &allocator, &copier, &uploader, 5000);
+ layer1->pushPropertiesTo(layerImpl1.get());
+ layer2->pushPropertiesTo(layerImpl2.get());
+
+ // Now idle paint layer2. We are going to run out of memory though!
+ layer2->updateLayerRect(updater, IntRect(0, 0, 100, 100), 0);
+ layer2->idleUpdateLayerRect(updater, layer2Rect, 0);
+
+ // Oh well, commit the frame and push.
+ updater.update(0, &allocator, &copier, &uploader, 5000);
+ layer1->pushPropertiesTo(layerImpl1.get());
+ layer2->pushPropertiesTo(layerImpl2.get());
+
+ // Sanity check, we should have textures for the big layer.
+ EXPECT_TRUE(layerImpl1->hasTextureIdForTileAt(0, 0));
+
+ // We should only have the first tile from layer2 since it failed to idle update.
+ EXPECT_TRUE(layerImpl2->hasTileAt(0, 0));
+ EXPECT_TRUE(layerImpl2->hasTextureIdForTileAt(0, 0));
+ EXPECT_FALSE(layerImpl2->hasTileAt(0, 1));
+ EXPECT_FALSE(layerImpl2->hasTileAt(0, 2));
+
+ // Now if layer2 becomes fully visible, we should be able to paint it and push valid textures.
+ textureManager->unprotectAllTextures();
+
+ layer2->updateLayerRect(updater, layer2Rect, 0);
+ layer1->updateLayerRect(updater, IntRect(), 0);
+
+ updater.update(0, &allocator, &copier, &uploader, 5000);
+ layer1->pushPropertiesTo(layerImpl1.get());
+ layer2->pushPropertiesTo(layerImpl2.get());
+
+ EXPECT_TRUE(layerImpl2->hasTileAt(0, 0));
+ EXPECT_TRUE(layerImpl2->hasTileAt(0, 1));
+ EXPECT_TRUE(layerImpl2->hasTileAt(0, 2));
+ EXPECT_TRUE(layerImpl2->hasTextureIdForTileAt(0, 0));
+ EXPECT_TRUE(layerImpl2->hasTextureIdForTileAt(0, 1));
+ EXPECT_TRUE(layerImpl2->hasTextureIdForTileAt(0, 2));
+}
+
+TEST(TiledLayerChromiumTest, pushIdlePaintedOccludedTiles)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ TestCCOcclusionTracker occluded;
+
+ CCTextureUpdater updater;
+
+ // The tile size is 100x100, so this invalidates one occluded tile, culls it during paint, but prepaints it.
+ occluded.setOcclusion(IntRect(0, 0, 100, 100));
+
+ layer->setBounds(IntSize(100, 100));
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
+ layer->setVisibleLayerRect(IntRect(0, 0, 100, 100));
+ layer->invalidateRect(IntRect(0, 0, 100, 100));
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 100), &occluded);
+ layer->idleUpdateLayerRect(updater, IntRect(0, 0, 100, 100), &occluded);
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should have the prepainted tile on the impl side.
+ EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
+}
+
TEST(TiledLayerChromiumTest, pushTilesMarkedDirtyDuringPaint)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
@@ -372,9 +345,7 @@ TEST(TiledLayerChromiumTest, pushTilesMarkedDirtyDuringPaint)
DebugScopedSetImplThread implThread;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
- Region noOcclusion;
+ CCTextureUpdater updater;
// The tile size is 100x100, so this invalidates and then paints two tiles.
// However, during the paint, we invalidate one of the tiles. This should
@@ -382,8 +353,7 @@ TEST(TiledLayerChromiumTest, pushTilesMarkedDirtyDuringPaint)
layer->setBounds(IntSize(100, 200));
layer->invalidateRect(IntRect(0, 0, 100, 200));
layer->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 50), layer.get());
- layer->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
layer->pushPropertiesTo(layerImpl.get());
// We should have both tiles on the impl side.
@@ -400,23 +370,18 @@ TEST(TiledLayerChromiumTest, pushTilesLayerMarkedDirtyDuringPaintOnNextLayer)
OwnPtr<FakeCCTiledLayerImpl> layer1Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
OwnPtr<FakeCCTiledLayerImpl> layer2Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
- Region noOcclusion;
+ CCTextureUpdater updater;
layer1->setBounds(IntSize(100, 200));
layer1->invalidateRect(IntRect(0, 0, 100, 200));
layer2->setBounds(IntSize(100, 200));
layer2->invalidateRect(IntRect(0, 0, 100, 200));
- layer1->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
+ layer1->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
// Invalidate a tile on layer1
layer2->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 50), layer1.get());
- layer2->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
-
- layer1->updateCompositorResources(0, updater);
- layer2->updateCompositorResources(0, updater);
+ layer2->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
layer1->pushPropertiesTo(layer1Impl.get());
layer2->pushPropertiesTo(layer2Impl.get());
@@ -437,9 +402,7 @@ TEST(TiledLayerChromiumTest, pushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer
OwnPtr<FakeCCTiledLayerImpl> layer1Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
OwnPtr<FakeCCTiledLayerImpl> layer2Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
- Region noOcclusion;
+ CCTextureUpdater updater;
layer1->setBounds(IntSize(100, 200));
layer1->invalidateRect(IntRect(0, 0, 100, 200));
@@ -448,12 +411,9 @@ TEST(TiledLayerChromiumTest, pushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer
// Invalidate a tile on layer2
layer1->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 50), layer2.get());
- layer1->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
+ layer1->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
- layer2->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
-
- layer1->updateCompositorResources(0, updater);
- layer2->updateCompositorResources(0, updater);
+ layer2->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
layer1->pushPropertiesTo(layer1Impl.get());
layer2->pushPropertiesTo(layer2Impl.get());
@@ -471,7 +431,6 @@ TEST(TiledLayerChromiumTest, idlePaintOutOfMemory)
IntSize contentBounds(300, 300);
IntRect contentRect(IntPoint::zero(), contentBounds);
IntRect visibleRect(100, 100, 100, 100);
- Region noOcclusion;
// We have enough memory for only the visible rect, so we will run out of memory in first idle paint.
int memoryLimit = 4 * 100 * 100; // 2 tiles, 4 bytes per pixel.
@@ -481,51 +440,243 @@ TEST(TiledLayerChromiumTest, idlePaintOutOfMemory)
DebugScopedSetImplThread implThread;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
// This invalidates 9 tiles and then paints one visible tile.
layer->setBounds(contentBounds);
layer->setVisibleLayerRect(visibleRect);
layer->invalidateRect(contentRect);
- layer->prepareToUpdate(visibleRect, noOcclusion);
+ layer->updateLayerRect(updater, visibleRect, 0);
// We should need idle-painting for 3x3 tiles surounding visible tile.
EXPECT_TRUE(layer->needsIdlePaint(visibleRect));
- layer->updateCompositorResources(0, updater);
layer->pushPropertiesTo(layerImpl.get());
// We should have one tile on the impl side.
EXPECT_TRUE(layerImpl->hasTileAt(1, 1));
textureManager->unprotectAllTextures();
- layer->prepareToUpdate(visibleRect, noOcclusion);
- layer->prepareToUpdateIdle(visibleRect, noOcclusion);
+ layer->updateLayerRect(updater, visibleRect, 0);
+ layer->idleUpdateLayerRect(updater, visibleRect, 0);
// We shouldn't signal we need another idle paint after we run out of memory.
EXPECT_FALSE(layer->needsIdlePaint(visibleRect));
- layer->updateCompositorResources(0, updater);
layer->pushPropertiesTo(layerImpl.get());
}
+TEST(TiledLayerChromiumTest, idlePaintZeroSizedLayer)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(20000, 10000, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+
+ CCTextureUpdater updater;
+
+ // The layer's bounds are empty.
+ IntRect contentRect;
+
+ layer->setBounds(contentRect.size());
+ layer->setVisibleLayerRect(contentRect);
+ layer->invalidateRect(contentRect);
+ layer->updateLayerRect(updater, contentRect, 0);
+
+ // Empty layers don't have tiles.
+ EXPECT_EQ(0u, layer->numPaintedTiles());
+
+ // Empty layers don't need prepaint.
+ EXPECT_FALSE(layer->needsIdlePaint(contentRect));
+
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // Empty layers don't have tiles.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+
+ // Non-visible layers don't idle paint.
+ layer->idleUpdateLayerRect(updater, contentRect, 0);
+
+ // Empty layers don't have tiles.
+ EXPECT_EQ(0u, layer->numPaintedTiles());
+
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // Empty layers don't have tiles.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+}
+
+TEST(TiledLayerChromiumTest, idlePaintZeroSizedAnimatingLayer)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(20000, 10000, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+
+ CCTextureUpdater updater;
+
+ // Pretend the layer is animating.
+ layer->setDrawTransformIsAnimating(true);
+
+ // The layer's bounds are empty.
+ IntRect contentRect;
+
+ layer->setBounds(contentRect.size());
+ layer->setVisibleLayerRect(contentRect);
+ layer->invalidateRect(contentRect);
+ layer->updateLayerRect(updater, contentRect, 0);
+
+ // Empty layers don't have tiles.
+ EXPECT_EQ(0u, layer->numPaintedTiles());
+
+ // Empty layers don't need prepaint.
+ EXPECT_FALSE(layer->needsIdlePaint(contentRect));
+
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // Empty layers don't have tiles.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+
+ // Non-visible layers don't idle paint.
+ layer->idleUpdateLayerRect(updater, contentRect, 0);
+
+ // Empty layers don't have tiles.
+ EXPECT_EQ(0u, layer->numPaintedTiles());
+
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // Empty layers don't have tiles.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+}
+
+TEST(TiledLayerChromiumTest, idlePaintNonVisibleLayers)
+{
+ IntSize contentBounds(100, 100);
+ IntRect contentRect(IntPoint::zero(), contentBounds);
+
+ OwnPtr<TextureManager> textureManager = TextureManager::create(20000, 10000, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+
+ CCTextureUpdater updater;
+
+ // Invalidate the layer but make none of it visible, so nothing paints.
+ IntRect visibleRect;
+
+ layer->setBounds(contentBounds);
+ layer->setVisibleLayerRect(visibleRect);
+ layer->invalidateRect(contentRect);
+ layer->updateLayerRect(updater, visibleRect, 0);
+
+ // Non-visible layers don't need idle paint.
+ EXPECT_FALSE(layer->needsIdlePaint(visibleRect));
+
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should not have any tiles pushed since the layer is not visible.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+
+ // Non-visible layers don't idle paint.
+ layer->idleUpdateLayerRect(updater, visibleRect, 0);
+
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should not have any tiles pushed since the layer is not visible.
+ EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
+}
+
+static void idlePaintRepeat(int repeatTimes, FakeTiledLayerChromium* layer, FakeCCTiledLayerImpl* layerImpl, CCTextureUpdater& updater, const IntRect& visibleRect)
+{
+ for (int i = 0; i < repeatTimes; ++i) {
+ layer->updateLayerRect(updater, visibleRect, 0);
+ layer->idleUpdateLayerRect(updater, visibleRect, 0);
+ layer->pushPropertiesTo(layerImpl);
+ }
+}
+
+static void testHaveOuterTiles(FakeCCTiledLayerImpl* layerImpl, int width, int height, int have)
+{
+ for (int i = 0; i < width; ++i) {
+ for (int j = 0; j < height; ++j) {
+ bool hasTile = i < have || j < have || i >= width - have || j >= height - have;
+ EXPECT_EQ(hasTile, layerImpl->hasTileAt(i, j));
+ }
+ }
+}
+
+TEST(TiledLayerChromiumTest, idlePaintNonVisibleAnimatingLayers)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(8000*8000*8, 8000*8000*4, 1024);
+ DebugScopedSetImplThread implThread;
+
+ CCTextureUpdater updater;
+
+ int tileWidth = FakeTiledLayerChromium::tileSize().width();
+ int tileHeight = FakeTiledLayerChromium::tileSize().height();
+ int width[] = { 1, 2, 3, 4, 9, 10, 0 };
+ int height[] = { 1, 2, 3, 4, 9, 10, 0 };
+
+ for (int j = 0; height[j]; ++j) {
+ for (int i = 0; width[i]; ++i) {
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+
+ // Pretend the layer is animating.
+ layer->setDrawTransformIsAnimating(true);
+
+ IntSize contentBounds(width[i] * tileWidth, height[j] * tileHeight);
+ IntRect contentRect(IntPoint::zero(), contentBounds);
+ IntRect visibleRect;
+
+ layer->setBounds(contentBounds);
+ layer->setVisibleLayerRect(visibleRect);
+ layer->invalidateRect(contentRect);
+
+ // If idlePaintRect gives back a non-empty result then we should paint it. Otherwise,
+ // we shoud paint nothing.
+ bool shouldPrepaint = !layer->idlePaintRect(visibleRect).isEmpty();
+
+ // This paints the layer but there's nothing visible so it's a no-op.
+ layer->updateLayerRect(updater, visibleRect, 0);
+ layer->pushPropertiesTo(layerImpl.get());
+
+ // We should not have any tiles pushed yet since the layer is not visible and we've not prepainted.
+ testHaveOuterTiles(layerImpl.get(), width[i], height[j], 0);
+
+ // Normally we don't allow non-visible layers to pre-paint, but if they are animating then we should.
+ EXPECT_EQ(shouldPrepaint, layer->needsIdlePaint(visibleRect));
+
+ // If the layer is to be prepainted at all, then after four updates we should have the outer row/columns painted.
+ idlePaintRepeat(4, layer.get(), layerImpl.get(), updater, visibleRect);
+ testHaveOuterTiles(layerImpl.get(), width[i], height[j], shouldPrepaint ? 1 : 0);
+
+ // We don't currently idle paint past the outermost tiles.
+ EXPECT_FALSE(layer->needsIdlePaint(visibleRect));
+ idlePaintRepeat(4, layer.get(), layerImpl.get(), updater, visibleRect);
+ testHaveOuterTiles(layerImpl.get(), width[i], height[j], shouldPrepaint ? 1 : 0);
+ }
+ }
+}
+
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;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- Region noOcclusion;
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
+ FakeTextureAllocator fakeAllocator;
+ FakeTextureCopier fakeCopier;
+ FakeTextureUploader fakeUploader;
+ RefPtr<GraphicsContext3D> context = createCompositorMockGraphicsContext3D(GraphicsContext3D::Attributes());
// 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), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
+ updater.update(context.get(), &fakeAllocator, &fakeCopier, &fakeUploader, 1000);
layer->pushPropertiesTo(layerImpl.get());
// We should have both tiles on the impl side.
@@ -535,20 +686,23 @@ TEST(TiledLayerChromiumTest, invalidateFromPrepare)
textureManager->unprotectAllTextures();
layer->fakeLayerTextureUpdater()->clearPrepareCount();
- // Invoke prepareToUpdate again. As the layer is valid prepareToUpdate shouldn't be invoked on
+ // Invoke updateLayerRect again. As the layer is valid updateLayerRect shouldn't be invoked on
// the LayerTextureUpdater.
- layer->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
+ updater.update(context.get(), &fakeAllocator, &fakeCopier, &fakeUploader, 1000);
EXPECT_EQ(0, layer->fakeLayerTextureUpdater()->prepareCount());
layer->invalidateRect(IntRect(0, 0, 50, 50));
- // setRectToInvalidate triggers invalidateRect() being invoked from prepareToUpdate.
+ // setRectToInvalidate triggers invalidateRect() being invoked from updateLayerRect.
layer->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(25, 25, 50, 50), layer.get());
layer->fakeLayerTextureUpdater()->clearPrepareCount();
- layer->prepareToUpdate(IntRect(0, 0, 100, 200), noOcclusion);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
+ updater.update(context.get(), &fakeAllocator, &fakeCopier, &fakeUploader, 1000);
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), noOcclusion);
+ // The layer should still be invalid as updateLayerRect invoked invalidate.
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
+ updater.update(context.get(), &fakeAllocator, &fakeCopier, &fakeUploader, 1000);
EXPECT_EQ(1, layer->fakeLayerTextureUpdater()->prepareCount());
}
@@ -559,10 +713,8 @@ TEST(TiledLayerChromiumTest, verifyUpdateRectWhenContentBoundsAreScaled)
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerWithScaledBounds> layer = adoptRef(new FakeTiledLayerWithScaledBounds(textureManager.get()));
- Region noOcclusion;
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
IntRect layerBounds(0, 0, 300, 200);
IntRect contentBounds(0, 0, 200, 250);
@@ -574,21 +726,18 @@ TEST(TiledLayerChromiumTest, verifyUpdateRectWhenContentBoundsAreScaled)
// On first update, the updateRect includes all tiles, even beyond the boundaries of the layer.
// However, it should still be in layer space, not content space.
layer->invalidateRect(contentBounds);
- layer->prepareToUpdate(contentBounds, noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, contentBounds, 0);
EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 300, 300 * 0.8), layer->updateRect());
// After the tiles are updated once, another invalidate only needs to update the bounds of the layer.
layer->invalidateRect(contentBounds);
- layer->prepareToUpdate(contentBounds, noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, contentBounds, 0);
EXPECT_FLOAT_RECT_EQ(FloatRect(layerBounds), layer->updateRect());
// Partial re-paint should also be represented by the updateRect in layer space, not content space.
IntRect partialDamage(30, 100, 10, 10);
layer->invalidateRect(partialDamage);
- layer->prepareToUpdate(contentBounds, noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, contentBounds, 0);
EXPECT_FLOAT_RECT_EQ(FloatRect(45, 80, 15, 8), layer->updateRect());
}
@@ -599,9 +748,7 @@ TEST(TiledLayerChromiumTest, verifyInvalidationWhenContentsScaleChanges)
DebugScopedSetImplThread implThread;
OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
- Region noOcclusion;
+ CCTextureUpdater updater;
// Create a layer with one tile.
layer->setBounds(IntSize(100, 100));
@@ -611,8 +758,7 @@ TEST(TiledLayerChromiumTest, verifyInvalidationWhenContentsScaleChanges)
EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect());
// Push the tiles to the impl side and check that there is exactly one.
- layer->prepareToUpdate(IntRect(0, 0, 100, 100), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 100), 0);
layer->pushPropertiesTo(layerImpl.get());
EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
@@ -625,8 +771,7 @@ TEST(TiledLayerChromiumTest, verifyInvalidationWhenContentsScaleChanges)
EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect());
// The impl side should get 2x2 tiles now.
- layer->prepareToUpdate(IntRect(0, 0, 200, 200), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(0, 0, 200, 200), 0);
layer->pushPropertiesTo(layerImpl.get());
EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
@@ -636,8 +781,7 @@ TEST(TiledLayerChromiumTest, verifyInvalidationWhenContentsScaleChanges)
// Invalidate the entire layer again, but do not paint. All tiles should be gone now from the
// impl side.
layer->setNeedsDisplay();
- layer->prepareToUpdate(IntRect(0, 0, 0, 0), noOcclusion);
- layer->updateCompositorResources(0, updater);
+ layer->updateLayerRect(updater, IntRect(1, 0, 0, 1), 0);
layer->pushPropertiesTo(layerImpl.get());
EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
@@ -650,7 +794,7 @@ TEST(TiledLayerChromiumTest, skipsDrawGetsReset)
// Initialize without threading support.
WebKit::WebCompositor::initialize(0);
FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient;
- RefPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, CCSettings());
+ OwnPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, CCSettings());
// Create two 300 x 300 tiled layers.
IntSize contentBounds(300, 300);
@@ -671,14 +815,12 @@ TEST(TiledLayerChromiumTest, skipsDrawGetsReset)
rootLayer->invalidateRect(contentRect);
childLayer->invalidateRect(contentRect);
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
ccLayerTreeHost->setRootLayer(rootLayer);
ccLayerTreeHost->setViewportSize(IntSize(300, 300));
textureManager->setMaxMemoryLimitBytes(memoryLimit);
- ccLayerTreeHost->updateLayers();
- ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
+ ccLayerTreeHost->updateLayers(updater);
// We'll skip the root layer.
EXPECT_TRUE(rootLayer->skipsDraw());
@@ -690,7 +832,7 @@ TEST(TiledLayerChromiumTest, skipsDrawGetsReset)
// Remove the child layer.
rootLayer->removeAllChildren();
- ccLayerTreeHost->updateLayers();
+ ccLayerTreeHost->updateLayers(updater);
EXPECT_FALSE(rootLayer->skipsDraw());
ccLayerTreeHost->setRootLayer(0);
@@ -702,16 +844,30 @@ TEST(TiledLayerChromiumTest, resizeToSmaller)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(60*1024*1024, 60*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region noOcclusion;
+ CCTextureUpdater updater;
layer->setBounds(IntSize(700, 700));
layer->invalidateRect(IntRect(0, 0, 700, 700));
- layer->prepareToUpdate(IntRect(0, 0, 700, 700), noOcclusion);
+ layer->updateLayerRect(updater, IntRect(0, 0, 700, 700), 0);
layer->setBounds(IntSize(200, 200));
layer->invalidateRect(IntRect(0, 0, 200, 200));
}
+TEST(TiledLayerChromiumTest, hugeLayerUpdateCrash)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(60*1024*1024, 60*1024*1024, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ CCTextureUpdater updater;
+
+ int size = 1 << 30;
+ layer->setBounds(IntSize(size, size));
+ layer->invalidateRect(IntRect(0, 0, size, size));
+
+ // Ensure no crash for bounds where size * size would overflow an int.
+ layer->updateLayerRect(updater, IntRect(0, 0, 700, 700), 0);
+}
+
TEST(TiledLayerChromiumTest, partialUpdates)
{
CCSettings settings;
@@ -719,7 +875,7 @@ TEST(TiledLayerChromiumTest, partialUpdates)
// Initialize without threading support.
WebKit::WebCompositor::initialize(0);
FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient;
- RefPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, settings);
+ OwnPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, settings);
// Create one 500 x 300 tiled layer.
IntSize contentBounds(300, 200);
@@ -731,51 +887,92 @@ TEST(TiledLayerChromiumTest, partialUpdates)
layer->setPosition(FloatPoint(150, 150));
layer->invalidateRect(contentRect);
- FakeTextureAllocator textureAllocator;
- CCTextureUpdater updater(&textureAllocator);
+ CCTextureUpdater updater;
+ FakeTextureAllocator allocator;
+ FakeTextureCopier copier;
+ FakeTextureUploader uploader;
ccLayerTreeHost->setRootLayer(layer);
ccLayerTreeHost->setViewportSize(IntSize(300, 200));
// Full update of all 6 tiles.
- ccLayerTreeHost->updateLayers();
- ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
- updater.update(0, 4);
- EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
- EXPECT_TRUE(updater.hasMoreUpdates());
- layer->fakeLayerTextureUpdater()->clearUpdateCount();
- updater.update(0, 4);
- EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
- EXPECT_FALSE(updater.hasMoreUpdates());
- layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ ccLayerTreeHost->updateLayers(updater);
+ {
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_TRUE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_FALSE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ layer->pushPropertiesTo(layerImpl.get());
+ }
ccLayerTreeHost->commitComplete();
// Full update of 3 tiles and partial update of 3 tiles.
layer->invalidateRect(IntRect(0, 0, 300, 150));
- ccLayerTreeHost->updateLayers();
- ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
- updater.update(0, 4);
- EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
- EXPECT_TRUE(updater.hasMoreUpdates());
- layer->fakeLayerTextureUpdater()->clearUpdateCount();
- updater.update(0, 4);
- EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
- EXPECT_FALSE(updater.hasMoreUpdates());
- layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ ccLayerTreeHost->updateLayers(updater);
+ {
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_TRUE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_FALSE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ layer->pushPropertiesTo(layerImpl.get());
+ }
ccLayerTreeHost->commitComplete();
// Partial update of 6 tiles.
layer->invalidateRect(IntRect(50, 50, 200, 100));
- ccLayerTreeHost->updateLayers();
- ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
- updater.update(0, 4);
- EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
- EXPECT_TRUE(updater.hasMoreUpdates());
- layer->fakeLayerTextureUpdater()->clearUpdateCount();
- updater.update(0, 4);
- EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
- EXPECT_FALSE(updater.hasMoreUpdates());
- layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ {
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ ccLayerTreeHost->updateLayers(updater);
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_TRUE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_FALSE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ layer->pushPropertiesTo(layerImpl.get());
+ }
+ ccLayerTreeHost->commitComplete();
+
+ // Checkerboard all tiles.
+ layer->invalidateRect(IntRect(0, 0, 300, 200));
+ {
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ layer->pushPropertiesTo(layerImpl.get());
+ }
+ ccLayerTreeHost->commitComplete();
+
+ // Partail update of 6 checkerboard tiles.
+ layer->invalidateRect(IntRect(50, 50, 200, 100));
+ {
+ DebugScopedSetImplThread implThread;
+ OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
+ ccLayerTreeHost->updateLayers(updater);
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_TRUE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ updater.update(0, &allocator, &copier, &uploader, 4);
+ EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_FALSE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ layer->pushPropertiesTo(layerImpl.get());
+ }
ccLayerTreeHost->commitComplete();
ccLayerTreeHost->setRootLayer(0);
@@ -787,13 +984,13 @@ TEST(TiledLayerChromiumTest, tilesPaintedWithoutOcclusion)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region occluded;
+ CCTextureUpdater updater;
// 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), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 100, 200), 0);
EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->prepareRectCount());
}
@@ -801,97 +998,137 @@ TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusion)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region occluded;
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
// The tile size is 100x100.
layer->setBounds(IntSize(600, 600));
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
- occluded = IntRect(200, 200, 300, 100);
+ occluded.setOcclusion(IntRect(200, 200, 300, 100));
layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000, 1);
+ EXPECT_EQ(3, occluded.overdrawMetrics().tilesCulledForUpload());
+
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
- occluded = IntRect(250, 200, 300, 100);
+ occluded.setOcclusion(IntRect(250, 200, 300, 100));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(36-2, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000 + 340000, 1);
+ EXPECT_EQ(3 + 2, occluded.overdrawMetrics().tilesCulledForUpload());
+
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
- occluded = IntRect(250, 250, 300, 100);
+ occluded.setOcclusion(IntRect(250, 250, 300, 100));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(36, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000 + 340000 + 360000, 1);
+ EXPECT_EQ(3 + 2, occluded.overdrawMetrics().tilesCulledForUpload());
}
TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndVisiblityConstraints)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region occluded;
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
// The tile size is 100x100.
layer->setBounds(IntSize(600, 600));
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
// The partially occluded tiles (by the 150 occlusion height) are visible beyond the occlusion, so not culled.
- occluded = IntRect(200, 200, 300, 150);
+ occluded.setOcclusion(IntRect(200, 200, 300, 150));
layer->setVisibleLayerRect(IntRect(0, 0, 600, 360));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
- EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 360), &occluded);
+ EXPECT_EQ(24-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 210000, 1);
+ EXPECT_EQ(3, occluded.overdrawMetrics().tilesCulledForUpload());
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
// Now the visible region stops at the edge of the occlusion so the partly visible tiles become fully occluded.
- occluded = IntRect(200, 200, 300, 150);
+ occluded.setOcclusion(IntRect(200, 200, 300, 150));
layer->setVisibleLayerRect(IntRect(0, 0, 600, 350));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
- EXPECT_EQ(36-6, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 350), &occluded);
+ EXPECT_EQ(24-6, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 210000 + 180000, 1);
+ EXPECT_EQ(3 + 6, occluded.overdrawMetrics().tilesCulledForUpload());
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
// Now the visible region is even smaller than the occlusion, it should have the same result.
- occluded = IntRect(200, 200, 300, 150);
+ occluded.setOcclusion(IntRect(200, 200, 300, 150));
layer->setVisibleLayerRect(IntRect(0, 0, 600, 340));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
- EXPECT_EQ(36-6, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 340), &occluded);
+ EXPECT_EQ(24-6, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 210000 + 180000 + 180000, 1);
+ EXPECT_EQ(3 + 6 + 6, occluded.overdrawMetrics().tilesCulledForUpload());
+
}
TEST(TiledLayerChromiumTest, tilesNotPaintedWithoutInvalidation)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region occluded;
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
// The tile size is 100x100.
layer->setBounds(IntSize(600, 600));
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
- occluded = IntRect(200, 200, 300, 100);
+ occluded.setOcclusion(IntRect(200, 200, 300, 100));
layer->setVisibleLayerRect(IntRect(0, 0, 600, 600));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000, 1);
+ EXPECT_EQ(3, occluded.overdrawMetrics().tilesCulledForUpload());
+
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
- // Repaint without marking it dirty.
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ // Repaint without marking it dirty. The culled tiles remained dirty.
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(0, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000, 1);
+ EXPECT_EQ(6, occluded.overdrawMetrics().tilesCulledForUpload());
}
TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndTransforms)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region occluded;
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
// The tile size is 100x100.
@@ -901,19 +1138,25 @@ TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndTransforms)
TransformationMatrix screenTransform;
screenTransform.scale(0.5);
layer->setScreenSpaceTransform(screenTransform);
+ layer->setDrawTransform(screenTransform * TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
- occluded = IntRect(100, 100, 150, 50);
+ occluded.setOcclusion(IntRect(100, 100, 150, 50));
layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000, 1);
+ EXPECT_EQ(3, occluded.overdrawMetrics().tilesCulledForUpload());
}
TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndScaling)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
- Region occluded;
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
// The tile size is 100x100.
@@ -922,99 +1165,196 @@ TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndScaling)
// pixels, which means none should be occluded.
layer->setContentsScale(0.5);
layer->setBounds(IntSize(600, 600));
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
- occluded = IntRect(200, 200, 300, 100);
+ occluded.setOcclusion(IntRect(200, 200, 300, 100));
layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
// The content is half the size of the layer (so the number of tiles is fewer).
// In this case, the content is 300x300, and since the tile size is 100, the
// number of tiles 3x3.
EXPECT_EQ(9, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 90000, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
// This makes sure the painting works when the content space is scaled to
// a different layer space. In this case the occluded region catches the
// blown up tiles.
- occluded = IntRect(200, 200, 300, 200);
+ occluded.setOcclusion(IntRect(200, 200, 300, 200));
layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(9-1, layer->fakeLayerTextureUpdater()->prepareRectCount());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 90000 + 80000, 1);
+ EXPECT_EQ(1, occluded.overdrawMetrics().tilesCulledForUpload());
+
layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
// This makes sure content scaling and transforms work together.
TransformationMatrix screenTransform;
screenTransform.scale(0.5);
layer->setScreenSpaceTransform(screenTransform);
+ layer->setDrawTransform(screenTransform * TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
- occluded = IntRect(100, 100, 150, 100);
+ occluded.setOcclusion(IntRect(100, 100, 150, 100));
layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
layer->invalidateRect(IntRect(0, 0, 600, 600));
- layer->prepareToUpdate(IntRect(0, 0, 600, 600), occluded);
+ layer->updateLayerRect(updater, IntRect(0, 0, 600, 600), &occluded);
EXPECT_EQ(9-1, layer->fakeLayerTextureUpdater()->prepareRectCount());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 90000 + 80000 + 80000, 1);
+ EXPECT_EQ(1 + 1, occluded.overdrawMetrics().tilesCulledForUpload());
}
-TEST(TiledLayerChromiumTest, opaqueContentsRegion)
+TEST(TiledLayerChromiumTest, visibleContentOpaqueRegion)
{
OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
// The tile size is 100x100, so this invalidates and then paints two tiles in various ways.
IntRect opaquePaintRect;
Region opaqueContents;
- Region noOcclusion;
IntRect contentBounds = IntRect(0, 0, 100, 200);
IntRect visibleBounds = IntRect(0, 0, 100, 150);
layer->setBounds(contentBounds.size());
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
layer->setVisibleLayerRect(visibleBounds);
layer->setDrawOpacity(1);
- // If the layer doesn't paint opaque content, then the opaqueContentsRegion should be empty.
- layer->fakeLayerTextureUpdater()->setOpaquePaintRect(opaquePaintRect);
+ // If the layer doesn't paint opaque content, then the visibleContentOpaqueRegion should be empty.
+ layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
layer->invalidateRect(contentBounds);
- layer->prepareToUpdate(contentBounds, noOcclusion);
- opaqueContents = layer->opaqueContentsRegion();
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
EXPECT_TRUE(opaqueContents.isEmpty());
- // opaqueContentsRegion should match the visible part of what is painted opaque.
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
+ // visibleContentOpaqueRegion should match the visible part of what is painted opaque.
opaquePaintRect = IntRect(10, 10, 90, 190);
layer->fakeLayerTextureUpdater()->setOpaquePaintRect(opaquePaintRect);
layer->invalidateRect(contentBounds);
- layer->prepareToUpdate(contentBounds, noOcclusion);
- opaqueContents = layer->opaqueContentsRegion();
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), opaqueContents.bounds());
EXPECT_EQ(1u, opaqueContents.rects().size());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 + 20000 - 17100, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
// If we paint again without invalidating, the same stuff should be opaque.
layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
- layer->prepareToUpdate(contentBounds, noOcclusion);
- opaqueContents = layer->opaqueContentsRegion();
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), opaqueContents.bounds());
EXPECT_EQ(1u, opaqueContents.rects().size());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 + 20000 - 17100, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
// If we repaint a non-opaque part of the tile, then it shouldn't lose its opaque-ness. And other tiles should
// not be affected.
layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
layer->invalidateRect(IntRect(0, 0, 1, 1));
- layer->prepareToUpdate(contentBounds, noOcclusion);
- opaqueContents = layer->opaqueContentsRegion();
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), opaqueContents.bounds());
EXPECT_EQ(1u, opaqueContents.rects().size());
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2 + 1, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 + 20000 - 17100 + 1, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
// If we repaint an opaque part of the tile, then it should lose its opaque-ness. But other tiles should still
// not be affected.
layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
layer->invalidateRect(IntRect(10, 10, 1, 1));
- layer->prepareToUpdate(contentBounds, noOcclusion);
- opaqueContents = layer->opaqueContentsRegion();
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
EXPECT_EQ_RECT(intersection(IntRect(10, 100, 90, 100), visibleBounds), opaqueContents.bounds());
EXPECT_EQ(1u, opaqueContents.rects().size());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2 + 1 + 1, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 + 20000 - 17100 + 1 + 1, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
+ // No metrics are recorded in prepaint, so the values should not change from above.
+ layer->idleUpdateLayerRect(updater, contentBounds, &occluded);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2 + 1 + 1, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 + 20000 - 17100 + 1 + 1, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+}
+
+TEST(TiledLayerChromiumTest, pixelsPaintedMetrics)
+{
+ OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ TestCCOcclusionTracker occluded;
+ CCTextureUpdater updater;
+
+ // The tile size is 100x100, so this invalidates and then paints two tiles in various ways.
+
+ IntRect opaquePaintRect;
+ Region opaqueContents;
+
+ IntRect contentBounds = IntRect(0, 0, 100, 300);
+ IntRect visibleBounds = IntRect(0, 0, 100, 300);
+
+ layer->setBounds(contentBounds.size());
+ layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
+ layer->setVisibleLayerRect(visibleBounds);
+ layer->setDrawOpacity(1);
+
+ // Invalidates and paints the whole layer.
+ layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
+ layer->invalidateRect(contentBounds);
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
+ EXPECT_TRUE(opaqueContents.isEmpty());
+
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 30000, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 30000, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
+
+ // Invalidates an area on the top and bottom tile, which will cause us to paint the tile in the middle,
+ // even though it is not dirty and will not be uploaded.
+ layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
+ layer->invalidateRect(IntRect(0, 0, 1, 1));
+ layer->invalidateRect(IntRect(50, 200, 10, 10));
+ layer->updateLayerRect(updater, contentBounds, &occluded);
+ opaqueContents = layer->visibleContentOpaqueRegion();
+ EXPECT_TRUE(opaqueContents.isEmpty());
+
+ // The middle tile was painted even though not invalidated.
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 30000 + 60 * 210, 1);
+ // The pixels uploaded will not include the non-invalidated tile in the middle.
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1);
+ EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 30000 + 1 + 100, 1);
+ EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload());
}
} // namespace