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
);