Include all dupe types (event when value is zero) in scan stats.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest_damage.cc
blobdb00fb511cc32e42a96b366118b5ac4a68246ea4
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 void SetupTree() override {
30 // Viewport is 10x10.
31 scoped_refptr<FakeContentLayer> root =
32 FakeContentLayer::Create(layer_settings(), &client_);
33 root->SetBounds(gfx::Size(10, 10));
35 layer_tree_host()->SetRootLayer(root);
36 LayerTreeHostDamageTest::SetupTree();
39 void BeginTest() override {
40 draw_count_ = 0;
41 PostSetNeedsCommitToMainThread();
44 void DidCommitAndDrawFrame() override {
45 switch (layer_tree_host()->source_frame_number()) {
46 case 1:
47 layer_tree_host()->SetNeedsRedraw();
48 break;
52 DrawResult PrepareToDrawOnThread(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 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 void SetupTree() override {
92 // Viewport is 10x10.
93 scoped_refptr<FakeContentLayer> root =
94 FakeContentLayer::Create(layer_settings(), &client_);
95 root->SetBounds(gfx::Size(10, 10));
97 layer_tree_host()->SetRootLayer(root);
98 LayerTreeHostDamageTest::SetupTree();
101 void BeginTest() override {
102 draw_count_ = 0;
103 PostSetNeedsCommitToMainThread();
106 void DidCommitAndDrawFrame() override {
107 switch (layer_tree_host()->source_frame_number()) {
108 case 1:
109 layer_tree_host()->SetViewportSize(gfx::Size(15, 15));
110 break;
114 DrawResult PrepareToDrawOnThread(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 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 void BeginTest() override {
153 expect_swap_and_succeed_ = 0;
154 did_swaps_ = 0;
155 did_swap_and_succeed_ = 0;
156 PostSetNeedsCommitToMainThread();
159 void SetupTree() override {
160 scoped_refptr<FakeContentLayer> root =
161 FakeContentLayer::Create(layer_settings(), &client_);
162 root->SetBounds(gfx::Size(10, 10));
164 // Most of the layer isn't visible.
165 content_ = FakeContentLayer::Create(layer_settings(), &client_);
166 content_->SetBounds(gfx::Size(2000, 100));
167 root->AddChild(content_);
169 layer_tree_host()->SetRootLayer(root);
170 LayerTreeHostDamageTest::SetupTree();
173 DrawResult PrepareToDrawOnThread(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 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
201 ++did_swaps_;
202 if (result)
203 ++did_swap_and_succeed_;
204 EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
207 void DidCommit() override {
208 int next_frame = layer_tree_host()->source_frame_number();
209 switch (next_frame) {
210 case 1:
211 layer_tree_host()->SetNeedsCommit();
212 break;
213 case 2:
214 // Cause visible damage.
215 content_->SetNeedsDisplayRect(
216 gfx::Rect(layer_tree_host()->device_viewport_size()));
217 break;
218 case 3:
219 // Cause non-visible damage.
220 content_->SetNeedsDisplayRect(gfx::Rect(1990, 1990, 10, 10));
221 layer_tree_host()->SetNeedsCommit();
222 break;
226 void AfterTest() override {
227 EXPECT_EQ(4, did_swaps_);
228 EXPECT_EQ(2, expect_swap_and_succeed_);
229 EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
232 FakeContentLayerClient client_;
233 scoped_refptr<FakeContentLayer> content_;
234 int expect_swap_and_succeed_;
235 int did_swaps_;
236 int did_swap_and_succeed_;
239 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
240 LayerTreeHostDamageTestNoDamageDoesNotSwap);
242 class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
243 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
245 void SetupTree() override {
246 root_ = FakeContentLayer::Create(layer_settings(), &client_);
247 child_ = FakeContentLayer::Create(layer_settings(), &client_);
249 root_->SetBounds(gfx::Size(500, 500));
250 child_->SetPosition(gfx::Point(100, 100));
251 child_->SetBounds(gfx::Size(30, 30));
253 root_->AddChild(child_);
254 layer_tree_host()->SetRootLayer(root_);
255 LayerTreeHostDamageTest::SetupTree();
258 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
259 LayerTreeHostImpl::FrameData* frame_data,
260 DrawResult draw_result) override {
261 EXPECT_EQ(DRAW_SUCCESS, draw_result);
263 RenderSurfaceImpl* root_surface =
264 host_impl->active_tree()->root_layer()->render_surface();
265 gfx::RectF root_damage =
266 root_surface->damage_tracker()->current_damage_rect();
267 root_damage.Intersect(root_surface->content_rect());
269 int source_frame = host_impl->active_tree()->source_frame_number();
270 switch (source_frame) {
271 case 0:
272 // The first frame draws and clears any damage.
273 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
274 root_damage.ToString());
275 EXPECT_FALSE(frame_data->has_no_damage);
276 break;
277 case 1:
278 // If we get a frame without damage then we don't draw.
279 EXPECT_EQ(gfx::RectF().ToString(), root_damage.ToString());
280 EXPECT_TRUE(frame_data->has_no_damage);
282 // Then we set full damage for the next frame.
283 host_impl->SetFullRootLayerDamage();
284 break;
285 case 2:
286 // The whole frame should be damaged as requested.
287 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
288 root_damage.ToString());
289 EXPECT_FALSE(frame_data->has_no_damage);
291 // Just a part of the next frame should be damaged.
292 child_damage_rect_ = gfx::Rect(10, 11, 12, 13);
293 break;
294 case 3:
295 // The update rect in the child should be damaged and the damaged area
296 // should match the invalidation.
297 EXPECT_EQ(gfx::RectF(100+10, 100+11, 12, 13).ToString(),
298 root_damage.ToString());
300 // TODO(danakj): Remove this when impl side painting is always on.
301 if (delegating_renderer() ||
302 host_impl->settings().impl_side_painting) {
303 // When using a delegating renderer, or using impl side painting, the
304 // entire child is considered damaged as we need to replace its
305 // resources with newly created ones. The damaged area is kept as it
306 // is, but entire child is painted.
308 // The paint rect should match the layer bounds.
309 gfx::RectF paint_rect = child_->LastPaintRect();
310 paint_rect.set_origin(child_->position());
311 EXPECT_EQ(gfx::RectF(100, 100, 30, 30).ToString(),
312 paint_rect.ToString());
314 EXPECT_FALSE(frame_data->has_no_damage);
316 // If we damage part of the frame, but also damage the full
317 // frame, then the whole frame should be damaged.
318 child_damage_rect_ = gfx::Rect(10, 11, 12, 13);
319 host_impl->SetFullRootLayerDamage();
320 break;
321 case 4:
322 // The whole frame is damaged.
323 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
324 root_damage.ToString());
325 EXPECT_FALSE(frame_data->has_no_damage);
327 EndTest();
328 break;
330 return draw_result;
333 void DidCommitAndDrawFrame() override {
334 if (!TestEnded())
335 layer_tree_host()->SetNeedsCommit();
337 if (!child_damage_rect_.IsEmpty()) {
338 child_->SetNeedsDisplayRect(child_damage_rect_);
339 child_damage_rect_ = gfx::Rect();
343 void AfterTest() override {}
345 FakeContentLayerClient client_;
346 scoped_refptr<FakeContentLayer> root_;
347 scoped_refptr<FakeContentLayer> child_;
348 gfx::Rect child_damage_rect_;
351 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostDamageTestForcedFullDamage);
353 class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest {
354 void SetupTree() override {
355 scoped_refptr<Layer> root_layer = Layer::Create(layer_settings());
356 root_layer->SetBounds(gfx::Size(400, 400));
357 root_layer->SetMasksToBounds(true);
358 layer_tree_host()->SetRootLayer(root_layer);
360 scoped_refptr<Layer> scroll_clip_layer = Layer::Create(layer_settings());
361 scoped_refptr<Layer> content_layer =
362 FakeContentLayer::Create(layer_settings(), &client_);
363 content_layer->SetScrollClipLayerId(scroll_clip_layer->id());
364 content_layer->SetScrollOffset(gfx::ScrollOffset(10, 20));
365 content_layer->SetBounds(gfx::Size(100, 200));
366 scroll_clip_layer->SetBounds(
367 gfx::Size(content_layer->bounds().width() - 30,
368 content_layer->bounds().height() - 50));
369 scroll_clip_layer->AddChild(content_layer);
370 root_layer->AddChild(scroll_clip_layer);
372 scoped_refptr<Layer> scrollbar_layer = FakePaintedScrollbarLayer::Create(
373 layer_settings(), false, true, content_layer->id());
374 scrollbar_layer->SetPosition(gfx::Point(300, 300));
375 scrollbar_layer->SetBounds(gfx::Size(10, 100));
376 scrollbar_layer->ToScrollbarLayer()->SetClipLayer(scroll_clip_layer->id());
377 scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(content_layer->id());
378 root_layer->AddChild(scrollbar_layer);
380 gfx::RectF content_rect(content_layer->position(),
381 content_layer->bounds());
382 gfx::RectF scrollbar_rect(scrollbar_layer->position(),
383 scrollbar_layer->bounds());
384 EXPECT_FALSE(content_rect.Intersects(scrollbar_rect));
386 LayerTreeHostDamageTest::SetupTree();
389 private:
390 FakeContentLayerClient client_;
393 class LayerTreeHostDamageTestScrollbarDoesDamage
394 : public LayerTreeHostScrollbarDamageTest {
395 void BeginTest() override {
396 did_swaps_ = 0;
397 PostSetNeedsCommitToMainThread();
400 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
401 LayerTreeHostImpl::FrameData* frame_data,
402 DrawResult draw_result) override {
403 EXPECT_EQ(DRAW_SUCCESS, draw_result);
404 RenderSurfaceImpl* root_surface =
405 host_impl->active_tree()->root_layer()->render_surface();
406 gfx::RectF root_damage =
407 root_surface->damage_tracker()->current_damage_rect();
408 root_damage.Intersect(root_surface->content_rect());
409 switch (did_swaps_) {
410 case 0:
411 // The first frame has damage, so we should draw and swap.
412 break;
413 case 1:
414 // The second frame should not damage the scrollbars.
415 EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
416 break;
417 case 2:
418 // The third frame should damage the scrollbars.
419 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
420 break;
421 case 3:
422 // The fourth frame should damage the scrollbars.
423 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
424 EndTest();
425 break;
427 return draw_result;
430 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
431 ++did_swaps_;
432 EXPECT_TRUE(result);
433 LayerImpl* root = host_impl->active_tree()->root_layer();
434 LayerImpl* scroll_clip_layer = root->children()[0];
435 LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
436 switch (did_swaps_) {
437 case 1:
438 // Test that modifying the position of the content layer (not
439 // scrolling) won't damage the scrollbar.
440 scroll_layer->SetPosition(gfx::Point(1, 1));
441 scroll_layer->PushScrollOffsetFromMainThread(
442 scroll_layer->BaseScrollOffset());
443 host_impl->SetNeedsRedraw();
444 break;
445 case 2:
446 scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
447 host_impl->SetNeedsRedraw();
448 break;
449 case 3:
450 scroll_layer->SetBounds(gfx::Size(root->bounds().width() + 60,
451 root->bounds().height() + 100));
452 host_impl->SetNeedsRedraw();
453 break;
457 void AfterTest() override { EXPECT_EQ(4, did_swaps_); }
459 int did_swaps_;
462 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarDoesDamage);
464 class LayerTreeHostDamageTestScrollbarCommitDoesNoDamage
465 : public LayerTreeHostScrollbarDamageTest {
466 void BeginTest() override {
467 did_swaps_ = 0;
468 PostSetNeedsCommitToMainThread();
471 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
472 LayerTreeHostImpl::FrameData* frame_data,
473 DrawResult draw_result) override {
474 EXPECT_EQ(DRAW_SUCCESS, draw_result);
475 RenderSurfaceImpl* root_surface =
476 host_impl->active_tree()->root_layer()->render_surface();
477 gfx::RectF root_damage =
478 root_surface->damage_tracker()->current_damage_rect();
479 root_damage.Intersect(root_surface->content_rect());
480 int frame = host_impl->active_tree()->source_frame_number();
481 switch (did_swaps_) {
482 case 0:
483 // The first frame has damage, so we should draw and swap.
484 EXPECT_EQ(0, frame);
485 break;
486 case 1:
487 // The second frame has scrolled, so the scrollbar should be damaged.
488 EXPECT_EQ(0, frame);
489 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
490 break;
491 case 2:
492 // The third frame (after the commit) has no changes, so it shouldn't.
493 EXPECT_EQ(1, frame);
494 EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
495 break;
496 default:
497 NOTREACHED();
498 break;
500 return draw_result;
503 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
504 ++did_swaps_;
505 EXPECT_TRUE(result);
506 LayerImpl* root = host_impl->active_tree()->root_layer();
507 LayerImpl* scroll_clip_layer = root->children()[0];
508 LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
509 switch (did_swaps_) {
510 case 1:
511 // Scroll on the thread. This should damage the scrollbar for the
512 // next draw on the thread.
513 scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
514 host_impl->SetNeedsRedraw();
515 break;
516 case 2:
517 // Forcibly send the scroll to the main thread.
518 PostSetNeedsCommitToMainThread();
519 break;
520 case 3:
521 // First swap after second commit.
522 EndTest();
523 break;
524 default:
525 NOTREACHED();
526 break;
530 void AfterTest() override { EXPECT_EQ(3, did_swaps_); }
532 int did_swaps_;
535 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarCommitDoesNoDamage);
537 } // namespace
538 } // namespace cc