Changes to RenderFrameProxy:
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest_damage.cc
blobeab8ed6b60ebe110bfc884ba6af5f65e0a2312e7
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"
7 #include "base/bind.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"
20 namespace cc {
21 namespace {
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 {
30 // Viewport is 10x10.
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 {
39 draw_count_ = 0;
40 PostSetNeedsCommitToMainThread();
43 virtual void DidCommitAndDrawFrame() OVERRIDE {
44 switch (layer_tree_host()->source_frame_number()) {
45 case 1:
46 layer_tree_host()->SetNeedsRedraw();
47 break;
51 virtual DrawResult PrepareToDrawOnThread(
52 LayerTreeHostImpl* impl,
53 LayerTreeHostImpl::FrameData* frame_data,
54 DrawResult draw_result) OVERRIDE {
55 EXPECT_EQ(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_) {
63 case 0:
64 // The first frame has full damage.
65 EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
66 break;
67 case 1:
68 // The second frame has full damage.
69 EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
70 EndTest();
71 break;
72 case 2:
73 NOTREACHED();
76 ++draw_count_;
77 return draw_result;
80 virtual void AfterTest() OVERRIDE {}
82 int draw_count_;
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 {
92 // Viewport is 10x10.
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 {
101 draw_count_ = 0;
102 PostSetNeedsCommitToMainThread();
105 virtual void DidCommitAndDrawFrame() OVERRIDE {
106 switch (layer_tree_host()->source_frame_number()) {
107 case 1:
108 layer_tree_host()->SetViewportSize(gfx::Size(15, 15));
109 break;
113 virtual DrawResult PrepareToDrawOnThread(
114 LayerTreeHostImpl* impl,
115 LayerTreeHostImpl::FrameData* frame_data,
116 DrawResult draw_result) OVERRIDE {
117 EXPECT_EQ(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_) {
125 case 0:
126 // The first frame has full damage.
127 EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
128 break;
129 case 1:
130 // The second frame has full damage.
131 EXPECT_EQ(gfx::RectF(15.f, 15.f).ToString(), root_damage.ToString());
132 EndTest();
133 break;
134 case 2:
135 NOTREACHED();
138 ++draw_count_;
139 return draw_result;
142 virtual void AfterTest() OVERRIDE {}
144 int draw_count_;
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;
154 did_swaps_ = 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 DrawResult PrepareToDrawOnThread(
173 LayerTreeHostImpl* host_impl,
174 LayerTreeHostImpl::FrameData* frame_data,
175 DrawResult draw_result) OVERRIDE {
176 EXPECT_EQ(DRAW_SUCCESS, draw_result);
178 int source_frame = host_impl->active_tree()->source_frame_number();
179 switch (source_frame) {
180 case 0:
181 // The first frame has damage, so we should draw and swap.
182 ++expect_swap_and_succeed_;
183 break;
184 case 1:
185 // The second frame has no damage, so we should not draw and swap.
186 break;
187 case 2:
188 // The third frame has damage again, so we should draw and swap.
189 ++expect_swap_and_succeed_;
190 break;
191 case 3:
192 // The fourth frame has no visible damage, so we should not draw and
193 // swap.
194 EndTest();
195 break;
197 return draw_result;
200 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
201 bool result) OVERRIDE {
202 ++did_swaps_;
203 if (result)
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) {
211 case 1:
212 layer_tree_host()->SetNeedsCommit();
213 break;
214 case 2:
215 // Cause visible damage.
216 content_->SetNeedsDisplayRect(
217 gfx::Rect(layer_tree_host()->device_viewport_size()));
218 break;
219 case 3:
220 // Cause non-visible damage.
221 content_->SetNeedsDisplayRect(gfx::Rect(1990, 1990, 10, 10));
222 layer_tree_host()->SetNeedsCommit();
223 break;
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_;
236 int did_swaps_;
237 int did_swap_and_succeed_;
240 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
241 LayerTreeHostDamageTestNoDamageDoesNotSwap);
243 class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
244 virtual void BeginTest() OVERRIDE {
245 PostSetNeedsCommitToMainThread();
248 virtual void SetupTree() OVERRIDE {
249 root_ = FakeContentLayer::Create(&client_);
250 child_ = FakeContentLayer::Create(&client_);
252 root_->SetBounds(gfx::Size(500, 500));
253 child_->SetPosition(gfx::Point(100, 100));
254 child_->SetBounds(gfx::Size(30, 30));
256 root_->AddChild(child_);
257 layer_tree_host()->SetRootLayer(root_);
258 LayerTreeHostDamageTest::SetupTree();
261 virtual DrawResult PrepareToDrawOnThread(
262 LayerTreeHostImpl* host_impl,
263 LayerTreeHostImpl::FrameData* frame_data,
264 DrawResult draw_result) OVERRIDE {
265 EXPECT_EQ(DRAW_SUCCESS, draw_result);
267 RenderSurfaceImpl* root_surface =
268 host_impl->active_tree()->root_layer()->render_surface();
269 gfx::RectF root_damage =
270 root_surface->damage_tracker()->current_damage_rect();
271 root_damage.Intersect(root_surface->content_rect());
273 int source_frame = host_impl->active_tree()->source_frame_number();
274 switch (source_frame) {
275 case 0:
276 // The first frame draws and clears any damage.
277 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
278 root_damage.ToString());
279 EXPECT_FALSE(frame_data->has_no_damage);
280 break;
281 case 1:
282 // If we get a frame without damage then we don't draw.
283 EXPECT_EQ(gfx::RectF().ToString(), root_damage.ToString());
284 EXPECT_TRUE(frame_data->has_no_damage);
286 // Then we set full damage for the next frame.
287 host_impl->SetFullRootLayerDamage();
288 break;
289 case 2:
290 // The whole frame should be damaged as requested.
291 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
292 root_damage.ToString());
293 EXPECT_FALSE(frame_data->has_no_damage);
295 // Just a part of the next frame should be damaged.
296 child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
297 break;
298 case 3:
299 // The update rect in the child should be damaged and the damaged area
300 // should match the invalidation.
301 EXPECT_EQ(gfx::RectF(100+10, 100+11, 12, 13).ToString(),
302 root_damage.ToString());
304 // TODO(danakj): Remove this when impl side painting is always on.
305 if (delegating_renderer() ||
306 host_impl->settings().impl_side_painting) {
307 // When using a delegating renderer, or using impl side painting, the
308 // entire child is considered damaged as we need to replace its
309 // resources with newly created ones. The damaged area is kept as it
310 // is, but entire child is painted.
312 // The paint rect should match the layer bounds.
313 gfx::RectF paint_rect = child_->LastPaintRect();
314 paint_rect.set_origin(child_->position());
315 EXPECT_EQ(gfx::RectF(100, 100, 30, 30).ToString(),
316 paint_rect.ToString());
318 EXPECT_FALSE(frame_data->has_no_damage);
320 // If we damage part of the frame, but also damage the full
321 // frame, then the whole frame should be damaged.
322 child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
323 host_impl->SetFullRootLayerDamage();
324 break;
325 case 4:
326 // The whole frame is damaged.
327 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
328 root_damage.ToString());
329 EXPECT_FALSE(frame_data->has_no_damage);
331 EndTest();
332 break;
334 return draw_result;
337 virtual void DidCommitAndDrawFrame() OVERRIDE {
338 if (!TestEnded())
339 layer_tree_host()->SetNeedsCommit();
341 if (!child_damage_rect_.IsEmpty()) {
342 child_->SetNeedsDisplayRect(child_damage_rect_);
343 child_damage_rect_ = gfx::RectF();
347 virtual void AfterTest() OVERRIDE {}
349 FakeContentLayerClient client_;
350 scoped_refptr<FakeContentLayer> root_;
351 scoped_refptr<FakeContentLayer> child_;
352 gfx::RectF child_damage_rect_;
355 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostDamageTestForcedFullDamage);
357 class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest {
358 virtual void SetupTree() OVERRIDE {
359 scoped_refptr<Layer> root_layer = Layer::Create();
360 root_layer->SetBounds(gfx::Size(400, 400));
361 root_layer->SetMasksToBounds(true);
362 layer_tree_host()->SetRootLayer(root_layer);
364 scoped_refptr<Layer> scroll_clip_layer = Layer::Create();
365 scoped_refptr<Layer> content_layer = FakeContentLayer::Create(&client_);
366 content_layer->SetScrollClipLayerId(scroll_clip_layer->id());
367 content_layer->SetScrollOffset(gfx::Vector2d(10, 20));
368 content_layer->SetBounds(gfx::Size(100, 200));
369 scroll_clip_layer->SetBounds(
370 gfx::Size(content_layer->bounds().width() - 30,
371 content_layer->bounds().height() - 50));
372 scroll_clip_layer->AddChild(content_layer);
373 root_layer->AddChild(scroll_clip_layer);
375 scoped_refptr<Layer> scrollbar_layer =
376 FakePaintedScrollbarLayer::Create(false, true, content_layer->id());
377 scrollbar_layer->SetPosition(gfx::Point(300, 300));
378 scrollbar_layer->SetBounds(gfx::Size(10, 100));
379 scrollbar_layer->ToScrollbarLayer()->SetClipLayer(scroll_clip_layer->id());
380 scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(content_layer->id());
381 root_layer->AddChild(scrollbar_layer);
383 gfx::RectF content_rect(content_layer->position(),
384 content_layer->bounds());
385 gfx::RectF scrollbar_rect(scrollbar_layer->position(),
386 scrollbar_layer->bounds());
387 EXPECT_FALSE(content_rect.Intersects(scrollbar_rect));
389 LayerTreeHostDamageTest::SetupTree();
392 private:
393 FakeContentLayerClient client_;
396 class LayerTreeHostDamageTestScrollbarDoesDamage
397 : public LayerTreeHostScrollbarDamageTest {
398 virtual void BeginTest() OVERRIDE {
399 did_swaps_ = 0;
400 PostSetNeedsCommitToMainThread();
403 virtual DrawResult PrepareToDrawOnThread(
404 LayerTreeHostImpl* host_impl,
405 LayerTreeHostImpl::FrameData* frame_data,
406 DrawResult draw_result) OVERRIDE {
407 EXPECT_EQ(DRAW_SUCCESS, draw_result);
408 RenderSurfaceImpl* root_surface =
409 host_impl->active_tree()->root_layer()->render_surface();
410 gfx::RectF root_damage =
411 root_surface->damage_tracker()->current_damage_rect();
412 root_damage.Intersect(root_surface->content_rect());
413 switch (did_swaps_) {
414 case 0:
415 // The first frame has damage, so we should draw and swap.
416 break;
417 case 1:
418 // The second frame should not damage the scrollbars.
419 EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
420 break;
421 case 2:
422 // The third frame should damage the scrollbars.
423 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
424 break;
425 case 3:
426 // The fourth frame should damage the scrollbars.
427 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
428 EndTest();
429 break;
431 return draw_result;
434 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
435 bool result) OVERRIDE {
436 ++did_swaps_;
437 EXPECT_TRUE(result);
438 LayerImpl* root = host_impl->active_tree()->root_layer();
439 LayerImpl* scroll_clip_layer = root->children()[0];
440 LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
441 switch (did_swaps_) {
442 case 1:
443 // Test that modifying the position of the content layer (not
444 // scrolling) won't damage the scrollbar.
445 scroll_layer->SetPosition(gfx::Point(1, 1));
446 scroll_layer->SetScrollOffset(scroll_layer->scroll_offset());
447 host_impl->SetNeedsRedraw();
448 break;
449 case 2:
450 scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
451 host_impl->SetNeedsRedraw();
452 break;
453 case 3:
454 scroll_layer->SetBounds(gfx::Size(root->bounds().width() + 60,
455 root->bounds().height() + 100));
456 host_impl->SetNeedsRedraw();
457 break;
461 virtual void AfterTest() OVERRIDE {
462 EXPECT_EQ(4, did_swaps_);
465 int did_swaps_;
468 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarDoesDamage);
470 class LayerTreeHostDamageTestScrollbarCommitDoesNoDamage
471 : public LayerTreeHostScrollbarDamageTest {
472 virtual void BeginTest() OVERRIDE {
473 did_swaps_ = 0;
474 PostSetNeedsCommitToMainThread();
477 virtual DrawResult PrepareToDrawOnThread(
478 LayerTreeHostImpl* host_impl,
479 LayerTreeHostImpl::FrameData* frame_data,
480 DrawResult draw_result) OVERRIDE {
481 EXPECT_EQ(DRAW_SUCCESS, draw_result);
482 RenderSurfaceImpl* root_surface =
483 host_impl->active_tree()->root_layer()->render_surface();
484 gfx::RectF root_damage =
485 root_surface->damage_tracker()->current_damage_rect();
486 root_damage.Intersect(root_surface->content_rect());
487 int frame = host_impl->active_tree()->source_frame_number();
488 switch (did_swaps_) {
489 case 0:
490 // The first frame has damage, so we should draw and swap.
491 EXPECT_EQ(0, frame);
492 break;
493 case 1:
494 // The second frame has scrolled, so the scrollbar should be damaged.
495 EXPECT_EQ(0, frame);
496 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
497 break;
498 case 2:
499 // The third frame (after the commit) has no changes, so it shouldn't.
500 EXPECT_EQ(1, frame);
501 EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
502 break;
503 default:
504 NOTREACHED();
505 break;
507 return draw_result;
510 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
511 bool result) OVERRIDE {
512 ++did_swaps_;
513 EXPECT_TRUE(result);
514 LayerImpl* root = host_impl->active_tree()->root_layer();
515 LayerImpl* scroll_clip_layer = root->children()[0];
516 LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
517 switch (did_swaps_) {
518 case 1:
519 // Scroll on the thread. This should damage the scrollbar for the
520 // next draw on the thread.
521 scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
522 host_impl->SetNeedsRedraw();
523 break;
524 case 2:
525 // Forcibly send the scroll to the main thread.
526 PostSetNeedsCommitToMainThread();
527 break;
528 case 3:
529 // First swap after second commit.
530 EndTest();
531 break;
532 default:
533 NOTREACHED();
534 break;
538 virtual void AfterTest() OVERRIDE {
539 EXPECT_EQ(3, did_swaps_);
542 int did_swaps_;
545 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarCommitDoesNoDamage);
547 class LayerTreeHostDamageTestVisibleTilesStillTriggerDraws
548 : public LayerTreeHostDamageTest {
550 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
551 settings->impl_side_painting = true;
554 virtual void BeginTest() OVERRIDE {
555 PostSetNeedsCommitToMainThread();
558 virtual void SetupTree() OVERRIDE {
559 scoped_refptr<FakePictureLayer> root = FakePictureLayer::Create(&client_);
560 root->SetBounds(gfx::Size(500, 500));
561 layer_tree_host()->SetRootLayer(root);
562 LayerTreeHostDamageTest::SetupTree();
564 swap_count_ = 0;
565 prepare_to_draw_count_ = 0;
566 update_visible_tile_count_ = 0;
569 virtual DrawResult PrepareToDrawOnThread(
570 LayerTreeHostImpl* host_impl,
571 LayerTreeHostImpl::FrameData* frame_data,
572 DrawResult draw_result) OVERRIDE {
573 EXPECT_EQ(DRAW_SUCCESS, draw_result);
574 prepare_to_draw_count_++;
575 switch (prepare_to_draw_count_) {
576 case 1:
577 // Detect that we have an incomplete tile, during the first frame.
578 // The first frame should have damage.
579 frame_data->contains_incomplete_tile = true;
580 DCHECK(!frame_data->has_no_damage);
581 break;
582 case 2:
583 // Make a no-damage frame. We early out and can't detect
584 // incomplete tiles, even if they still exist.
585 frame_data->contains_incomplete_tile = false;
586 frame_data->has_no_damage = true;
587 break;
588 case 3:
589 // Trigger the last swap for the completed tile.
590 frame_data->contains_incomplete_tile = false;
591 frame_data->has_no_damage = false;
592 EndTest();
593 break;
594 default:
595 NOTREACHED();
596 break;
599 return draw_result;
602 virtual void UpdateVisibleTilesOnThread(
603 LayerTreeHostImpl* host_impl) OVERRIDE {
604 // Simulate creating some visible tiles (that trigger prepare-to-draws).
605 // The first we make into a no-damage-frame during prepare-to-draw (see
606 // above). This is to ensure we still get UpdateVisibleTiles calls after
607 // a no-damage or aborted frame.
608 update_visible_tile_count_++;
609 switch (update_visible_tile_count_) {
610 case 3:
611 case 6:
612 host_impl->DidInitializeVisibleTileForTesting();
613 break;
614 case 7:
615 NOTREACHED();
616 break;
620 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
621 bool didSwap) OVERRIDE {
622 if (!didSwap)
623 return;
624 ++swap_count_;
627 virtual void AfterTest() OVERRIDE {
628 // We should keep getting update-visible-tiles calls
629 // until we report there are no more incomplete-tiles.
630 EXPECT_EQ(update_visible_tile_count_, 6);
631 // First frame, plus two triggered by DidInitializeVisibleTile()
632 EXPECT_EQ(prepare_to_draw_count_, 3);
633 // First swap, plus final swap (contained damage).
634 EXPECT_EQ(swap_count_, 2);
637 FakeContentLayerClient client_;
638 int swap_count_;
639 int prepare_to_draw_count_;
640 int update_visible_tile_count_;
643 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestVisibleTilesStillTriggerDraws);
645 } // namespace
646 } // namespace cc