summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-06 05:01:20 +0000
committerdanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-06 05:01:20 +0000
commite0341359793fd1b9cef790e6927d6fa2cb33c0ff (patch)
tree75dd6a56c44aeea4a6bab43a21aad7ce30584b80
parent34e25581f9c2513ef1b294cadfa6c4ea250c288c (diff)
downloadchromium_src-e0341359793fd1b9cef790e6927d6fa2cb33c0ff.zip
chromium_src-e0341359793fd1b9cef790e6927d6fa2cb33c0ff.tar.gz
chromium_src-e0341359793fd1b9cef790e6927d6fa2cb33c0ff.tar.bz2
cc: Don't draw and swap if the frame will not change.
When there is no visible damage in the root surface, we have no reason to do CalculateRenderPasses, DrawLayers, or SwapBuffers. This adds an early out in each of these when there is no damage, but storing a flag on the FrameData to communicate this state. When doing a readback, we need to make sure we draw the area being read back, so we pass a damage rect in to PrepareToDraw to enforce this. This mechanism can be used to also implement the "ForceFullFrameDamage" mechanism, so we move the flag to LayerTreeHostImpl and have DamageTracker take a general rect instead. Before: [ RUN ] LayerTreeHostPerfTestJsonReader.TenTenSingleThread *RESULT 10_10_layer_tree: frames= 3089.37 runs/s After: [ RUN ] LayerTreeHostPerfTestJsonReader.TenTenSingleThread *RESULT 10_10_layer_tree: frames= 4679.13 runs/s When there's no damage, a full single-threaded commit+composite speeds up about 50%. Tests: DamageTrackerTest.DamageWhenAddedExternally LayerTreeHostDamageTestNoDamageDoesNotSwap.RunSingleThread LayerTreeHostDamageTestNoDamageDoesNotSwap.RunMultiThread LayerTreeHostDamageTestNoDamageReadbackDoesDraw.RunSingleThread LayerTreeHostDamageTestNoDamageReadbackDoesDraw.RunMultiThread LayerTreeHostDamageTestForcedFullDamage.RunSingleThread LayerTreeHostDamageTestForcedFullDamage.RunMultiThread Adding a new perf test with damage: LayerTreeHostPerfTestJsonReader.TenTenSingleThread_FullDamageEachFrame *RESULT 10_10_layer_tree: frames= 3233.98 runs/s R=nduca BUG=222915 Review URL: https://chromiumcodereview.appspot.com/12662021 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192706 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/cc_tests.gyp1
-rw-r--r--cc/layers/delegated_renderer_layer_impl_unittest.cc46
-rw-r--r--cc/output/delegating_renderer_unittest.cc5
-rw-r--r--cc/test/fake_layer_tree_host_impl.h2
-rw-r--r--cc/test/layer_tree_test.cc17
-rw-r--r--cc/test/layer_tree_test.h2
-rw-r--r--cc/trees/damage_tracker.cc7
-rw-r--r--cc/trees/damage_tracker.h3
-rw-r--r--cc/trees/damage_tracker_unittest.cc29
-rw-r--r--cc/trees/layer_tree_host_impl.cc51
-rw-r--r--cc/trees/layer_tree_host_impl.h8
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc264
-rw-r--r--cc/trees/layer_tree_host_perftest.cc14
-rw-r--r--cc/trees/layer_tree_host_unittest.cc54
-rw-r--r--cc/trees/layer_tree_host_unittest_context.cc13
-rw-r--r--cc/trees/layer_tree_host_unittest_damage.cc275
-rw-r--r--cc/trees/layer_tree_host_unittest_delegated.cc8
-rw-r--r--cc/trees/single_thread_proxy.cc39
-rw-r--r--cc/trees/single_thread_proxy.h8
-rw-r--r--cc/trees/thread_proxy.cc10
20 files changed, 644 insertions, 212 deletions
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 7c6ee9c..3fe351a 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -34,6 +34,7 @@
'trees/layer_tree_host_unittest.cc',
'trees/layer_tree_host_unittest_animation.cc',
'trees/layer_tree_host_unittest_context.cc',
+ 'trees/layer_tree_host_unittest_damage.cc',
'trees/layer_tree_host_unittest_delegated.cc',
'trees/layer_tree_host_unittest_occlusion.cc',
'trees/layer_tree_host_unittest_scroll.cc',
diff --git a/cc/layers/delegated_renderer_layer_impl_unittest.cc b/cc/layers/delegated_renderer_layer_impl_unittest.cc
index 6e6c00f..a97d83c 100644
--- a/cc/layers/delegated_renderer_layer_impl_unittest.cc
+++ b/cc/layers/delegated_renderer_layer_impl_unittest.cc
@@ -143,7 +143,7 @@ class DelegatedRendererLayerImplTestSimple
TEST_F(DelegatedRendererLayerImplTestSimple, AddsContributingRenderPasses) {
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
// Each non-DelegatedRendererLayer added one RenderPass. The
// DelegatedRendererLayer added two contributing passes.
@@ -177,7 +177,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple, AddsContributingRenderPasses) {
TEST_F(DelegatedRendererLayerImplTestSimple,
AddsQuadsToContributingRenderPasses) {
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
// Each non-DelegatedRendererLayer added one RenderPass. The
// DelegatedRendererLayer added two contributing passes.
@@ -212,7 +212,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple,
TEST_F(DelegatedRendererLayerImplTestSimple, AddsQuadsToTargetRenderPass) {
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
// Each non-DelegatedRendererLayer added one RenderPass. The
// DelegatedRendererLayer added two contributing passes.
@@ -240,7 +240,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple, AddsQuadsToTargetRenderPass) {
TEST_F(DelegatedRendererLayerImplTestSimple,
QuadsFromRootRenderPassAreModifiedForTheTarget) {
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
// Each non-DelegatedRendererLayer added one RenderPass. The
// DelegatedRendererLayer added two contributing passes.
@@ -273,7 +273,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple,
TEST_F(DelegatedRendererLayerImplTestSimple, DoesNotOwnARenderSurface) {
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
// If the DelegatedRendererLayer is axis aligned and has opacity 1, then it
// has no need to be a RenderSurface for the quads it carries.
@@ -287,7 +287,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple, DoesOwnARenderSurfaceForOpacity) {
delegated_renderer_layer_->SetOpacity(0.5f);
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
// This test case has quads from multiple layers in the delegated renderer, so
// if the DelegatedRendererLayer has opacity < 1, it should end up with a
@@ -305,7 +305,7 @@ TEST_F(DelegatedRendererLayerImplTestSimple,
delegated_renderer_layer_->SetTransform(rotation);
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
// This test case has quads from multiple layers in the delegated renderer, so
// if the DelegatedRendererLayer has opacity < 1, it should end up with a
@@ -327,7 +327,7 @@ class DelegatedRendererLayerImplTestOwnSurface
TEST_F(DelegatedRendererLayerImplTestOwnSurface, AddsRenderPasses) {
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
// Each non-DelegatedRendererLayer added one RenderPass. The
// DelegatedRendererLayer added two contributing passes and its owned surface
@@ -366,7 +366,7 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface, AddsRenderPasses) {
TEST_F(DelegatedRendererLayerImplTestOwnSurface,
AddsQuadsToContributingRenderPasses) {
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
// Each non-DelegatedRendererLayer added one RenderPass. The
// DelegatedRendererLayer added two contributing passes and its owned surface
@@ -402,7 +402,7 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface,
TEST_F(DelegatedRendererLayerImplTestOwnSurface, AddsQuadsToTargetRenderPass) {
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
// Each non-DelegatedRendererLayer added one RenderPass. The
// DelegatedRendererLayer added two contributing passes and its owned surface
@@ -428,7 +428,7 @@ TEST_F(DelegatedRendererLayerImplTestOwnSurface, AddsQuadsToTargetRenderPass) {
TEST_F(DelegatedRendererLayerImplTestOwnSurface,
QuadsFromRootRenderPassAreNotModifiedForTheTarget) {
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
// Each non-DelegatedRendererLayer added one RenderPass. The
// DelegatedRendererLayer added two contributing passes and its owned surface
@@ -639,7 +639,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsUnclipped_NoSurface) {
SetUpTest();
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
const SharedQuadState* root_delegated_shared_quad_state = NULL;
const SharedQuadState* contrib_delegated_shared_quad_state = NULL;
@@ -693,7 +693,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsClipped_NoSurface) {
SetUpTest();
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
const SharedQuadState* root_delegated_shared_quad_state = NULL;
const SharedQuadState* contrib_delegated_shared_quad_state = NULL;
@@ -754,7 +754,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsUnclipped_Surface) {
delegated_renderer_layer_->SetForceRenderSurface(true);
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
const SharedQuadState* root_delegated_shared_quad_state = NULL;
const SharedQuadState* contrib_delegated_shared_quad_state = NULL;
@@ -809,7 +809,7 @@ TEST_F(DelegatedRendererLayerImplTestTransform, QuadsClipped_Surface) {
delegated_renderer_layer_->SetForceRenderSurface(true);
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
const SharedQuadState* root_delegated_shared_quad_state = NULL;
const SharedQuadState* contrib_delegated_shared_quad_state = NULL;
@@ -1011,7 +1011,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
SetUpTest();
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(2u, frame.render_passes.size());
const QuadList& contrib_delegated_quad_list =
@@ -1040,7 +1040,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
SetUpTest();
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(2u, frame.render_passes.size());
const QuadList& contrib_delegated_quad_list =
@@ -1069,7 +1069,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
SetUpTest();
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(2u, frame.render_passes.size());
const QuadList& contrib_delegated_quad_list =
@@ -1099,7 +1099,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
SetUpTest();
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(2u, frame.render_passes.size());
const QuadList& contrib_delegated_quad_list =
@@ -1130,7 +1130,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
delegated_renderer_layer_->SetForceRenderSurface(true);
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(3u, frame.render_passes.size());
const QuadList& contrib_delegated_quad_list =
@@ -1159,7 +1159,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
delegated_renderer_layer_->SetForceRenderSurface(true);
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(3u, frame.render_passes.size());
const QuadList& contrib_delegated_quad_list =
@@ -1189,7 +1189,7 @@ TEST_F(DelegatedRendererLayerImplTestClip,
delegated_renderer_layer_->SetForceRenderSurface(true);
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(3u, frame.render_passes.size());
const QuadList& contrib_delegated_quad_list =
@@ -1217,7 +1217,7 @@ TEST_F(DelegatedRendererLayerImplTestClip, QuadsClipped_LayerClipped_Surface) {
delegated_renderer_layer_->SetForceRenderSurface(true);
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(3u, frame.render_passes.size());
const QuadList& contrib_delegated_quad_list =
diff --git a/cc/output/delegating_renderer_unittest.cc b/cc/output/delegating_renderer_unittest.cc
index 5357a58..e270860 100644
--- a/cc/output/delegating_renderer_unittest.cc
+++ b/cc/output/delegating_renderer_unittest.cc
@@ -43,8 +43,9 @@ class DelegatingRendererTestDraw : public DelegatingRendererTest {
virtual void AfterTest() OVERRIDE {}
- virtual bool PrepareToDrawOnThread(
- LayerTreeHostImpl*, LayerTreeHostImpl::FrameData* frame, bool result)
+ virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame,
+ bool result)
OVERRIDE {
EXPECT_EQ(0u, output_surface_->num_sent_frames());
diff --git a/cc/test/fake_layer_tree_host_impl.h b/cc/test/fake_layer_tree_host_impl.h
index d46c625..5f8e0a4 100644
--- a/cc/test/fake_layer_tree_host_impl.h
+++ b/cc/test/fake_layer_tree_host_impl.h
@@ -20,7 +20,7 @@ class FakeLayerTreeHostImpl : public LayerTreeHostImpl {
void ForcePrepareToDraw() {
LayerTreeHostImpl::FrameData frame_data;
- PrepareToDraw(&frame_data);
+ PrepareToDraw(&frame_data, gfx::Rect());
DidDrawAllLayers(frame_data);
}
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index d602334..f1bad56 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -26,10 +26,9 @@
namespace cc {
-TestHooks::TestHooks() {
- fake_client_.reset(
- new FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D));
-}
+TestHooks::TestHooks()
+ : fake_client_(
+ new FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
TestHooks::~TestHooks() {}
@@ -100,8 +99,8 @@ class LayerTreeHostImplForTesting : public LayerTreeHostImpl {
test_hooks_->TreeActivatedOnThread(this);
}
- virtual bool PrepareToDraw(FrameData* frame) OVERRIDE {
- bool result = LayerTreeHostImpl::PrepareToDraw(frame);
+ virtual bool PrepareToDraw(FrameData* frame, gfx::Rect damage_rect) OVERRIDE {
+ bool result = LayerTreeHostImpl::PrepareToDraw(frame, damage_rect);
if (!test_hooks_->PrepareToDrawOnThread(this, frame, result))
result = false;
return result;
@@ -113,8 +112,8 @@ class LayerTreeHostImplForTesting : public LayerTreeHostImpl {
test_hooks_->DrawLayersOnThread(this);
}
- virtual bool SwapBuffers() OVERRIDE {
- bool result = LayerTreeHostImpl::SwapBuffers();
+ virtual bool SwapBuffers(const LayerTreeHostImpl::FrameData& frame) OVERRIDE {
+ bool result = LayerTreeHostImpl::SwapBuffers(frame);
test_hooks_->SwapBuffersOnThread(this, result);
return result;
}
@@ -413,7 +412,9 @@ void LayerTreeTest::DoBeginTest() {
void LayerTreeTest::SetupTree() {
if (!layer_tree_host_->root_layer()) {
scoped_refptr<Layer> root_layer = Layer::Create();
+ root_layer->SetAnchorPoint(gfx::PointF());
root_layer->SetBounds(gfx::Size(1, 1));
+ root_layer->SetIsDrawable(true);
layer_tree_host_->SetRootLayer(root_layer);
}
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index 0c56267..6be09b8 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -30,6 +30,8 @@ class TestHooks : public WebKit::WebAnimationDelegate {
TestHooks();
virtual ~TestHooks();
+ void ReadSettings(const LayerTreeSettings& settings);
+
virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) {}
virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) {}
virtual void TreeActivatedOnThread(LayerTreeHostImpl* host_impl) {}
diff --git a/cc/trees/damage_tracker.cc b/cc/trees/damage_tracker.cc
index 94ab9fa..16ae0a1 100644
--- a/cc/trees/damage_tracker.cc
+++ b/cc/trees/damage_tracker.cc
@@ -22,8 +22,7 @@ scoped_ptr<DamageTracker> DamageTracker::Create() {
DamageTracker::DamageTracker()
: current_rect_history_(new RectMap),
- next_rect_history_(new RectMap),
- force_full_damage_next_update_(false) {}
+ next_rect_history_(new RectMap) {}
DamageTracker::~DamageTracker() {}
@@ -135,10 +134,8 @@ void DamageTracker::UpdateDamageTrackingState(
gfx::RectF damage_rect_for_this_update;
- if (force_full_damage_next_update_ ||
- target_surface_property_changed_only_from_descendant) {
+ if (target_surface_property_changed_only_from_descendant) {
damage_rect_for_this_update = target_surface_content_rect;
- force_full_damage_next_update_ = false;
} else {
// TODO(shawnsingh): can we clamp this damage to the surface's content rect?
// (affects performance, but not correctness)
diff --git a/cc/trees/damage_tracker.h b/cc/trees/damage_tracker.h
index f09fe32..0627687 100644
--- a/cc/trees/damage_tracker.h
+++ b/cc/trees/damage_tracker.h
@@ -36,7 +36,7 @@ class CC_EXPORT DamageTracker {
~DamageTracker();
void DidDrawDamagedArea() { current_damage_rect_ = gfx::RectF(); }
- void ForceFullDamageNextUpdate() { force_full_damage_next_update_ = true; }
+ void AddDamageNextUpdate(gfx::RectF dmg) { current_damage_rect_.Union(dmg); }
void UpdateDamageTrackingState(
const LayerImplList& layer_list,
int target_surface_layer_id,
@@ -74,7 +74,6 @@ class CC_EXPORT DamageTracker {
scoped_ptr<RectMap> next_rect_history_;
gfx::RectF current_damage_rect_;
- bool force_full_damage_next_update_;
DISALLOW_COPY_AND_ASSIGN(DamageTracker);
};
diff --git a/cc/trees/damage_tracker_unittest.cc b/cc/trees/damage_tracker_unittest.cc
index d46a9a4..03767dc 100644
--- a/cc/trees/damage_tracker_unittest.cc
+++ b/cc/trees/damage_tracker_unittest.cc
@@ -1262,30 +1262,35 @@ TEST_F(DamageTrackerTest, VerifyDamageForReplicaMaskWithAnchor) {
EXPECT_FLOAT_RECT_EQ(gfx::RectF(206.f, 200.f, 6.f, 8.f), child_damage_rect);
}
-TEST_F(DamageTrackerTest, VerifyDamageWhenForcedFullDamage) {
+TEST_F(DamageTrackerTest, DamageWhenAddedExternally) {
scoped_ptr<LayerImpl> root = CreateAndSetUpTestTreeWithOneSurface();
LayerImpl* child = root->children()[0];
- // Case 1: This test ensures that when the tracker is forced to have full
- // damage, that it takes priority over any other partial damage.
+ // Case 1: This test ensures that when the tracker is given damage, that
+ // it is included with any other partial damage.
//
ClearDamageForAllSurfaces(root.get());
- child->set_update_rect(gfx::RectF(10.f, 11.f, 12.f, 13.f));
- root->render_surface()->damage_tracker()->ForceFullDamageNextUpdate();
+ child->set_update_rect(gfx::RectF(10, 11, 12, 13));
+ root->render_surface()->damage_tracker()->AddDamageNextUpdate(
+ gfx::RectF(15, 16, 32, 33));
EmulateDrawingOneFrame(root.get());
gfx::RectF root_damage_rect =
- root->render_surface()->damage_tracker()->current_damage_rect();
- EXPECT_FLOAT_RECT_EQ(gfx::RectF(0.f, 0.f, 500.f, 500.f), root_damage_rect);
+ root->render_surface()->damage_tracker()->current_damage_rect();
+ EXPECT_FLOAT_RECT_EQ(
+ gfx::UnionRects(gfx::RectF(15, 16, 32, 33),
+ gfx::RectF(100+10, 100+11, 12, 13)),
+ root_damage_rect);
- // Case 2: An additional sanity check that forcing full damage works even
- // when nothing on the layer tree changed.
+ // Case 2: An additional sanity check that adding damage works even when
+ // nothing on the layer tree changed.
//
ClearDamageForAllSurfaces(root.get());
- root->render_surface()->damage_tracker()->ForceFullDamageNextUpdate();
+ root->render_surface()->damage_tracker()->AddDamageNextUpdate(
+ gfx::RectF(30, 31, 14, 15));
EmulateDrawingOneFrame(root.get());
root_damage_rect =
- root->render_surface()->damage_tracker()->current_damage_rect();
- EXPECT_FLOAT_RECT_EQ(gfx::RectF(0.f, 0.f, 500.f, 500.f), root_damage_rect);
+ root->render_surface()->damage_tracker()->current_damage_rect();
+ EXPECT_FLOAT_RECT_EQ(gfx::RectF(30, 31, 14, 15), root_damage_rect);
}
TEST_F(DamageTrackerTest, VerifyDamageForEmptyLayerList) {
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 68083c2..7152fcb 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -139,7 +139,7 @@ class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient {
};
LayerTreeHostImpl::FrameData::FrameData()
- : contains_incomplete_tile(false) {}
+ : contains_incomplete_tile(false), has_no_damage(false) {}
LayerTreeHostImpl::FrameData::~FrameData() {}
@@ -183,6 +183,7 @@ LayerTreeHostImpl::LayerTreeHostImpl(
last_sent_memory_visible_bytes_(0),
last_sent_memory_visible_and_nearby_bytes_(0),
last_sent_memory_use_bytes_(0),
+ next_frame_damages_full_device_viewport_(false),
animation_registrar_(AnimationRegistrar::Create()),
rendering_stats_instrumentation_(rendering_stats_instrumentation) {
DCHECK(proxy_->IsImplThread());
@@ -508,6 +509,23 @@ bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
TrackDamageForAllSurfaces(active_tree_->root_layer(),
*frame->render_surface_layer_list);
+ // If the root render surface has no visible damage, then don't generate a
+ // frame at all.
+ RenderSurfaceImpl* root_surface =
+ active_tree_->root_layer()->render_surface();
+ bool root_surface_has_no_visible_damage =
+ !root_surface->damage_tracker()->current_damage_rect().Intersects(
+ root_surface->content_rect());
+ bool root_surface_has_contributing_layers =
+ !root_surface->layer_list().empty();
+ if (root_surface_has_contributing_layers &&
+ root_surface_has_no_visible_damage) {
+ TRACE_EVENT0("cc",
+ "LayerTreeHostImpl::CalculateRenderPasses::EmptyDamageRect");
+ frame->has_no_damage = true;
+ return true;
+ }
+
TRACE_EVENT1("cc",
"LayerTreeHostImpl::CalculateRenderPasses",
"render_surface_layer_list.size()",
@@ -675,6 +693,8 @@ bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
RemoveRenderPasses(CullRenderPassesWithCachedTextures(renderer_.get()),
frame);
+ // If we're making a frame to draw, it better have at least one render pass.
+ DCHECK(!frame->render_passes.empty());
return draw_frame;
}
@@ -827,7 +847,8 @@ void LayerTreeHostImpl::RemoveRenderPasses(RenderPassCuller culler,
}
}
-bool LayerTreeHostImpl::PrepareToDraw(FrameData* frame) {
+bool LayerTreeHostImpl::PrepareToDraw(FrameData* frame,
+ gfx::Rect device_viewport_damage_rect) {
TRACE_EVENT0("cc", "LayerTreeHostImpl::PrepareToDraw");
active_tree_->UpdateDrawProperties(
@@ -837,6 +858,17 @@ bool LayerTreeHostImpl::PrepareToDraw(FrameData* frame) {
frame->render_passes.clear();
frame->render_passes_by_id.clear();
frame->will_draw_layers.clear();
+ frame->contains_incomplete_tile = false;
+ frame->has_no_damage = false;
+
+ if (active_tree_->root_layer()) {
+ if (next_frame_damages_full_device_viewport_)
+ device_viewport_damage_rect.Union(gfx::Rect(device_viewport_size_));
+
+ active_tree_->root_layer()->render_surface()->damage_tracker()->
+ AddDamageNextUpdate(device_viewport_damage_rect);
+ }
+ next_frame_damages_full_device_viewport_ = false;
if (!CalculateRenderPasses(frame))
return false;
@@ -997,6 +1029,10 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame,
base::TimeTicks frame_begin_time) {
TRACE_EVENT0("cc", "LayerTreeHostImpl::DrawLayers");
DCHECK(CanDraw());
+
+ if (frame->has_no_damage)
+ return;
+
DCHECK(!frame->render_passes.empty());
fps_counter_->SaveTimeStamp(frame_begin_time);
@@ -1074,7 +1110,9 @@ const RendererCapabilities& LayerTreeHostImpl::GetRendererCapabilities() const {
return renderer_->Capabilities();
}
-bool LayerTreeHostImpl::SwapBuffers() {
+bool LayerTreeHostImpl::SwapBuffers(const LayerTreeHostImpl::FrameData& frame) {
+ if (frame.has_no_damage)
+ return false;
return renderer_->SwapBuffers();
}
@@ -1763,12 +1801,7 @@ scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() {
}
void LayerTreeHostImpl::SetFullRootLayerDamage() {
- if (active_tree_->root_layer()) {
- RenderSurfaceImpl* render_surface =
- active_tree_->root_layer()->render_surface();
- if (render_surface)
- render_surface->damage_tracker()->ForceFullDamageNextUpdate();
- }
+ next_frame_damages_full_device_viewport_ = true;
}
void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks time) {
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 016b165..0730c73 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -131,6 +131,7 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandlerClient,
const LayerImplList* render_surface_layer_list;
LayerImplList will_draw_layers;
bool contains_incomplete_tile;
+ bool has_no_damage;
// RenderPassSink implementation.
virtual void AppendRenderPass(scoped_ptr<RenderPass> render_pass) OVERRIDE;
@@ -150,7 +151,8 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandlerClient,
// to avoid displaying the frame. If PrepareToDraw is called, DidDrawAllLayers
// must also be called, regardless of whether DrawLayers is called between the
// two.
- virtual bool PrepareToDraw(FrameData* frame);
+ virtual bool PrepareToDraw(FrameData* frame,
+ gfx::Rect device_viewport_damage_rect);
virtual void DrawLayers(FrameData* frame, base::TimeTicks frame_begin_time);
// Must be called if and only if PrepareToDraw was called.
void DidDrawAllLayers(const FrameData& frame);
@@ -208,7 +210,7 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandlerClient,
Renderer* renderer() { return renderer_.get(); }
const RendererCapabilities& GetRendererCapabilities() const;
- virtual bool SwapBuffers();
+ virtual bool SwapBuffers(const FrameData& frame);
void EnableVSyncNotification(bool enable);
void Readback(void* pixels, gfx::Rect rect_in_device_viewport);
@@ -462,6 +464,8 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandlerClient,
size_t last_sent_memory_visible_and_nearby_bytes_;
size_t last_sent_memory_use_bytes_;
+ bool next_frame_damages_full_device_viewport_;
+
base::TimeTicks current_frame_time_;
scoped_ptr<AnimationRegistrar> animation_registrar_;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 40d0ced..49c9b0b 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -224,7 +224,7 @@ class LayerTreeHostImplTest : public testing::Test,
void InitializeRendererAndDrawFrame() {
host_impl_->InitializeRenderer(CreateOutputSurface());
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -242,7 +242,7 @@ class LayerTreeHostImplTest : public testing::Test,
void DrawOneFrame() {
LayerTreeHostImpl::FrameData frame_data;
- host_impl_->PrepareToDraw(&frame_data);
+ host_impl_->PrepareToDraw(&frame_data, gfx::Rect());
host_impl_->DidDrawAllLayers(frame_data);
}
@@ -1058,7 +1058,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
EXPECT_FALSE(layer->will_draw_called());
EXPECT_FALSE(layer->did_draw_called());
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
@@ -1073,7 +1073,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
EXPECT_FALSE(layer->will_draw_called());
EXPECT_FALSE(layer->did_draw_called());
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
@@ -1112,7 +1112,7 @@ TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
EXPECT_FALSE(top_layer->will_draw_called());
EXPECT_FALSE(top_layer->did_draw_called());
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
@@ -1144,7 +1144,7 @@ TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
EXPECT_FALSE(layer2->did_draw_called());
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
@@ -1216,7 +1216,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
@@ -1234,7 +1234,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
false,
host_impl_->resource_provider()));
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
@@ -1252,7 +1252,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
true,
host_impl_->resource_provider()));
- EXPECT_FALSE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_FALSE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
@@ -1269,7 +1269,7 @@ TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
true,
host_impl_->resource_provider()));
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -1308,6 +1308,7 @@ TEST_F(LayerTreeHostImplTest, ScrollNonScrollableRootWithTopControls) {
root->SetContentBounds(layer_size);
root->SetPosition(gfx::PointF());
root->SetAnchorPoint(gfx::PointF());
+ root->SetDrawsContent(false);
host_impl_->active_tree()->SetRootLayer(root.Pass());
host_impl_->active_tree()->FindRootScrollLayer();
InitializeRendererAndDrawFrame();
@@ -1610,7 +1611,7 @@ TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
// Make sure all the layers are drawn with the page scale delta applied, i.e.,
// the page scale delta on the root layer is applied hierarchically.
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
@@ -2146,7 +2147,8 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
// Opaque layer, drawn without blending.
layer1->SetContentsOpaque(true);
layer1->SetExpectation(false, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2154,7 +2156,8 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
// Layer with translucent content and painting, so drawn with blending.
layer1->SetContentsOpaque(false);
layer1->SetExpectation(true, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2163,7 +2166,8 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetContentsOpaque(true);
layer1->SetOpacity(0.5f);
layer1->SetExpectation(true, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2172,7 +2176,8 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetContentsOpaque(true);
layer1->SetOpacity(0.5f);
layer1->SetExpectation(true, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2189,10 +2194,12 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetContentsOpaque(true);
layer1->SetOpacity(1.f);
layer1->SetExpectation(false, false);
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
layer2->SetContentsOpaque(true);
layer2->SetOpacity(1.f);
layer2->SetExpectation(false, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -2202,8 +2209,10 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
// Child layer with opaque content, drawn without blending.
layer1->SetContentsOpaque(false);
layer1->SetExpectation(true, false);
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
layer2->SetExpectation(false, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -2214,8 +2223,10 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
// Child layer with opaque content, drawn without blending.
layer1->SetContentsOpaque(true);
layer1->SetExpectation(false, false);
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
layer2->SetExpectation(false, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -2229,8 +2240,10 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetContentsOpaque(true);
layer1->SetOpacity(0.5f);
layer1->SetExpectation(false, true);
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
layer2->SetExpectation(false, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -2241,10 +2254,12 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetContentsOpaque(true);
layer1->SetOpacity(1.f);
layer1->SetExpectation(false, false);
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
layer2->SetContentsOpaque(true);
layer2->SetOpacity(0.5f);
layer2->SetExpectation(true, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -2254,10 +2269,12 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetContentsOpaque(true);
layer1->SetOpacity(1.f);
layer1->SetExpectation(false, false);
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
layer2->SetContentsOpaque(false);
layer2->SetOpacity(1.f);
layer2->SetExpectation(true, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -2268,10 +2285,12 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetContentsOpaque(true);
layer1->SetOpacity(1.f);
layer1->SetExpectation(false, false);
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
layer2->SetContentsOpaque(true);
layer2->SetOpacity(1.f);
layer2->SetExpectation(false, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
EXPECT_TRUE(layer2->quads_appended());
@@ -2283,7 +2302,8 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
layer1->SetExpectation(true, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2294,7 +2314,8 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
layer1->SetExpectation(true, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2305,7 +2326,8 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
layer1->SetExpectation(true, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2317,7 +2339,8 @@ TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
layer1->SetExpectation(false, false);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(layer1->quads_appended());
host_impl_->DidDrawAllLayers(frame);
@@ -2351,7 +2374,7 @@ TEST_F(LayerTreeHostImplTest, ViewportCovered) {
child->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(1u, frame.render_passes.size());
size_t num_gutter_quads = 0;
@@ -2376,7 +2399,7 @@ TEST_F(LayerTreeHostImplTest, ViewportCovered) {
child->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(1u, frame.render_passes.size());
size_t num_gutter_quads = 0;
@@ -2401,7 +2424,7 @@ TEST_F(LayerTreeHostImplTest, ViewportCovered) {
child->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(1u, frame.render_passes.size());
size_t num_gutter_quads = 0;
@@ -2457,12 +2480,13 @@ TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
root->SetAnchorPoint(gfx::PointF());
root->SetBounds(gfx::Size(10, 10));
+ root->SetContentBounds(gfx::Size(10, 10));
root->SetDrawsContent(true);
host_impl_->active_tree()->SetRootLayer(root.Pass());
EXPECT_FALSE(reshape_tracker->reshape_called());
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
EXPECT_TRUE(reshape_tracker->reshape_called());
host_impl_->DidDrawAllLayers(frame);
@@ -2531,10 +2555,10 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
LayerTreeHostImpl::FrameData frame;
// First frame, the entire screen should get swapped.
- EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
layer_tree_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
layer_tree_host_impl->DidDrawAllLayers(frame);
- layer_tree_host_impl->SwapBuffers();
+ layer_tree_host_impl->SwapBuffers(frame);
gfx::Rect actual_swap_rect = partial_swap_tracker->partial_swap_rect();
gfx::Rect expected_swap_rect = gfx::Rect(0, 0, 500, 500);
EXPECT_EQ(expected_swap_rect.x(), actual_swap_rect.x());
@@ -2548,10 +2572,10 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
// expected swap rect: vertically flipped, with origin at bottom left corner.
layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
gfx::PointF());
- EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
layer_tree_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
- layer_tree_host_impl->SwapBuffers();
+ layer_tree_host_impl->SwapBuffers(frame);
actual_swap_rect = partial_swap_tracker->partial_swap_rect();
expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
EXPECT_EQ(expected_swap_rect.x(), actual_swap_rect.x());
@@ -2565,10 +2589,10 @@ TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10), gfx::Size(10, 10));
// This will damage everything.
layer_tree_host_impl->active_tree()->root_layer()->SetOpacity(0.7f);
- EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
layer_tree_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
- layer_tree_host_impl->SwapBuffers();
+ layer_tree_host_impl->SwapBuffers(frame);
actual_swap_rect = partial_swap_tracker->partial_swap_rect();
expected_swap_rect = gfx::Rect(10, 10);
EXPECT_EQ(expected_swap_rect.x(), actual_swap_rect.x());
@@ -2597,7 +2621,7 @@ TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
EXPECT_EQ(1u, frame.render_surface_layer_list->size());
EXPECT_EQ(1u, frame.render_passes.size());
host_impl_->DidDrawAllLayers(frame);
@@ -2743,7 +2767,7 @@ TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
harness.MustSetNoScissor();
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -2756,7 +2780,7 @@ TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
harness.MustSetScissor(0, 0, 10, 10);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -2779,7 +2803,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwap) {
harness.MustDrawSolidQuad();
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -2794,7 +2818,7 @@ TEST_F(LayerTreeHostImplTest, PartialSwap) {
harness.MustDrawSolidQuad();
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
}
@@ -2903,7 +2927,7 @@ TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
SetupLayersForOpacity(true, this, &proxy_, &stats_instrumentation_);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Verify all quads have been computed
ASSERT_EQ(2U, frame.render_passes.size());
@@ -2924,7 +2948,7 @@ TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
SetupLayersForOpacity(false, this, &proxy_, &stats_instrumentation_);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Verify all quads have been computed
ASSERT_EQ(2U, frame.render_passes.size());
@@ -3019,10 +3043,10 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
EXPECT_EQ(0u, context3d->NumTextures());
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
- host_impl_->SwapBuffers();
+ host_impl_->SwapBuffers(frame);
EXPECT_GT(context3d->NumTextures(), 0u);
@@ -3062,14 +3086,15 @@ TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
.Times(1);
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
Mock::VerifyAndClearExpectations(&mock_context);
// Verify no quads are drawn when transparent background is set.
host_impl_->active_tree()->set_has_transparent_background(true);
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ host_impl_->SetFullRootLayerDamage();
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
Mock::VerifyAndClearExpectations(&mock_context);
@@ -3214,7 +3239,7 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusion) {
// Initial draw - must receive all quads
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive 3 render passes.
// For Root, there are 2 quads; for S1, there are 2 quads (1 is occluded);
@@ -3237,7 +3262,7 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusion) {
layer_s2_ptr->SetTransform(transform);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive 2 render passes.
// For Root, there are 2 quads
@@ -3261,7 +3286,7 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusion) {
layer_s2_ptr->SetTransform(transform);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive 1 render pass - for the root.
ASSERT_EQ(1U, frame.render_passes.size());
@@ -3335,7 +3360,7 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionEarlyOut) {
// Initial draw - must receive all quads
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive 3 render passes.
// For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is
@@ -3360,7 +3385,7 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionEarlyOut) {
layer_s2_ptr->SetTransform(transform);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive 2 render passes.
// For Root, there are 2 quads
@@ -3384,7 +3409,7 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionEarlyOut) {
layer_s2_ptr->SetTransform(transform);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive 1 render pass - for the root.
ASSERT_EQ(1U, frame.render_passes.size());
@@ -3452,7 +3477,7 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionExternalOverInternal) {
// Initial draw - must receive all quads
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive 3 render passes.
// For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is
@@ -3475,7 +3500,7 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionExternalOverInternal) {
layer_s2_ptr->SetTransform(transform);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive 2 render passes.
// For Root, there are 2 quads
@@ -3543,7 +3568,7 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionExternalNotAligned) {
// Initial draw - must receive all quads
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive 2 render passes.
ASSERT_EQ(2U, frame.render_passes.size());
@@ -3559,7 +3584,7 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionExternalNotAligned) {
layer_s1_ptr->SetOpacity(0.2f);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// One render pass must be gone due to cached texture.
ASSERT_EQ(1U, frame.render_passes.size());
@@ -3635,7 +3660,7 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionPartialSwap) {
// Initial draw - must receive all quads
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive 3 render passes.
// For Root, there are 2 quads; for S1, there are 2 quads (one is occluded);
@@ -3658,7 +3683,7 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionPartialSwap) {
layer_s2_ptr->SetTransform(transform);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive 2 render passes.
// For Root, there are 2 quads.
@@ -3681,7 +3706,7 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionPartialSwap) {
layer_s2_ptr->SetTransform(transform);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Root render pass only.
ASSERT_EQ(1U, frame.render_passes.size());
@@ -3775,7 +3800,8 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithScissor) {
child_pass_id));
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ host_impl_->SetFullRootLayerDamage();
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
my_host_impl->DidDrawAllLayers(frame);
}
@@ -3785,7 +3811,8 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithScissor) {
child_pass_id));
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ host_impl_->SetFullRootLayerDamage();
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
my_host_impl->DidDrawAllLayers(frame);
}
@@ -3799,7 +3826,8 @@ TEST_F(LayerTreeHostImplTest, TextureCachingWithScissor) {
child_ptr->set_update_rect(gfx::Rect(10, 10, 10, 10));
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ host_impl_->SetFullRootLayerDamage();
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
my_host_impl->DidDrawAllLayers(frame);
}
@@ -3834,7 +3862,7 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCaching) {
gfx::Size(100, 100));
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive two render passes, each with one quad
ASSERT_EQ(2U, frame.render_passes.size());
@@ -3856,7 +3884,8 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCaching) {
// Draw without any change
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ my_host_impl->SetFullRootLayerDamage();
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive one render pass, as the other one should be culled
ASSERT_EQ(1U, frame.render_passes.size());
@@ -3877,7 +3906,7 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCaching) {
surface_layer_ptr->SetOpacity(0.6f);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive one render pass, as the other one should be culled
ASSERT_EQ(1U, frame.render_passes.size());
@@ -3898,7 +3927,7 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCaching) {
surface_layer_ptr->SetStackingOrderChanged(true);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive two render passes, each with one quad
ASSERT_EQ(2U, frame.render_passes.size());
@@ -3928,7 +3957,7 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCaching) {
surface_layer_ptr->SetOpacity(0.6f);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive two render passes
ASSERT_EQ(2U, frame.render_passes.size());
@@ -3957,7 +3986,8 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCaching) {
// Draw without any change, to make sure the state is clear
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ my_host_impl->SetFullRootLayerDamage();
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive one render pass, as the other one should be culled
ASSERT_EQ(1U, frame.render_passes.size());
@@ -3980,7 +4010,7 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCaching) {
intermediate_layer_ptr->SetTransform(transform);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive one render pass, as the other one should be culled.
ASSERT_EQ(1U, frame.render_passes.size());
@@ -4021,7 +4051,7 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCachingNoPartialSwap) {
gfx::Size(100, 100));
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive two render passes, each with one quad
ASSERT_EQ(2U, frame.render_passes.size());
@@ -4050,7 +4080,8 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCachingNoPartialSwap) {
// Draw without any change
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ my_host_impl->SetFullRootLayerDamage();
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Even though there was no change, we set the damage to entire viewport.
// One of the passes should be culled as a result, since contents didn't
@@ -4058,8 +4089,6 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCachingNoPartialSwap) {
ASSERT_EQ(1U, frame.render_passes.size());
EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
- EXPECT_TRUE(frame.render_passes[0]->damage_rect.IsEmpty());
-
my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
my_host_impl->DidDrawAllLayers(frame);
}
@@ -4068,7 +4097,7 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCachingNoPartialSwap) {
surface_layer_ptr->SetOpacity(0.6f);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive one render pass, as the other one should be culled
ASSERT_EQ(1U, frame.render_passes.size());
@@ -4089,7 +4118,7 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCachingNoPartialSwap) {
surface_layer_ptr->SetStackingOrderChanged(true);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive two render passes, each with one quad
ASSERT_EQ(2U, frame.render_passes.size());
@@ -4119,7 +4148,7 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCachingNoPartialSwap) {
surface_layer_ptr->SetOpacity(0.6f);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive two render passes
ASSERT_EQ(2U, frame.render_passes.size());
@@ -4148,7 +4177,8 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCachingNoPartialSwap) {
// Draw without any change, to make sure the state is clear
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ my_host_impl->SetFullRootLayerDamage();
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Even though there was no change, we set the damage to entire viewport.
// One of the passes should be culled as a result, since contents didn't
@@ -4166,7 +4196,7 @@ TEST_F(LayerTreeHostImplTest, SurfaceTextureCachingNoPartialSwap) {
intermediate_layer_ptr->SetTransform(transform);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame));
+ EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
// Must receive one render pass, as the other one should be culled.
ASSERT_EQ(1U, frame.render_passes.size());
@@ -4645,23 +4675,39 @@ class LayerTreeHostImplTestWithDelegatingRenderer
}
void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
- LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
- ASSERT_EQ(1u, frame.render_passes.size());
-
- // Verify the damage rect for the root render pass.
- const RenderPass* root_render_pass = frame.render_passes.back();
- EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
+ bool expect_to_draw = !expected_damage.IsEmpty();
- // Verify the root layer's quad is generated and not being culled.
- ASSERT_EQ(1u, root_render_pass->quad_list.size());
- gfx::Rect expected_visible_rect(
- host_impl_->active_tree()->root_layer()->content_bounds());
- EXPECT_RECT_EQ(expected_visible_rect,
- root_render_pass->quad_list[0]->visible_rect);
+ LayerTreeHostImpl::FrameData frame;
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
+
+ if (!expect_to_draw) {
+ // With no damage, we don't draw, and no quads are created.
+ ASSERT_EQ(0u, frame.render_passes.size());
+ } else {
+ ASSERT_EQ(1u, frame.render_passes.size());
+
+ // Verify the damage rect for the root render pass.
+ const RenderPass* root_render_pass = frame.render_passes.back();
+ EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
+
+ // Verify the root and child layers' quads are generated and not being
+ // culled.
+ ASSERT_EQ(2u, root_render_pass->quad_list.size());
+
+ LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
+ gfx::RectF expected_child_visible_rect(child->content_bounds());
+ EXPECT_RECT_EQ(expected_child_visible_rect,
+ root_render_pass->quad_list[0]->visible_rect);
+
+ LayerImpl* root = host_impl_->active_tree()->root_layer();
+ gfx::RectF expected_root_visible_rect(root->content_bounds());
+ EXPECT_RECT_EQ(expected_root_visible_rect,
+ root_render_pass->quad_list[1]->visible_rect);
+ }
host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
host_impl_->DidDrawAllLayers(frame);
+ EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
}
};
@@ -4673,14 +4719,30 @@ TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
root->SetBounds(gfx::Size(10, 10));
root->SetContentBounds(gfx::Size(10, 10));
root->SetDrawsContent(true);
+
+ // Child layer is in the bottom right corner.
+ scoped_ptr<SolidColorLayerImpl> child =
+ SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
+ child->SetAnchorPoint(gfx::PointF(0.f, 0.f));
+ child->SetPosition(gfx::PointF(9.f, 9.f));
+ child->SetBounds(gfx::Size(1, 1));
+ child->SetContentBounds(gfx::Size(1, 1));
+ child->SetDrawsContent(true);
+ root->AddChild(child.PassAs<LayerImpl>());
+
host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
// Draw a frame. In the first frame, the entire viewport should be damaged.
gfx::Rect full_frame_damage = gfx::Rect(host_impl_->device_viewport_size());
DrawFrameAndTestDamage(full_frame_damage);
- // The second frame should have no damage, but the quads should still be
- // generated.
+ // The second frame has damage that doesn't touch the child layer. Its quads
+ // should still be generated.
+ gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
+ host_impl_->active_tree()->root_layer()->set_update_rect(small_damage);
+ DrawFrameAndTestDamage(small_damage);
+
+ // The third frame should have no damage, so no quads should be generated.
gfx::Rect no_damage;
DrawFrameAndTestDamage(no_damage);
}
@@ -4763,7 +4825,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
host_impl_->SetDeviceScaleFactor(device_scale_factor);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(1u, frame.render_passes.size());
ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
@@ -4791,7 +4853,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
host_impl_->active_tree()->set_needs_update_draw_properties();
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(1u, frame.render_passes.size());
ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
@@ -4821,7 +4883,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
host_impl_->active_tree()->set_needs_update_draw_properties();
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(1u, frame.render_passes.size());
ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
@@ -4885,7 +4947,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
host_impl_->SetDeviceScaleFactor(device_scale_factor);
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(1u, frame.render_passes.size());
ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
@@ -4913,7 +4975,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
host_impl_->active_tree()->set_needs_update_draw_properties();
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(1u, frame.render_passes.size());
ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
@@ -4944,7 +5006,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
host_impl_->active_tree()->set_needs_update_draw_properties();
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(1u, frame.render_passes.size());
ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
@@ -4968,7 +5030,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
host_impl_->active_tree()->set_needs_update_draw_properties();
{
LayerTreeHostImpl::FrameData frame;
- EXPECT_TRUE(host_impl_->PrepareToDraw(&frame));
+ EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
ASSERT_EQ(1u, frame.render_passes.size());
ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
diff --git a/cc/trees/layer_tree_host_perftest.cc b/cc/trees/layer_tree_host_perftest.cc
index bd3849e..8f247e8 100644
--- a/cc/trees/layer_tree_host_perftest.cc
+++ b/cc/trees/layer_tree_host_perftest.cc
@@ -26,7 +26,8 @@ static const int kTimeCheckInterval = 10;
class LayerTreeHostPerfTest : public LayerTreeTest {
public:
LayerTreeHostPerfTest()
- : num_draws_(0) {
+ : num_draws_(0),
+ full_damage_each_frame_(false) {
fake_content_layer_client_.set_paint_all_opaque(true);
}
@@ -49,6 +50,8 @@ class LayerTreeHostPerfTest : public LayerTreeTest {
}
}
impl->setNeedsRedraw();
+ if (full_damage_each_frame_)
+ impl->SetFullRootLayerDamage();
}
virtual void BuildTree() {}
@@ -66,6 +69,7 @@ class LayerTreeHostPerfTest : public LayerTreeTest {
std::string test_name_;
base::TimeDelta elapsed_;
FakeContentLayerClient fake_content_layer_client_;
+ bool full_damage_each_frame_;
};
@@ -102,6 +106,14 @@ TEST_F(LayerTreeHostPerfTestJsonReader, TenTenSingleThread) {
RunTest(false);
}
+// Simulates a tab switcher scene with two stacks of 10 tabs each.
+TEST_F(LayerTreeHostPerfTestJsonReader,
+ TenTenSingleThread_FullDamageEachFrame) {
+ full_damage_each_frame_ = true;
+ ReadTestFile("10_10_layer_tree");
+ RunTest(false);
+}
+
// Simulates main-thread scrolling on each frame.
class ScrollingLayerTreePerfTest : public LayerTreeHostPerfTestJsonReader {
public:
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 130e8b6..f53a618 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -120,19 +120,20 @@ class LayerTreeHostTestSetNeedsCommit2 : public LayerTreeHostTest {
virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ ++num_draws_;
+ }
+
+ virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
+ ++num_commits_;
if (impl->active_tree()->source_frame_number() == 0)
PostSetNeedsCommitToMainThread();
else if (impl->active_tree()->source_frame_number() == 1)
EndTest();
}
- virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
- num_commits_++;
- }
-
virtual void AfterTest() OVERRIDE {
EXPECT_EQ(2, num_commits_);
- EXPECT_GE(2, num_draws_);
+ EXPECT_LE(1, num_draws_);
}
private:
@@ -694,7 +695,7 @@ class LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers
// Compute all the layer transforms for the frame.
LayerTreeHostImpl::FrameData frame_data;
- impl->PrepareToDraw(&frame_data);
+ impl->PrepareToDraw(&frame_data, gfx::Rect());
impl->DidDrawAllLayers(frame_data);
const LayerImplList& render_surface_layer_list =
@@ -1124,15 +1125,15 @@ class LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit
: public LayerTreeHostTest {
public:
LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit()
- : root_layer_(ContentLayerWithUpdateTracking::Create(&fake_delegate_)),
+ : root_layer_(FakeContentLayer::Create(&client_)),
surface_layer1_(
- ContentLayerWithUpdateTracking::Create(&fake_delegate_)),
+ FakeContentLayer::Create(&client_)),
replica_layer1_(
- ContentLayerWithUpdateTracking::Create(&fake_delegate_)),
+ FakeContentLayer::Create(&client_)),
surface_layer2_(
- ContentLayerWithUpdateTracking::Create(&fake_delegate_)),
+ FakeContentLayer::Create(&client_)),
replica_layer2_(
- ContentLayerWithUpdateTracking::Create(&fake_delegate_)) {}
+ FakeContentLayer::Create(&client_)) {}
virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
settings->cache_render_pass_contents = true;
@@ -1192,19 +1193,24 @@ class LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit
}
}
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ if (!TestEnded())
+ root_layer_->SetNeedsDisplay();
+ }
+
virtual void AfterTest() OVERRIDE {
- EXPECT_EQ(2, root_layer_->PaintContentsCount());
- EXPECT_EQ(2, surface_layer1_->PaintContentsCount());
- EXPECT_EQ(2, surface_layer2_->PaintContentsCount());
+ EXPECT_EQ(3u, root_layer_->update_count());
+ EXPECT_EQ(3u, surface_layer1_->update_count());
+ EXPECT_EQ(3u, surface_layer2_->update_count());
}
private:
- FakeContentLayerClient fake_delegate_;
- scoped_refptr<ContentLayerWithUpdateTracking> root_layer_;
- scoped_refptr<ContentLayerWithUpdateTracking> surface_layer1_;
- scoped_refptr<ContentLayerWithUpdateTracking> replica_layer1_;
- scoped_refptr<ContentLayerWithUpdateTracking> surface_layer2_;
- scoped_refptr<ContentLayerWithUpdateTracking> replica_layer2_;
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> root_layer_;
+ scoped_refptr<FakeContentLayer> surface_layer1_;
+ scoped_refptr<FakeContentLayer> replica_layer1_;
+ scoped_refptr<FakeContentLayer> surface_layer2_;
+ scoped_refptr<FakeContentLayer> replica_layer2_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(
@@ -1362,7 +1368,7 @@ class LayerTreeHostTestEvictTextures : public LayerTreeHostTest {
// the beginFrame/commit pair.
// Commits 5+6 test the path where an eviction happens during the eviction
// recovery path.
- virtual void DidCommitAndDrawFrame() OVERRIDE {
+ virtual void DidCommit() OVERRIDE {
switch (num_commits_) {
case 1:
EXPECT_TRUE(layer_->HaveBackingTexture());
@@ -1449,7 +1455,7 @@ class LayerTreeHostTestContinuousCommit : public LayerTreeHostTest {
virtual void DidCommit() OVERRIDE {
if (num_draw_layers_ == 2)
return;
- PostSetNeedsCommitToMainThread();
+ layer_tree_host()->root_layer()->SetNeedsDisplay();
}
virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
@@ -1484,7 +1490,7 @@ class LayerTreeHostTestContinuousInvalidate : public LayerTreeHostTest {
layer_tree_host()->SetViewportSize(gfx::Size(10, 10), gfx::Size(10, 10));
layer_tree_host()->root_layer()->SetBounds(gfx::Size(10, 10));
- content_layer_ = ContentLayer::Create(&fake_delegate_);
+ content_layer_ = ContentLayer::Create(&client_);
content_layer_->SetBounds(gfx::Size(10, 10));
content_layer_->SetPosition(gfx::PointF(0.f, 0.f));
content_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f));
@@ -1517,7 +1523,7 @@ class LayerTreeHostTestContinuousInvalidate : public LayerTreeHostTest {
}
private:
- FakeContentLayerClient fake_delegate_;
+ FakeContentLayerClient client_;
scoped_refptr<Layer> content_layer_;
int num_commit_complete_;
int num_draw_layers_;
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
index 6b95121..abde0a8 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -155,7 +155,8 @@ class LayerTreeHostContextTest : public LayerTreeTest {
LayerTreeHostImpl::FrameData* frame,
bool result)
OVERRIDE {
- EXPECT_TRUE(result);
+ bool expect_success = !frame->has_no_damage;
+ EXPECT_EQ(expect_success, result);
if (!times_to_lose_during_draw_)
return result;
@@ -269,7 +270,8 @@ class LayerTreeHostContextTestLostContextSucceeds
}
virtual void InvalidateAndSetNeedsCommit() {
- layer_tree_host()->SetNeedsCommit();
+ // Cause damage so we try to draw.
+ layer_tree_host()->root_layer()->SetNeedsDisplay();
}
bool NextTestCase() {
@@ -1050,10 +1052,9 @@ class LayerTreeHostContextTestDontUseLostResources
}
}
- virtual bool PrepareToDrawOnThread(
- LayerTreeHostImpl* host_impl,
- LayerTreeHostImpl::FrameData* frame,
- bool result) OVERRIDE {
+ virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame,
+ bool result) OVERRIDE {
if (host_impl->active_tree()->source_frame_number() == 2) {
// Lose the context during draw on the second commit. This will cause
// a third commit to recover.
diff --git a/cc/trees/layer_tree_host_unittest_damage.cc b/cc/trees/layer_tree_host_unittest_damage.cc
new file mode 100644
index 0000000..a66b798a
--- /dev/null
+++ b/cc/trees/layer_tree_host_unittest_damage.cc
@@ -0,0 +1,275 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/trees/layer_tree_host.h"
+
+#include "cc/test/fake_content_layer.h"
+#include "cc/test/fake_content_layer_client.h"
+#include "cc/test/layer_tree_test.h"
+#include "cc/trees/damage_tracker.h"
+#include "cc/trees/layer_tree_impl.h"
+
+namespace cc {
+namespace {
+
+// These tests deal with damage tracking.
+class LayerTreeHostDamageTest : public LayerTreeTest {};
+
+class LayerTreeHostDamageTestNoDamageDoesNotSwap
+ : public LayerTreeHostDamageTest {
+ virtual void BeginTest() OVERRIDE {
+ expect_swap_and_succeed_ = 0;
+ did_swaps_ = 0;
+ did_swap_and_succeed_ = 0;
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void SetupTree() OVERRIDE {
+ scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
+ root->SetBounds(gfx::Size(10, 10));
+
+ // Most of the layer isn't visible.
+ content_ = FakeContentLayer::Create(&client_);
+ content_->SetBounds(gfx::Size(100, 100));
+ root->AddChild(content_);
+
+ layer_tree_host()->SetRootLayer(root);
+ LayerTreeHostDamageTest::SetupTree();
+ }
+
+ virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ bool result) OVERRIDE {
+ EXPECT_TRUE(result);
+
+ int source_frame = host_impl->active_tree()->source_frame_number();
+ switch (source_frame) {
+ case 0:
+ // The first frame has damage, so we should draw and swap.
+ ++expect_swap_and_succeed_;
+ break;
+ case 1:
+ // The second frame has no damage, so we should not draw and swap.
+ break;
+ case 2:
+ // The third frame has damage again, so we should draw and swap.
+ ++expect_swap_and_succeed_;
+ break;
+ case 3:
+ // The fourth frame has no visible damage, so we should not draw and
+ // swap.
+ EndTest();
+ break;
+ }
+ return result;
+ }
+
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ ++did_swaps_;
+ if (result)
+ ++did_swap_and_succeed_;
+ EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
+ }
+
+ virtual void DidCommit() OVERRIDE {
+ int next_frame = layer_tree_host()->commit_number();
+ switch (next_frame) {
+ case 1:
+ layer_tree_host()->SetNeedsCommit();
+ break;
+ case 2:
+ // Cause visible damage.
+ content_->SetNeedsDisplayRect(
+ gfx::Rect(layer_tree_host()->layout_viewport_size()));
+ break;
+ case 3:
+ // Cause non-visible damage.
+ content_->SetNeedsDisplayRect(gfx::Rect(90, 90, 10, 10));
+ break;
+ }
+ }
+
+ virtual void AfterTest() OVERRIDE {
+ EXPECT_EQ(4, did_swaps_);
+ EXPECT_EQ(2, expect_swap_and_succeed_);
+ EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
+ }
+
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> content_;
+ int expect_swap_and_succeed_;
+ int did_swaps_;
+ int did_swap_and_succeed_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestNoDamageDoesNotSwap);
+
+class LayerTreeHostDamageTestNoDamageReadbackDoesDraw
+ : public LayerTreeHostDamageTest {
+ virtual void BeginTest() OVERRIDE {
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void SetupTree() OVERRIDE {
+ scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
+ root->SetBounds(gfx::Size(10, 10));
+
+ // Most of the layer isn't visible.
+ content_ = FakeContentLayer::Create(&client_);
+ content_->SetBounds(gfx::Size(100, 100));
+ root->AddChild(content_);
+
+ layer_tree_host()->SetRootLayer(root);
+ LayerTreeHostDamageTest::SetupTree();
+ }
+
+ virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ bool result) OVERRIDE {
+ EXPECT_TRUE(result);
+
+ int source_frame = host_impl->active_tree()->source_frame_number();
+ switch (source_frame) {
+ case 0:
+ // The first frame draws and clears any damage.
+ break;
+ case 1: {
+ // The second frame is a readback, we should have damage in the readback
+ // rect, but not swap.
+ RenderSurfaceImpl* root_surface =
+ host_impl->active_tree()->root_layer()->render_surface();
+ gfx::RectF root_damage =
+ root_surface->damage_tracker()->current_damage_rect();
+ root_damage.Intersect(root_surface->content_rect());
+ EXPECT_TRUE(root_damage.Contains(gfx::Rect(3, 3, 1, 1)));
+ break;
+ }
+ case 2:
+ NOTREACHED();
+ break;
+ }
+ return result;
+ }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ int next_frame = layer_tree_host()->commit_number();
+ switch (next_frame) {
+ case 1: {
+ char pixels[4];
+ layer_tree_host()->CompositeAndReadback(static_cast<void*>(&pixels),
+ gfx::Rect(3, 3, 1, 1));
+ EndTest();
+ break;
+ }
+ }
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> content_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestNoDamageReadbackDoesDraw);
+
+class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
+ virtual void BeginTest() OVERRIDE {
+ PostSetNeedsCommitToMainThread();
+ }
+
+ virtual void SetupTree() OVERRIDE {
+ root_ = FakeContentLayer::Create(&client_);
+ child_ = FakeContentLayer::Create(&client_);
+
+ root_->SetBounds(gfx::Size(500, 500));
+ child_->SetPosition(gfx::Point(100, 100));
+ child_->SetBounds(gfx::Size(30, 30));
+
+ root_->AddChild(child_);
+ layer_tree_host()->SetRootLayer(root_);
+ LayerTreeHostDamageTest::SetupTree();
+ }
+
+ virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ bool result) OVERRIDE {
+ EXPECT_TRUE(result);
+
+ RenderSurfaceImpl* root_surface =
+ host_impl->active_tree()->root_layer()->render_surface();
+ gfx::RectF root_damage =
+ root_surface->damage_tracker()->current_damage_rect();
+ root_damage.Intersect(root_surface->content_rect());
+
+ int source_frame = host_impl->active_tree()->source_frame_number();
+ switch (source_frame) {
+ case 0:
+ // The first frame draws and clears any damage.
+ EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
+ root_damage.ToString());
+ EXPECT_FALSE(frame_data->has_no_damage);
+ break;
+ case 1:
+ // If we get a frame without damage then we don't draw.
+ EXPECT_EQ(gfx::RectF().ToString(), root_damage.ToString());
+ EXPECT_TRUE(frame_data->has_no_damage);
+
+ // Then we set full damage for the next frame.
+ host_impl->SetFullRootLayerDamage();
+ break;
+ case 2:
+ // The whole frame should be damaged as requested.
+ EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
+ root_damage.ToString());
+ EXPECT_FALSE(frame_data->has_no_damage);
+
+ // Just a part of the next frame should be damaged.
+ child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
+ break;
+ case 3:
+ // The update rect in the child should be damaged.
+ EXPECT_EQ(gfx::RectF(100+10, 100+11, 12, 13).ToString(),
+ root_damage.ToString());
+ EXPECT_FALSE(frame_data->has_no_damage);
+
+ // If we damage part of the frame, but also damage the full
+ // frame, then the whole frame should be damaged.
+ child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
+ host_impl->SetFullRootLayerDamage();
+ break;
+ case 4:
+ // The whole frame is damaged.
+ EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
+ root_damage.ToString());
+ EXPECT_FALSE(frame_data->has_no_damage);
+
+ EndTest();
+ break;
+ }
+ return result;
+ }
+
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
+ if (!TestEnded())
+ layer_tree_host()->SetNeedsCommit();
+
+ if (!child_damage_rect_.IsEmpty()) {
+ child_->SetNeedsDisplayRect(child_damage_rect_);
+ child_damage_rect_ = gfx::RectF();
+ }
+ }
+
+ virtual void AfterTest() OVERRIDE {}
+
+ FakeContentLayerClient client_;
+ scoped_refptr<FakeContentLayer> root_;
+ scoped_refptr<FakeContentLayer> child_;
+ gfx::RectF child_damage_rect_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestForcedFullDamage);
+
+} // namespace
+} // namespace cc
diff --git a/cc/trees/layer_tree_host_unittest_delegated.cc b/cc/trees/layer_tree_host_unittest_delegated.cc
index cc81707..380113a 100644
--- a/cc/trees/layer_tree_host_unittest_delegated.cc
+++ b/cc/trees/layer_tree_host_unittest_delegated.cc
@@ -252,7 +252,13 @@ class LayerTreeHostDelegatedTestLayerUsesFrameDamage
if (!first_draw_for_source_frame_)
return result;
- gfx::RectF damage_rect = frame->render_passes.back()->damage_rect;
+ gfx::RectF damage_rect;
+ if (!frame->has_no_damage) {
+ damage_rect = frame->render_passes.back()->damage_rect;
+ } else {
+ // If there is no damage, then we have no render passes to send.
+ EXPECT_TRUE(frame->render_passes.empty());
+ }
switch (host_impl->active_tree()->source_frame_number()) {
case 0:
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 07056c4..31a7054 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -54,7 +54,12 @@ bool SingleThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) {
TRACE_EVENT0("cc", "SingleThreadProxy::CompositeAndReadback");
DCHECK(Proxy::IsMainThread());
- if (!CommitAndComposite(base::TimeTicks::Now()))
+ gfx::Rect device_viewport_damage_rect = rect;
+
+ LayerTreeHostImpl::FrameData frame;
+ if (!CommitAndComposite(base::TimeTicks::Now(),
+ device_viewport_damage_rect,
+ &frame))
return false;
{
@@ -64,7 +69,7 @@ bool SingleThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) {
if (layer_tree_host_impl_->IsContextLost())
return false;
- layer_tree_host_impl_->SwapBuffers();
+ layer_tree_host_impl_->SwapBuffers(frame);
}
DidSwapFrame();
@@ -330,8 +335,13 @@ void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
// Called by the legacy scheduling path (e.g. where render_widget does the
// scheduling)
void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
- if (CommitAndComposite(frame_begin_time)) {
- layer_tree_host_impl_->SwapBuffers();
+ gfx::Rect device_viewport_damage_rect;
+
+ LayerTreeHostImpl::FrameData frame;
+ if (CommitAndComposite(frame_begin_time,
+ device_viewport_damage_rect,
+ &frame)) {
+ layer_tree_host_impl_->SwapBuffers(frame);
DidSwapFrame();
}
}
@@ -360,7 +370,10 @@ void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
void SingleThreadProxy::OnSwapBuffersCompleteOnImplThread() { NOTREACHED(); }
-bool SingleThreadProxy::CommitAndComposite(base::TimeTicks frame_begin_time) {
+bool SingleThreadProxy::CommitAndComposite(
+ base::TimeTicks frame_begin_time,
+ gfx::Rect device_viewport_damage_rect,
+ LayerTreeHostImpl::FrameData* frame) {
DCHECK(Proxy::IsMainThread());
if (!layer_tree_host_->InitializeRendererIfNeeded())
@@ -384,7 +397,10 @@ bool SingleThreadProxy::CommitAndComposite(base::TimeTicks frame_begin_time) {
layer_tree_host_->WillCommit();
DoCommit(queue.Pass());
- bool result = DoComposite(offscreen_context_provider, frame_begin_time);
+ bool result = DoComposite(offscreen_context_provider,
+ frame_begin_time,
+ device_viewport_damage_rect,
+ frame);
layer_tree_host_->DidBeginFrame();
return result;
}
@@ -397,7 +413,9 @@ bool SingleThreadProxy::ShouldComposite() const {
bool SingleThreadProxy::DoComposite(
scoped_refptr<cc::ContextProvider> offscreen_context_provider,
- base::TimeTicks frame_begin_time) {
+ base::TimeTicks frame_begin_time,
+ gfx::Rect device_viewport_damage_rect,
+ LayerTreeHostImpl::FrameData* frame) {
DCHECK(!output_surface_lost_);
{
DebugScopedSetImplThread impl(this);
@@ -418,10 +436,9 @@ bool SingleThreadProxy::DoComposite(
layer_tree_host_impl_->Animate(base::TimeTicks::Now(), base::Time::Now());
layer_tree_host_impl_->UpdateBackgroundAnimateTicking(false);
- LayerTreeHostImpl::FrameData frame;
- layer_tree_host_impl_->PrepareToDraw(&frame);
- layer_tree_host_impl_->DrawLayers(&frame, frame_begin_time);
- layer_tree_host_impl_->DidDrawAllLayers(frame);
+ layer_tree_host_impl_->PrepareToDraw(frame, device_viewport_damage_rect);
+ layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
+ layer_tree_host_impl_->DidDrawAllLayers(*frame);
output_surface_lost_ = layer_tree_host_impl_->IsContextLost();
bool start_ready_animations = true;
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index 1375620..bfd054d 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -78,11 +78,15 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient {
private:
explicit SingleThreadProxy(LayerTreeHost* layer_tree_host);
- bool CommitAndComposite(base::TimeTicks frame_begin_time);
+ bool CommitAndComposite(base::TimeTicks frame_begin_time,
+ gfx::Rect device_viewport_damage_rect,
+ LayerTreeHostImpl::FrameData* frame);
void DoCommit(scoped_ptr<ResourceUpdateQueue> queue);
bool DoComposite(
scoped_refptr<cc::ContextProvider> offscreen_context_provider,
- base::TimeTicks frame_begin_time);
+ base::TimeTicks frame_begin_time,
+ gfx::Rect device_viewport_damage_rect,
+ LayerTreeHostImpl::FrameData* frame);
void DidSwapFrame();
bool ShouldComposite() const;
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index 2ec6f7d..f824c9b 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -894,6 +894,11 @@ ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) {
// DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
// CanDraw() as well.
+ // If it is a forced draw, make sure we do a draw and swap.
+ gfx::Rect readback_rect;
+ if (readback_request_on_impl_thread_)
+ readback_rect = readback_request_on_impl_thread_->rect;
+
LayerTreeHostImpl::FrameData frame;
bool draw_frame = false;
bool start_ready_animations = true;
@@ -901,7 +906,8 @@ ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) {
if (layer_tree_host_impl_->CanDraw()) {
// Do not start animations if we skip drawing the frame to avoid
// checkerboarding.
- if (layer_tree_host_impl_->PrepareToDraw(&frame) || forced_draw)
+ if (layer_tree_host_impl_->PrepareToDraw(&frame, readback_rect) ||
+ forced_draw)
draw_frame = true;
else
start_ready_animations = false;
@@ -939,7 +945,7 @@ ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) {
readback_request_on_impl_thread_->completion.Signal();
readback_request_on_impl_thread_ = NULL;
} else if (draw_frame) {
- result.did_swap = layer_tree_host_impl_->SwapBuffers();
+ result.did_swap = layer_tree_host_impl_->SwapBuffers(frame);
if (frame.contains_incomplete_tile)
DidSwapUseIncompleteTileOnImplThread();