Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest_damage.cc
blobe2cccb5c801513678c9444641f89e8059ec93460
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/time/time.h"
11 #include "cc/layers/solid_color_layer.h"
12 #include "cc/test/fake_content_layer_client.h"
13 #include "cc/test/fake_painted_scrollbar_layer.h"
14 #include "cc/test/fake_picture_layer.h"
15 #include "cc/test/layer_tree_test.h"
16 #include "cc/trees/damage_tracker.h"
17 #include "cc/trees/layer_tree_impl.h"
19 namespace cc {
20 namespace {
22 // These tests deal with damage tracking.
23 class LayerTreeHostDamageTest : public LayerTreeTest {};
25 // LayerTreeHost::SetNeedsRedraw should damage the whole viewport.
26 class LayerTreeHostDamageTestSetNeedsRedraw
27 : public LayerTreeHostDamageTest {
28 void SetupTree() override {
29 // Viewport is 10x10.
30 scoped_refptr<FakePictureLayer> root =
31 FakePictureLayer::Create(layer_settings(), &client_);
32 root->SetBounds(gfx::Size(10, 10));
34 layer_tree_host()->SetRootLayer(root);
35 LayerTreeHostDamageTest::SetupTree();
38 void BeginTest() override {
39 draw_count_ = 0;
40 PostSetNeedsCommitToMainThread();
43 void DidCommitAndDrawFrame() override {
44 switch (layer_tree_host()->source_frame_number()) {
45 case 1:
46 layer_tree_host()->SetNeedsRedraw();
47 break;
51 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* impl,
52 LayerTreeHostImpl::FrameData* frame_data,
53 DrawResult draw_result) override {
54 EXPECT_EQ(DRAW_SUCCESS, draw_result);
56 RenderSurfaceImpl* root_surface =
57 impl->active_tree()->root_layer()->render_surface();
58 gfx::Rect root_damage =
59 root_surface->damage_tracker()->current_damage_rect();
61 switch (draw_count_) {
62 case 0:
63 // The first frame has full damage.
64 EXPECT_EQ(gfx::Rect(10, 10), root_damage);
65 break;
66 case 1:
67 // The second frame has full damage.
68 EXPECT_EQ(gfx::Rect(10, 10), root_damage);
69 EndTest();
70 break;
71 case 2:
72 NOTREACHED();
75 ++draw_count_;
76 return draw_result;
79 void AfterTest() override {}
81 int draw_count_;
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 void SetupTree() override {
91 // Viewport is 10x10.
92 scoped_refptr<FakePictureLayer> root =
93 FakePictureLayer::Create(layer_settings(), &client_);
94 root->SetBounds(gfx::Size(10, 10));
96 layer_tree_host()->SetRootLayer(root);
97 LayerTreeHostDamageTest::SetupTree();
100 void BeginTest() override {
101 draw_count_ = 0;
102 PostSetNeedsCommitToMainThread();
105 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 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* impl,
114 LayerTreeHostImpl::FrameData* frame_data,
115 DrawResult draw_result) override {
116 EXPECT_EQ(DRAW_SUCCESS, draw_result);
118 RenderSurfaceImpl* root_surface =
119 impl->active_tree()->root_layer()->render_surface();
120 gfx::Rect root_damage =
121 root_surface->damage_tracker()->current_damage_rect();
123 switch (draw_count_) {
124 case 0:
125 // The first frame has full damage.
126 EXPECT_EQ(gfx::Rect(10, 10), root_damage);
127 break;
128 case 1:
129 // The second frame has full damage.
130 EXPECT_EQ(gfx::Rect(15, 15), root_damage);
131 EndTest();
132 break;
133 case 2:
134 NOTREACHED();
137 ++draw_count_;
138 return draw_result;
141 void AfterTest() override {}
143 int draw_count_;
144 FakeContentLayerClient client_;
147 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetViewportSize);
149 class LayerTreeHostDamageTestNoDamageDoesNotSwap
150 : public LayerTreeHostDamageTest {
151 void BeginTest() override {
152 expect_swap_and_succeed_ = 0;
153 did_swaps_ = 0;
154 did_swap_and_succeed_ = 0;
155 PostSetNeedsCommitToMainThread();
158 void SetupTree() override {
159 scoped_refptr<FakePictureLayer> root =
160 FakePictureLayer::Create(layer_settings(), &client_);
161 root->SetBounds(gfx::Size(10, 10));
163 // Most of the layer isn't visible.
164 content_ = FakePictureLayer::Create(layer_settings(), &client_);
165 content_->SetBounds(gfx::Size(2000, 100));
166 root->AddChild(content_);
168 layer_tree_host()->SetRootLayer(root);
169 LayerTreeHostDamageTest::SetupTree();
172 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
173 LayerTreeHostImpl::FrameData* frame_data,
174 DrawResult draw_result) override {
175 EXPECT_EQ(DRAW_SUCCESS, draw_result);
177 int source_frame = host_impl->active_tree()->source_frame_number();
178 switch (source_frame) {
179 case 0:
180 // The first frame has damage, so we should draw and swap.
181 ++expect_swap_and_succeed_;
182 break;
183 case 1:
184 // The second frame has no damage, so we should not draw and swap.
185 break;
186 case 2:
187 // The third frame has damage again, so we should draw and swap.
188 ++expect_swap_and_succeed_;
189 break;
190 case 3:
191 // The fourth frame has no visible damage, so we should not draw and
192 // swap.
193 EndTest();
194 break;
196 return draw_result;
199 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
200 ++did_swaps_;
201 if (result)
202 ++did_swap_and_succeed_;
203 EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
206 void DidCommit() override {
207 int next_frame = layer_tree_host()->source_frame_number();
208 switch (next_frame) {
209 case 1:
210 layer_tree_host()->SetNeedsCommit();
211 break;
212 case 2:
213 // Cause visible damage.
214 content_->SetNeedsDisplayRect(
215 gfx::Rect(layer_tree_host()->device_viewport_size()));
216 break;
217 case 3:
218 // Cause non-visible damage.
219 content_->SetNeedsDisplayRect(gfx::Rect(1990, 1990, 10, 10));
220 layer_tree_host()->SetNeedsCommit();
221 break;
225 void AfterTest() override {
226 EXPECT_EQ(4, did_swaps_);
227 EXPECT_EQ(2, expect_swap_and_succeed_);
228 EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
231 FakeContentLayerClient client_;
232 scoped_refptr<FakePictureLayer> content_;
233 int expect_swap_and_succeed_;
234 int did_swaps_;
235 int did_swap_and_succeed_;
238 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestNoDamageDoesNotSwap);
240 class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
241 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
243 void SetupTree() override {
244 root_ = FakePictureLayer::Create(layer_settings(), &client_);
245 child_ = FakePictureLayer::Create(layer_settings(), &client_);
247 root_->SetBounds(gfx::Size(500, 500));
248 child_->SetPosition(gfx::Point(100, 100));
249 child_->SetBounds(gfx::Size(30, 30));
251 root_->AddChild(child_);
252 layer_tree_host()->SetRootLayer(root_);
253 LayerTreeHostDamageTest::SetupTree();
256 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
257 LayerTreeHostImpl::FrameData* frame_data,
258 DrawResult draw_result) override {
259 EXPECT_EQ(DRAW_SUCCESS, draw_result);
261 RenderSurfaceImpl* root_surface =
262 host_impl->active_tree()->root_layer()->render_surface();
263 gfx::Rect root_damage =
264 root_surface->damage_tracker()->current_damage_rect();
265 root_damage.Intersect(root_surface->content_rect());
267 int source_frame = host_impl->active_tree()->source_frame_number();
268 switch (source_frame) {
269 case 0:
270 // The first frame draws and clears any damage.
271 EXPECT_EQ(root_surface->content_rect(), root_damage);
272 EXPECT_FALSE(frame_data->has_no_damage);
273 break;
274 case 1:
275 // If we get a frame without damage then we don't draw.
276 EXPECT_EQ(gfx::Rect(), root_damage);
277 EXPECT_TRUE(frame_data->has_no_damage);
279 // Then we set full damage for the next frame.
280 host_impl->SetFullRootLayerDamage();
281 break;
282 case 2:
283 // The whole frame should be damaged as requested.
284 EXPECT_EQ(root_surface->content_rect(), root_damage);
285 EXPECT_FALSE(frame_data->has_no_damage);
287 // Just a part of the next frame should be damaged.
288 child_damage_rect_ = gfx::Rect(10, 11, 12, 13);
289 break;
290 case 3:
291 // The update rect in the child should be damaged and the damaged area
292 // should match the invalidation.
293 EXPECT_EQ(gfx::Rect(100 + 10, 100 + 11, 12, 13), root_damage);
294 EXPECT_FALSE(frame_data->has_no_damage);
296 // If we damage part of the frame, but also damage the full
297 // frame, then the whole frame should be damaged.
298 child_damage_rect_ = gfx::Rect(10, 11, 12, 13);
299 host_impl->SetFullRootLayerDamage();
300 break;
301 case 4:
302 // The whole frame is damaged.
303 EXPECT_EQ(root_surface->content_rect(), root_damage);
304 EXPECT_FALSE(frame_data->has_no_damage);
306 EndTest();
307 break;
309 return draw_result;
312 void DidCommitAndDrawFrame() override {
313 if (!TestEnded())
314 layer_tree_host()->SetNeedsCommit();
316 if (!child_damage_rect_.IsEmpty()) {
317 child_->SetNeedsDisplayRect(child_damage_rect_);
318 child_damage_rect_ = gfx::Rect();
322 void AfterTest() override {}
324 FakeContentLayerClient client_;
325 scoped_refptr<FakePictureLayer> root_;
326 scoped_refptr<FakePictureLayer> child_;
327 gfx::Rect child_damage_rect_;
330 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestForcedFullDamage);
332 class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest {
333 void SetupTree() override {
334 scoped_refptr<Layer> root_layer = Layer::Create(layer_settings());
335 root_layer->SetBounds(gfx::Size(400, 400));
336 root_layer->SetMasksToBounds(true);
337 layer_tree_host()->SetRootLayer(root_layer);
339 scoped_refptr<Layer> scroll_clip_layer = Layer::Create(layer_settings());
340 scoped_refptr<Layer> content_layer =
341 FakePictureLayer::Create(layer_settings(), &client_);
342 content_layer->SetScrollClipLayerId(scroll_clip_layer->id());
343 content_layer->SetScrollOffset(gfx::ScrollOffset(10, 20));
344 content_layer->SetBounds(gfx::Size(100, 200));
345 content_layer->SetIsDrawable(true);
346 scroll_clip_layer->SetBounds(
347 gfx::Size(content_layer->bounds().width() - 30,
348 content_layer->bounds().height() - 50));
349 scroll_clip_layer->AddChild(content_layer);
350 root_layer->AddChild(scroll_clip_layer);
352 scoped_refptr<Layer> scrollbar_layer = FakePaintedScrollbarLayer::Create(
353 layer_settings(), false, true, content_layer->id());
354 scrollbar_layer->SetPosition(gfx::Point(300, 300));
355 scrollbar_layer->SetBounds(gfx::Size(10, 100));
356 scrollbar_layer->ToScrollbarLayer()->SetClipLayer(scroll_clip_layer->id());
357 scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(content_layer->id());
358 root_layer->AddChild(scrollbar_layer);
360 gfx::RectF content_rect(content_layer->position(),
361 content_layer->bounds());
362 gfx::RectF scrollbar_rect(scrollbar_layer->position(),
363 scrollbar_layer->bounds());
364 EXPECT_FALSE(content_rect.Intersects(scrollbar_rect));
366 LayerTreeHostDamageTest::SetupTree();
369 private:
370 FakeContentLayerClient client_;
373 class LayerTreeHostDamageTestScrollbarDoesDamage
374 : public LayerTreeHostScrollbarDamageTest {
375 void BeginTest() override {
376 did_swaps_ = 0;
377 PostSetNeedsCommitToMainThread();
380 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
381 LayerTreeHostImpl::FrameData* frame_data,
382 DrawResult draw_result) override {
383 EXPECT_EQ(DRAW_SUCCESS, draw_result);
384 RenderSurfaceImpl* root_surface =
385 host_impl->active_tree()->root_layer()->render_surface();
386 gfx::Rect root_damage =
387 root_surface->damage_tracker()->current_damage_rect();
388 root_damage.Intersect(root_surface->content_rect());
389 switch (did_swaps_) {
390 case 0:
391 // The first frame has damage, so we should draw and swap.
392 break;
393 case 1:
394 // The second frame should not damage the scrollbars.
395 EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
396 break;
397 case 2:
398 // The third frame should damage the scrollbars.
399 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
400 break;
401 case 3:
402 // The fourth frame should damage the scrollbars.
403 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
404 EndTest();
405 break;
407 return draw_result;
410 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
411 ++did_swaps_;
412 EXPECT_TRUE(result);
413 LayerImpl* root = host_impl->active_tree()->root_layer();
414 LayerImpl* scroll_clip_layer = root->children()[0];
415 LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
416 switch (did_swaps_) {
417 case 1:
418 // Test that modifying the position of the content layer (not
419 // scrolling) won't damage the scrollbar.
420 MainThreadTaskRunner()->PostTask(
421 FROM_HERE, base::Bind(&LayerTreeHostDamageTestScrollbarDoesDamage::
422 ModifyContentLayerPosition,
423 base::Unretained(this)));
424 break;
425 case 2:
426 scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
427 host_impl->SetNeedsRedraw();
428 break;
429 case 3:
430 // We will resize the content layer, on the main thread.
431 MainThreadTaskRunner()->PostTask(
432 FROM_HERE,
433 base::Bind(
434 &LayerTreeHostDamageTestScrollbarDoesDamage::ResizeScrollLayer,
435 base::Unretained(this)));
436 break;
440 void ModifyContentLayerPosition() {
441 EXPECT_EQ(1, did_swaps_);
442 Layer* root = layer_tree_host()->root_layer();
443 Layer* scroll_clip_layer = root->child_at(0);
444 Layer* scroll_layer = scroll_clip_layer->child_at(0);
445 scroll_layer->SetPosition(gfx::Point(10, 10));
448 void ResizeScrollLayer() {
449 EXPECT_EQ(3, did_swaps_);
450 Layer* root = layer_tree_host()->root_layer();
451 Layer* scroll_clip_layer = root->child_at(0);
452 Layer* scroll_layer = scroll_clip_layer->child_at(0);
453 scroll_layer->SetBounds(
454 gfx::Size(root->bounds().width() + 60, root->bounds().height() + 100));
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::Rect 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