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 bool PrepareToDrawOnThread(LayerTreeHostImpl* impl,
52 LayerTreeHostImpl::FrameData* frame_data,
53 bool result) OVERRIDE {
56 RenderSurfaceImpl* root_surface =
57 impl->active_tree()->root_layer()->render_surface();
58 gfx::RectF root_damage =
59 root_surface->damage_tracker()->current_damage_rect();
61 switch (draw_count_) {
63 // The first frame has full damage.
64 EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
67 // The second frame has full damage.
68 EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
79 virtual void AfterTest() OVERRIDE {}
82 FakeContentLayerClient client_;
85 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetNeedsRedraw);
87 // LayerTreeHost::SetViewportSize should damage the whole viewport.
88 class LayerTreeHostDamageTestSetViewportSize
89 : public LayerTreeHostDamageTest {
90 virtual void SetupTree() OVERRIDE {
92 scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
93 root->SetBounds(gfx::Size(10, 10));
95 layer_tree_host()->SetRootLayer(root);
96 LayerTreeHostDamageTest::SetupTree();
99 virtual void BeginTest() OVERRIDE {
101 PostSetNeedsCommitToMainThread();
104 virtual void DidCommitAndDrawFrame() OVERRIDE {
105 switch (layer_tree_host()->source_frame_number()) {
107 layer_tree_host()->SetViewportSize(gfx::Size(15, 15));
112 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* impl,
113 LayerTreeHostImpl::FrameData* frame_data,
114 bool result) OVERRIDE {
117 RenderSurfaceImpl* root_surface =
118 impl->active_tree()->root_layer()->render_surface();
119 gfx::RectF root_damage =
120 root_surface->damage_tracker()->current_damage_rect();
122 switch (draw_count_) {
124 // The first frame has full damage.
125 EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
128 // The second frame has full damage.
129 EXPECT_EQ(gfx::RectF(15.f, 15.f).ToString(), root_damage.ToString());
140 virtual void AfterTest() OVERRIDE {}
143 FakeContentLayerClient client_;
146 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetViewportSize);
148 class LayerTreeHostDamageTestNoDamageDoesNotSwap
149 : public LayerTreeHostDamageTest {
150 virtual void BeginTest() OVERRIDE {
151 expect_swap_and_succeed_ = 0;
153 did_swap_and_succeed_ = 0;
154 PostSetNeedsCommitToMainThread();
157 virtual void SetupTree() OVERRIDE {
158 scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
159 root->SetBounds(gfx::Size(10, 10));
161 // Most of the layer isn't visible.
162 content_ = FakeContentLayer::Create(&client_);
163 content_->SetBounds(gfx::Size(2000, 100));
164 root->AddChild(content_);
166 layer_tree_host()->SetRootLayer(root);
167 LayerTreeHostDamageTest::SetupTree();
170 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
171 LayerTreeHostImpl::FrameData* frame_data,
172 bool result) OVERRIDE {
175 int source_frame = host_impl->active_tree()->source_frame_number();
176 switch (source_frame) {
178 // The first frame has damage, so we should draw and swap.
179 ++expect_swap_and_succeed_;
182 // The second frame has no damage, so we should not draw and swap.
185 // The third frame has damage again, so we should draw and swap.
186 ++expect_swap_and_succeed_;
189 // The fourth frame has no visible damage, so we should not draw and
197 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
198 bool result) OVERRIDE {
201 ++did_swap_and_succeed_;
202 EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
205 virtual void DidCommit() OVERRIDE {
206 int next_frame = layer_tree_host()->source_frame_number();
207 switch (next_frame) {
209 layer_tree_host()->SetNeedsCommit();
212 // Cause visible damage.
213 content_->SetNeedsDisplayRect(
214 gfx::Rect(layer_tree_host()->device_viewport_size()));
217 // Cause non-visible damage.
218 content_->SetNeedsDisplayRect(gfx::Rect(1990, 1990, 10, 10));
219 layer_tree_host()->SetNeedsCommit();
224 virtual void AfterTest() OVERRIDE {
225 EXPECT_EQ(4, did_swaps_);
226 EXPECT_EQ(2, expect_swap_and_succeed_);
227 EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
230 FakeContentLayerClient client_;
231 scoped_refptr<FakeContentLayer> content_;
232 int expect_swap_and_succeed_;
234 int did_swap_and_succeed_;
237 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
238 LayerTreeHostDamageTestNoDamageDoesNotSwap);
240 class LayerTreeHostDamageTestNoDamageReadbackDoesDraw
241 : public LayerTreeHostDamageTest {
242 virtual void BeginTest() OVERRIDE {
243 PostSetNeedsCommitToMainThread();
246 virtual void SetupTree() OVERRIDE {
247 scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
248 root->SetBounds(gfx::Size(10, 10));
250 // Most of the layer isn't visible.
251 content_ = FakeContentLayer::Create(&client_);
252 content_->SetBounds(gfx::Size(100, 100));
253 root->AddChild(content_);
255 layer_tree_host()->SetRootLayer(root);
256 LayerTreeHostDamageTest::SetupTree();
259 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
260 LayerTreeHostImpl::FrameData* frame_data,
261 bool result) OVERRIDE {
264 int source_frame = host_impl->active_tree()->source_frame_number();
265 switch (source_frame) {
267 // The first frame draws and clears any damage.
270 // The second frame is a readback, we should have damage in the readback
271 // rect, but not swap.
272 RenderSurfaceImpl* root_surface =
273 host_impl->active_tree()->root_layer()->render_surface();
274 gfx::RectF root_damage =
275 root_surface->damage_tracker()->current_damage_rect();
276 root_damage.Intersect(root_surface->content_rect());
277 EXPECT_TRUE(root_damage.Contains(gfx::Rect(3, 3, 1, 1)));
281 // CompositeAndReadback causes a follow-up commit.
290 virtual void DidCommitAndDrawFrame() OVERRIDE {
291 int next_frame = layer_tree_host()->source_frame_number();
292 switch (next_frame) {
295 layer_tree_host()->CompositeAndReadback(static_cast<void*>(&pixels),
296 gfx::Rect(3, 3, 1, 1));
303 virtual void AfterTest() OVERRIDE {}
305 FakeContentLayerClient client_;
306 scoped_refptr<FakeContentLayer> content_;
309 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestNoDamageReadbackDoesDraw);
311 class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
312 virtual void BeginTest() OVERRIDE {
313 PostSetNeedsCommitToMainThread();
316 virtual void SetupTree() OVERRIDE {
317 root_ = FakeContentLayer::Create(&client_);
318 child_ = FakeContentLayer::Create(&client_);
320 root_->SetBounds(gfx::Size(500, 500));
321 child_->SetPosition(gfx::Point(100, 100));
322 child_->SetBounds(gfx::Size(30, 30));
324 root_->AddChild(child_);
325 layer_tree_host()->SetRootLayer(root_);
326 LayerTreeHostDamageTest::SetupTree();
329 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
330 LayerTreeHostImpl::FrameData* frame_data,
331 bool result) OVERRIDE {
334 RenderSurfaceImpl* root_surface =
335 host_impl->active_tree()->root_layer()->render_surface();
336 gfx::RectF root_damage =
337 root_surface->damage_tracker()->current_damage_rect();
338 root_damage.Intersect(root_surface->content_rect());
340 int source_frame = host_impl->active_tree()->source_frame_number();
341 switch (source_frame) {
343 // The first frame draws and clears any damage.
344 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
345 root_damage.ToString());
346 EXPECT_FALSE(frame_data->has_no_damage);
349 // If we get a frame without damage then we don't draw.
350 EXPECT_EQ(gfx::RectF().ToString(), root_damage.ToString());
351 EXPECT_TRUE(frame_data->has_no_damage);
353 // Then we set full damage for the next frame.
354 host_impl->SetFullRootLayerDamage();
357 // The whole frame should be damaged as requested.
358 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
359 root_damage.ToString());
360 EXPECT_FALSE(frame_data->has_no_damage);
362 // Just a part of the next frame should be damaged.
363 child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
366 // The update rect in the child should be damaged and the damaged area
367 // should match the invalidation.
368 EXPECT_EQ(gfx::RectF(100+10, 100+11, 12, 13).ToString(),
369 root_damage.ToString());
371 // TODO(danakj): Remove this when impl side painting is always on.
372 if (delegating_renderer() ||
373 host_impl->settings().impl_side_painting) {
374 // When using a delegating renderer, or using impl side painting, the
375 // entire child is considered damaged as we need to replace its
376 // resources with newly created ones. The damaged area is kept as it
377 // is, but entire child is painted.
379 // The paint rect should match the layer bounds.
380 gfx::RectF paint_rect = child_->LastPaintRect();
381 paint_rect.set_origin(child_->position());
382 EXPECT_EQ(gfx::RectF(100, 100, 30, 30).ToString(),
383 paint_rect.ToString());
385 EXPECT_FALSE(frame_data->has_no_damage);
387 // If we damage part of the frame, but also damage the full
388 // frame, then the whole frame should be damaged.
389 child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
390 host_impl->SetFullRootLayerDamage();
393 // The whole frame is damaged.
394 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
395 root_damage.ToString());
396 EXPECT_FALSE(frame_data->has_no_damage);
404 virtual void DidCommitAndDrawFrame() OVERRIDE {
406 layer_tree_host()->SetNeedsCommit();
408 if (!child_damage_rect_.IsEmpty()) {
409 child_->SetNeedsDisplayRect(child_damage_rect_);
410 child_damage_rect_ = gfx::RectF();
414 virtual void AfterTest() OVERRIDE {}
416 FakeContentLayerClient client_;
417 scoped_refptr<FakeContentLayer> root_;
418 scoped_refptr<FakeContentLayer> child_;
419 gfx::RectF child_damage_rect_;
422 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostDamageTestForcedFullDamage);
424 class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest {
425 virtual void SetupTree() OVERRIDE {
426 scoped_refptr<Layer> root_layer = Layer::Create();
427 root_layer->SetBounds(gfx::Size(400, 400));
428 root_layer->SetMasksToBounds(true);
429 layer_tree_host()->SetRootLayer(root_layer);
431 scoped_refptr<Layer> content_layer = FakeContentLayer::Create(&client_);
432 content_layer->SetScrollable(true);
433 content_layer->SetScrollOffset(gfx::Vector2d(10, 20));
434 content_layer->SetMaxScrollOffset(gfx::Vector2d(30, 50));
435 content_layer->SetBounds(gfx::Size(100, 200));
436 root_layer->AddChild(content_layer);
438 scoped_refptr<Layer> scrollbar_layer =
439 FakePaintedScrollbarLayer::Create(false, true, content_layer->id());
440 scrollbar_layer->SetPosition(gfx::Point(300, 300));
441 scrollbar_layer->SetBounds(gfx::Size(10, 100));
442 root_layer->AddChild(scrollbar_layer);
444 gfx::RectF content_rect(content_layer->position(),
445 content_layer->bounds());
446 gfx::RectF scrollbar_rect(scrollbar_layer->position(),
447 scrollbar_layer->bounds());
448 EXPECT_FALSE(content_rect.Intersects(scrollbar_rect));
450 LayerTreeHostDamageTest::SetupTree();
454 FakeContentLayerClient client_;
457 class LayerTreeHostDamageTestScrollbarDoesDamage
458 : public LayerTreeHostScrollbarDamageTest {
459 virtual void BeginTest() OVERRIDE {
461 PostSetNeedsCommitToMainThread();
464 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
465 LayerTreeHostImpl::FrameData* frame_data,
466 bool result) OVERRIDE {
468 RenderSurfaceImpl* root_surface =
469 host_impl->active_tree()->root_layer()->render_surface();
470 gfx::RectF root_damage =
471 root_surface->damage_tracker()->current_damage_rect();
472 root_damage.Intersect(root_surface->content_rect());
473 switch (did_swaps_) {
475 // The first frame has damage, so we should draw and swap.
478 // The second frame should not damage the scrollbars.
479 EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
482 // The third frame should damage the scrollbars.
483 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
486 // The fourth frame should damage the scrollbars.
487 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
494 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
495 bool result) OVERRIDE {
498 LayerImpl* root = host_impl->active_tree()->root_layer();
499 LayerImpl* scroll_layer = root->children()[0];
500 switch (did_swaps_) {
502 // Test that modifying the position of the content layer (not
503 // scrolling) won't damage the scrollbar.
504 scroll_layer->SetPosition(gfx::Point(1, 1));
505 scroll_layer->SetScrollOffset(scroll_layer->scroll_offset());
506 host_impl->SetNeedsRedraw();
509 scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
510 host_impl->SetNeedsRedraw();
513 scroll_layer->SetMaxScrollOffset(gfx::Vector2d(60, 100));
514 host_impl->SetNeedsRedraw();
519 virtual void AfterTest() OVERRIDE {
520 EXPECT_EQ(4, did_swaps_);
526 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarDoesDamage);
528 class LayerTreeHostDamageTestScrollbarCommitDoesNoDamage
529 : public LayerTreeHostScrollbarDamageTest {
530 virtual void BeginTest() OVERRIDE {
532 PostSetNeedsCommitToMainThread();
535 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
536 LayerTreeHostImpl::FrameData* frame_data,
537 bool result) OVERRIDE {
539 RenderSurfaceImpl* root_surface =
540 host_impl->active_tree()->root_layer()->render_surface();
541 gfx::RectF root_damage =
542 root_surface->damage_tracker()->current_damage_rect();
543 root_damage.Intersect(root_surface->content_rect());
544 int frame = host_impl->active_tree()->source_frame_number();
545 switch (did_swaps_) {
547 // The first frame has damage, so we should draw and swap.
551 // The second frame has scrolled, so the scrollbar should be damaged.
553 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
556 // The third frame (after the commit) has no changes, so it shouldn't.
558 EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
567 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
568 bool result) OVERRIDE {
571 LayerImpl* root = host_impl->active_tree()->root_layer();
572 LayerImpl* scroll_layer = root->children()[0];
573 switch (did_swaps_) {
575 // Scroll on the thread. This should damage the scrollbar for the
576 // next draw on the thread.
577 scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
578 host_impl->SetNeedsRedraw();
581 // Forcibly send the scroll to the main thread.
582 PostSetNeedsCommitToMainThread();
585 // First swap after second commit.
594 virtual void AfterTest() OVERRIDE {
595 EXPECT_EQ(3, did_swaps_);
601 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarCommitDoesNoDamage);
603 class LayerTreeHostDamageTestVisibleTilesStillTriggerDraws
604 : public LayerTreeHostDamageTest {
606 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
607 settings->impl_side_painting = true;
610 virtual void BeginTest() OVERRIDE {
611 PostSetNeedsCommitToMainThread();
614 virtual void SetupTree() OVERRIDE {
615 scoped_refptr<FakePictureLayer> root = FakePictureLayer::Create(&client_);
616 root->SetBounds(gfx::Size(500, 500));
617 layer_tree_host()->SetRootLayer(root);
618 LayerTreeHostDamageTest::SetupTree();
621 prepare_to_draw_count_ = 0;
622 update_visible_tile_count_ = 0;
625 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
626 LayerTreeHostImpl::FrameData* frame_data,
627 bool result) OVERRIDE {
629 prepare_to_draw_count_++;
630 switch (prepare_to_draw_count_) {
632 // Detect that we have an incomplete tile, during the first frame.
633 // The first frame should have damage.
634 frame_data->contains_incomplete_tile = true;
635 DCHECK(!frame_data->has_no_damage);
638 // Make a no-damage frame. We early out and can't detect
639 // incomplete tiles, even if they still exist.
640 frame_data->contains_incomplete_tile = false;
641 frame_data->has_no_damage = true;
644 // Trigger the last swap for the completed tile.
645 frame_data->contains_incomplete_tile = false;
646 frame_data->has_no_damage = false;
657 virtual void UpdateVisibleTilesOnThread(
658 LayerTreeHostImpl* host_impl) OVERRIDE {
659 // Simulate creating some visible tiles (that trigger prepare-to-draws).
660 // The first we make into a no-damage-frame during prepare-to-draw (see
661 // above). This is to ensure we still get UpdateVisibleTiles calls after
662 // a no-damage or aborted frame.
663 update_visible_tile_count_++;
664 switch (update_visible_tile_count_) {
667 host_impl->DidInitializeVisibleTileForTesting();
675 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
676 bool didSwap) OVERRIDE {
682 virtual void AfterTest() OVERRIDE {
683 // We should keep getting update-visible-tiles calls
684 // until we report there are no more incomplete-tiles.
685 EXPECT_EQ(update_visible_tile_count_, 6);
686 // First frame, plus two triggered by DidInitializeVisibleTile()
687 EXPECT_EQ(prepare_to_draw_count_, 3);
688 // First swap, plus final swap (contained damage).
689 EXPECT_EQ(swap_count_, 2);
692 FakeContentLayerClient client_;
694 int prepare_to_draw_count_;
695 int update_visible_tile_count_;
698 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestVisibleTilesStillTriggerDraws);