1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/layer_tree_host.h"
8 #include "base/callback.h"
9 #include "base/location.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/time/time.h"
12 #include "cc/test/fake_content_layer.h"
13 #include "cc/test/fake_content_layer_client.h"
14 #include "cc/test/fake_painted_scrollbar_layer.h"
15 #include "cc/test/fake_picture_layer.h"
16 #include "cc/test/layer_tree_test.h"
17 #include "cc/trees/damage_tracker.h"
18 #include "cc/trees/layer_tree_impl.h"
23 // These tests deal with damage tracking.
24 class LayerTreeHostDamageTest : public LayerTreeTest {};
26 // LayerTreeHost::SetNeedsRedraw should damage the whole viewport.
27 class LayerTreeHostDamageTestSetNeedsRedraw
28 : public LayerTreeHostDamageTest {
29 virtual void SetupTree() OVERRIDE {
31 scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
32 root->SetBounds(gfx::Size(10, 10));
34 layer_tree_host()->SetRootLayer(root);
35 LayerTreeHostDamageTest::SetupTree();
38 virtual void BeginTest() OVERRIDE {
40 PostSetNeedsCommitToMainThread();
43 virtual void DidCommitAndDrawFrame() OVERRIDE {
44 switch (layer_tree_host()->source_frame_number()) {
46 layer_tree_host()->SetNeedsRedraw();
51 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
52 LayerTreeHostImpl* impl,
53 LayerTreeHostImpl::FrameData* frame_data,
54 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
55 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
57 RenderSurfaceImpl* root_surface =
58 impl->active_tree()->root_layer()->render_surface();
59 gfx::RectF root_damage =
60 root_surface->damage_tracker()->current_damage_rect();
62 switch (draw_count_) {
64 // The first frame has full damage.
65 EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
68 // The second frame has full damage.
69 EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
80 virtual void AfterTest() OVERRIDE {}
83 FakeContentLayerClient client_;
86 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetNeedsRedraw);
88 // LayerTreeHost::SetViewportSize should damage the whole viewport.
89 class LayerTreeHostDamageTestSetViewportSize
90 : public LayerTreeHostDamageTest {
91 virtual void SetupTree() OVERRIDE {
93 scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
94 root->SetBounds(gfx::Size(10, 10));
96 layer_tree_host()->SetRootLayer(root);
97 LayerTreeHostDamageTest::SetupTree();
100 virtual void BeginTest() OVERRIDE {
102 PostSetNeedsCommitToMainThread();
105 virtual void DidCommitAndDrawFrame() OVERRIDE {
106 switch (layer_tree_host()->source_frame_number()) {
108 layer_tree_host()->SetViewportSize(gfx::Size(15, 15));
113 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
114 LayerTreeHostImpl* impl,
115 LayerTreeHostImpl::FrameData* frame_data,
116 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
117 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
119 RenderSurfaceImpl* root_surface =
120 impl->active_tree()->root_layer()->render_surface();
121 gfx::RectF root_damage =
122 root_surface->damage_tracker()->current_damage_rect();
124 switch (draw_count_) {
126 // The first frame has full damage.
127 EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
130 // The second frame has full damage.
131 EXPECT_EQ(gfx::RectF(15.f, 15.f).ToString(), root_damage.ToString());
142 virtual void AfterTest() OVERRIDE {}
145 FakeContentLayerClient client_;
148 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetViewportSize);
150 class LayerTreeHostDamageTestNoDamageDoesNotSwap
151 : public LayerTreeHostDamageTest {
152 virtual void BeginTest() OVERRIDE {
153 expect_swap_and_succeed_ = 0;
155 did_swap_and_succeed_ = 0;
156 PostSetNeedsCommitToMainThread();
159 virtual void SetupTree() OVERRIDE {
160 scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
161 root->SetBounds(gfx::Size(10, 10));
163 // Most of the layer isn't visible.
164 content_ = FakeContentLayer::Create(&client_);
165 content_->SetBounds(gfx::Size(2000, 100));
166 root->AddChild(content_);
168 layer_tree_host()->SetRootLayer(root);
169 LayerTreeHostDamageTest::SetupTree();
172 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
173 LayerTreeHostImpl* host_impl,
174 LayerTreeHostImpl::FrameData* frame_data,
175 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
176 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
178 int source_frame = host_impl->active_tree()->source_frame_number();
179 switch (source_frame) {
181 // The first frame has damage, so we should draw and swap.
182 ++expect_swap_and_succeed_;
185 // The second frame has no damage, so we should not draw and swap.
188 // The third frame has damage again, so we should draw and swap.
189 ++expect_swap_and_succeed_;
192 // The fourth frame has no visible damage, so we should not draw and
200 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
201 bool result) OVERRIDE {
204 ++did_swap_and_succeed_;
205 EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
208 virtual void DidCommit() OVERRIDE {
209 int next_frame = layer_tree_host()->source_frame_number();
210 switch (next_frame) {
212 layer_tree_host()->SetNeedsCommit();
215 // Cause visible damage.
216 content_->SetNeedsDisplayRect(
217 gfx::Rect(layer_tree_host()->device_viewport_size()));
220 // Cause non-visible damage.
221 content_->SetNeedsDisplayRect(gfx::Rect(1990, 1990, 10, 10));
222 layer_tree_host()->SetNeedsCommit();
227 virtual void AfterTest() OVERRIDE {
228 EXPECT_EQ(4, did_swaps_);
229 EXPECT_EQ(2, expect_swap_and_succeed_);
230 EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
233 FakeContentLayerClient client_;
234 scoped_refptr<FakeContentLayer> content_;
235 int expect_swap_and_succeed_;
237 int did_swap_and_succeed_;
240 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
241 LayerTreeHostDamageTestNoDamageDoesNotSwap);
243 class LayerTreeHostDamageTestNoDamageReadbackDoesDraw
244 : public LayerTreeHostDamageTest {
245 virtual void BeginTest() OVERRIDE {
246 PostSetNeedsCommitToMainThread();
249 virtual void SetupTree() OVERRIDE {
250 scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
251 root->SetBounds(gfx::Size(10, 10));
253 // Most of the layer isn't visible.
254 content_ = FakeContentLayer::Create(&client_);
255 content_->SetBounds(gfx::Size(100, 100));
256 root->AddChild(content_);
258 layer_tree_host()->SetRootLayer(root);
259 LayerTreeHostDamageTest::SetupTree();
262 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
263 LayerTreeHostImpl* host_impl,
264 LayerTreeHostImpl::FrameData* frame_data,
265 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
266 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
268 int source_frame = host_impl->active_tree()->source_frame_number();
269 switch (source_frame) {
271 // The first frame draws and clears any damage.
274 // The second frame is a readback, we should have damage in the readback
275 // rect, but not swap.
276 RenderSurfaceImpl* root_surface =
277 host_impl->active_tree()->root_layer()->render_surface();
278 gfx::RectF root_damage =
279 root_surface->damage_tracker()->current_damage_rect();
280 root_damage.Intersect(root_surface->content_rect());
281 EXPECT_TRUE(root_damage.Contains(gfx::Rect(3, 3, 1, 1)));
285 // CompositeAndReadback causes a follow-up commit.
294 virtual void DidCommitAndDrawFrame() OVERRIDE {
295 int next_frame = layer_tree_host()->source_frame_number();
296 switch (next_frame) {
299 layer_tree_host()->CompositeAndReadback(static_cast<void*>(&pixels),
300 gfx::Rect(3, 3, 1, 1));
307 virtual void AfterTest() OVERRIDE {}
309 FakeContentLayerClient client_;
310 scoped_refptr<FakeContentLayer> content_;
313 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestNoDamageReadbackDoesDraw);
315 class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
316 virtual void BeginTest() OVERRIDE {
317 PostSetNeedsCommitToMainThread();
320 virtual void SetupTree() OVERRIDE {
321 root_ = FakeContentLayer::Create(&client_);
322 child_ = FakeContentLayer::Create(&client_);
324 root_->SetBounds(gfx::Size(500, 500));
325 child_->SetPosition(gfx::Point(100, 100));
326 child_->SetBounds(gfx::Size(30, 30));
328 root_->AddChild(child_);
329 layer_tree_host()->SetRootLayer(root_);
330 LayerTreeHostDamageTest::SetupTree();
333 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
334 LayerTreeHostImpl* host_impl,
335 LayerTreeHostImpl::FrameData* frame_data,
336 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
337 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
339 RenderSurfaceImpl* root_surface =
340 host_impl->active_tree()->root_layer()->render_surface();
341 gfx::RectF root_damage =
342 root_surface->damage_tracker()->current_damage_rect();
343 root_damage.Intersect(root_surface->content_rect());
345 int source_frame = host_impl->active_tree()->source_frame_number();
346 switch (source_frame) {
348 // The first frame draws and clears any damage.
349 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
350 root_damage.ToString());
351 EXPECT_FALSE(frame_data->has_no_damage);
354 // If we get a frame without damage then we don't draw.
355 EXPECT_EQ(gfx::RectF().ToString(), root_damage.ToString());
356 EXPECT_TRUE(frame_data->has_no_damage);
358 // Then we set full damage for the next frame.
359 host_impl->SetFullRootLayerDamage();
362 // The whole frame should be damaged as requested.
363 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
364 root_damage.ToString());
365 EXPECT_FALSE(frame_data->has_no_damage);
367 // Just a part of the next frame should be damaged.
368 child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
371 // The update rect in the child should be damaged and the damaged area
372 // should match the invalidation.
373 EXPECT_EQ(gfx::RectF(100+10, 100+11, 12, 13).ToString(),
374 root_damage.ToString());
376 // TODO(danakj): Remove this when impl side painting is always on.
377 if (delegating_renderer() ||
378 host_impl->settings().impl_side_painting) {
379 // When using a delegating renderer, or using impl side painting, the
380 // entire child is considered damaged as we need to replace its
381 // resources with newly created ones. The damaged area is kept as it
382 // is, but entire child is painted.
384 // The paint rect should match the layer bounds.
385 gfx::RectF paint_rect = child_->LastPaintRect();
386 paint_rect.set_origin(child_->position());
387 EXPECT_EQ(gfx::RectF(100, 100, 30, 30).ToString(),
388 paint_rect.ToString());
390 EXPECT_FALSE(frame_data->has_no_damage);
392 // If we damage part of the frame, but also damage the full
393 // frame, then the whole frame should be damaged.
394 child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
395 host_impl->SetFullRootLayerDamage();
398 // The whole frame is damaged.
399 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
400 root_damage.ToString());
401 EXPECT_FALSE(frame_data->has_no_damage);
409 virtual void DidCommitAndDrawFrame() OVERRIDE {
411 layer_tree_host()->SetNeedsCommit();
413 if (!child_damage_rect_.IsEmpty()) {
414 child_->SetNeedsDisplayRect(child_damage_rect_);
415 child_damage_rect_ = gfx::RectF();
419 virtual void AfterTest() OVERRIDE {}
421 FakeContentLayerClient client_;
422 scoped_refptr<FakeContentLayer> root_;
423 scoped_refptr<FakeContentLayer> child_;
424 gfx::RectF child_damage_rect_;
427 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostDamageTestForcedFullDamage);
429 class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest {
430 virtual void SetupTree() OVERRIDE {
431 scoped_refptr<Layer> root_layer = Layer::Create();
432 root_layer->SetBounds(gfx::Size(400, 400));
433 root_layer->SetMasksToBounds(true);
434 layer_tree_host()->SetRootLayer(root_layer);
436 scoped_refptr<Layer> scroll_clip_layer = Layer::Create();
437 scoped_refptr<Layer> content_layer = FakeContentLayer::Create(&client_);
438 content_layer->SetScrollClipLayerId(scroll_clip_layer->id());
439 content_layer->SetScrollOffset(gfx::Vector2d(10, 20));
440 content_layer->SetBounds(gfx::Size(100, 200));
441 scroll_clip_layer->SetBounds(
442 gfx::Size(content_layer->bounds().width() - 30,
443 content_layer->bounds().height() - 50));
444 scroll_clip_layer->AddChild(content_layer);
445 root_layer->AddChild(scroll_clip_layer);
447 scoped_refptr<Layer> scrollbar_layer =
448 FakePaintedScrollbarLayer::Create(false, true, content_layer->id());
449 scrollbar_layer->SetPosition(gfx::Point(300, 300));
450 scrollbar_layer->SetBounds(gfx::Size(10, 100));
451 scrollbar_layer->ToScrollbarLayer()->SetClipLayer(scroll_clip_layer->id());
452 scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(content_layer->id());
453 root_layer->AddChild(scrollbar_layer);
455 gfx::RectF content_rect(content_layer->position(),
456 content_layer->bounds());
457 gfx::RectF scrollbar_rect(scrollbar_layer->position(),
458 scrollbar_layer->bounds());
459 EXPECT_FALSE(content_rect.Intersects(scrollbar_rect));
461 LayerTreeHostDamageTest::SetupTree();
465 FakeContentLayerClient client_;
468 class LayerTreeHostDamageTestScrollbarDoesDamage
469 : public LayerTreeHostScrollbarDamageTest {
470 virtual void BeginTest() OVERRIDE {
472 PostSetNeedsCommitToMainThread();
475 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
476 LayerTreeHostImpl* host_impl,
477 LayerTreeHostImpl::FrameData* frame_data,
478 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
479 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
480 RenderSurfaceImpl* root_surface =
481 host_impl->active_tree()->root_layer()->render_surface();
482 gfx::RectF root_damage =
483 root_surface->damage_tracker()->current_damage_rect();
484 root_damage.Intersect(root_surface->content_rect());
485 switch (did_swaps_) {
487 // The first frame has damage, so we should draw and swap.
490 // The second frame should not damage the scrollbars.
491 EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
494 // The third frame should damage the scrollbars.
495 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
498 // The fourth frame should damage the scrollbars.
499 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
506 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
507 bool result) OVERRIDE {
510 LayerImpl* root = host_impl->active_tree()->root_layer();
511 LayerImpl* scroll_clip_layer = root->children()[0];
512 LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
513 switch (did_swaps_) {
515 // Test that modifying the position of the content layer (not
516 // scrolling) won't damage the scrollbar.
517 scroll_layer->SetPosition(gfx::Point(1, 1));
518 scroll_layer->SetScrollOffset(scroll_layer->scroll_offset());
519 host_impl->SetNeedsRedraw();
522 scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
523 host_impl->SetNeedsRedraw();
526 scroll_layer->SetBounds(gfx::Size(root->bounds().width() + 60,
527 root->bounds().height() + 100));
528 host_impl->SetNeedsRedraw();
533 virtual void AfterTest() OVERRIDE {
534 EXPECT_EQ(4, did_swaps_);
540 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarDoesDamage);
542 class LayerTreeHostDamageTestScrollbarCommitDoesNoDamage
543 : public LayerTreeHostScrollbarDamageTest {
544 virtual void BeginTest() OVERRIDE {
546 PostSetNeedsCommitToMainThread();
549 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
550 LayerTreeHostImpl* host_impl,
551 LayerTreeHostImpl::FrameData* frame_data,
552 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
553 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
554 RenderSurfaceImpl* root_surface =
555 host_impl->active_tree()->root_layer()->render_surface();
556 gfx::RectF root_damage =
557 root_surface->damage_tracker()->current_damage_rect();
558 root_damage.Intersect(root_surface->content_rect());
559 int frame = host_impl->active_tree()->source_frame_number();
560 switch (did_swaps_) {
562 // The first frame has damage, so we should draw and swap.
566 // The second frame has scrolled, so the scrollbar should be damaged.
568 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
571 // The third frame (after the commit) has no changes, so it shouldn't.
573 EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
582 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
583 bool result) OVERRIDE {
586 LayerImpl* root = host_impl->active_tree()->root_layer();
587 LayerImpl* scroll_clip_layer = root->children()[0];
588 LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
589 switch (did_swaps_) {
591 // Scroll on the thread. This should damage the scrollbar for the
592 // next draw on the thread.
593 scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
594 host_impl->SetNeedsRedraw();
597 // Forcibly send the scroll to the main thread.
598 PostSetNeedsCommitToMainThread();
601 // First swap after second commit.
610 virtual void AfterTest() OVERRIDE {
611 EXPECT_EQ(3, did_swaps_);
617 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarCommitDoesNoDamage);
619 class LayerTreeHostDamageTestVisibleTilesStillTriggerDraws
620 : public LayerTreeHostDamageTest {
622 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
623 settings->impl_side_painting = true;
626 virtual void BeginTest() OVERRIDE {
627 PostSetNeedsCommitToMainThread();
630 virtual void SetupTree() OVERRIDE {
631 scoped_refptr<FakePictureLayer> root = FakePictureLayer::Create(&client_);
632 root->SetBounds(gfx::Size(500, 500));
633 layer_tree_host()->SetRootLayer(root);
634 LayerTreeHostDamageTest::SetupTree();
637 prepare_to_draw_count_ = 0;
638 update_visible_tile_count_ = 0;
641 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
642 LayerTreeHostImpl* host_impl,
643 LayerTreeHostImpl::FrameData* frame_data,
644 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
645 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
646 prepare_to_draw_count_++;
647 switch (prepare_to_draw_count_) {
649 // Detect that we have an incomplete tile, during the first frame.
650 // The first frame should have damage.
651 frame_data->contains_incomplete_tile = true;
652 DCHECK(!frame_data->has_no_damage);
655 // Make a no-damage frame. We early out and can't detect
656 // incomplete tiles, even if they still exist.
657 frame_data->contains_incomplete_tile = false;
658 frame_data->has_no_damage = true;
661 // Trigger the last swap for the completed tile.
662 frame_data->contains_incomplete_tile = false;
663 frame_data->has_no_damage = false;
674 virtual void UpdateVisibleTilesOnThread(
675 LayerTreeHostImpl* host_impl) OVERRIDE {
676 // Simulate creating some visible tiles (that trigger prepare-to-draws).
677 // The first we make into a no-damage-frame during prepare-to-draw (see
678 // above). This is to ensure we still get UpdateVisibleTiles calls after
679 // a no-damage or aborted frame.
680 update_visible_tile_count_++;
681 switch (update_visible_tile_count_) {
684 host_impl->DidInitializeVisibleTileForTesting();
692 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
693 bool didSwap) OVERRIDE {
699 virtual void AfterTest() OVERRIDE {
700 // We should keep getting update-visible-tiles calls
701 // until we report there are no more incomplete-tiles.
702 EXPECT_EQ(update_visible_tile_count_, 6);
703 // First frame, plus two triggered by DidInitializeVisibleTile()
704 EXPECT_EQ(prepare_to_draw_count_, 3);
705 // First swap, plus final swap (contained damage).
706 EXPECT_EQ(swap_count_, 2);
709 FakeContentLayerClient client_;
711 int prepare_to_draw_count_;
712 int update_visible_tile_count_;
715 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestVisibleTilesStillTriggerDraws);