diff options
-rw-r--r-- | cc/cc_tests.gyp | 1 | ||||
-rw-r--r-- | cc/layers/delegated_renderer_layer_impl_unittest.cc | 46 | ||||
-rw-r--r-- | cc/output/delegating_renderer_unittest.cc | 5 | ||||
-rw-r--r-- | cc/test/fake_layer_tree_host_impl.h | 2 | ||||
-rw-r--r-- | cc/test/layer_tree_test.cc | 17 | ||||
-rw-r--r-- | cc/test/layer_tree_test.h | 2 | ||||
-rw-r--r-- | cc/trees/damage_tracker.cc | 7 | ||||
-rw-r--r-- | cc/trees/damage_tracker.h | 3 | ||||
-rw-r--r-- | cc/trees/damage_tracker_unittest.cc | 29 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.cc | 51 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.h | 8 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl_unittest.cc | 264 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_perftest.cc | 14 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest.cc | 54 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest_context.cc | 13 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest_damage.cc | 275 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest_delegated.cc | 8 | ||||
-rw-r--r-- | cc/trees/single_thread_proxy.cc | 39 | ||||
-rw-r--r-- | cc/trees/single_thread_proxy.h | 8 | ||||
-rw-r--r-- | cc/trees/thread_proxy.cc | 10 |
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(); |