PlzNavigate: Improvements to RFHM commit logic.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest_damage.cc
blobdaff40beb2dec4bff98288a3a946901ffa4f83fc
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 = FakeContentLayer::Create(&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::RectF 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::RectF(10.f, 10.f).ToString(), root_damage.ToString());
65 break;
66 case 1:
67 // The second frame has full damage.
68 EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
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<FakeContentLayer> root = FakeContentLayer::Create(&client_);
93 root->SetBounds(gfx::Size(10, 10));
95 layer_tree_host()->SetRootLayer(root);
96 LayerTreeHostDamageTest::SetupTree();
99 void BeginTest() override {
100 draw_count_ = 0;
101 PostSetNeedsCommitToMainThread();
104 void DidCommitAndDrawFrame() override {
105 switch (layer_tree_host()->source_frame_number()) {
106 case 1:
107 layer_tree_host()->SetViewportSize(gfx::Size(15, 15));
108 break;
112 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* impl,
113 LayerTreeHostImpl::FrameData* frame_data,
114 DrawResult draw_result) override {
115 EXPECT_EQ(DRAW_SUCCESS, draw_result);
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_) {
123 case 0:
124 // The first frame has full damage.
125 EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
126 break;
127 case 1:
128 // The second frame has full damage.
129 EXPECT_EQ(gfx::RectF(15.f, 15.f).ToString(), root_damage.ToString());
130 EndTest();
131 break;
132 case 2:
133 NOTREACHED();
136 ++draw_count_;
137 return draw_result;
140 void AfterTest() override {}
142 int draw_count_;
143 FakeContentLayerClient client_;
146 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetViewportSize);
148 class LayerTreeHostDamageTestNoDamageDoesNotSwap
149 : public LayerTreeHostDamageTest {
150 void BeginTest() override {
151 expect_swap_and_succeed_ = 0;
152 did_swaps_ = 0;
153 did_swap_and_succeed_ = 0;
154 PostSetNeedsCommitToMainThread();
157 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 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
171 LayerTreeHostImpl::FrameData* frame_data,
172 DrawResult draw_result) override {
173 EXPECT_EQ(DRAW_SUCCESS, draw_result);
175 int source_frame = host_impl->active_tree()->source_frame_number();
176 switch (source_frame) {
177 case 0:
178 // The first frame has damage, so we should draw and swap.
179 ++expect_swap_and_succeed_;
180 break;
181 case 1:
182 // The second frame has no damage, so we should not draw and swap.
183 break;
184 case 2:
185 // The third frame has damage again, so we should draw and swap.
186 ++expect_swap_and_succeed_;
187 break;
188 case 3:
189 // The fourth frame has no visible damage, so we should not draw and
190 // swap.
191 EndTest();
192 break;
194 return draw_result;
197 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
198 ++did_swaps_;
199 if (result)
200 ++did_swap_and_succeed_;
201 EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
204 void DidCommit() override {
205 int next_frame = layer_tree_host()->source_frame_number();
206 switch (next_frame) {
207 case 1:
208 layer_tree_host()->SetNeedsCommit();
209 break;
210 case 2:
211 // Cause visible damage.
212 content_->SetNeedsDisplayRect(
213 gfx::Rect(layer_tree_host()->device_viewport_size()));
214 break;
215 case 3:
216 // Cause non-visible damage.
217 content_->SetNeedsDisplayRect(gfx::Rect(1990, 1990, 10, 10));
218 layer_tree_host()->SetNeedsCommit();
219 break;
223 void AfterTest() override {
224 EXPECT_EQ(4, did_swaps_);
225 EXPECT_EQ(2, expect_swap_and_succeed_);
226 EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
229 FakeContentLayerClient client_;
230 scoped_refptr<FakeContentLayer> content_;
231 int expect_swap_and_succeed_;
232 int did_swaps_;
233 int did_swap_and_succeed_;
236 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
237 LayerTreeHostDamageTestNoDamageDoesNotSwap);
239 class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
240 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
242 void SetupTree() override {
243 root_ = FakeContentLayer::Create(&client_);
244 child_ = FakeContentLayer::Create(&client_);
246 root_->SetBounds(gfx::Size(500, 500));
247 child_->SetPosition(gfx::Point(100, 100));
248 child_->SetBounds(gfx::Size(30, 30));
250 root_->AddChild(child_);
251 layer_tree_host()->SetRootLayer(root_);
252 LayerTreeHostDamageTest::SetupTree();
255 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
256 LayerTreeHostImpl::FrameData* frame_data,
257 DrawResult draw_result) override {
258 EXPECT_EQ(DRAW_SUCCESS, draw_result);
260 RenderSurfaceImpl* root_surface =
261 host_impl->active_tree()->root_layer()->render_surface();
262 gfx::RectF root_damage =
263 root_surface->damage_tracker()->current_damage_rect();
264 root_damage.Intersect(root_surface->content_rect());
266 int source_frame = host_impl->active_tree()->source_frame_number();
267 switch (source_frame) {
268 case 0:
269 // The first frame draws and clears any damage.
270 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
271 root_damage.ToString());
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::RectF().ToString(), root_damage.ToString());
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(gfx::RectF(root_surface->content_rect()).ToString(),
285 root_damage.ToString());
286 EXPECT_FALSE(frame_data->has_no_damage);
288 // Just a part of the next frame should be damaged.
289 child_damage_rect_ = gfx::Rect(10, 11, 12, 13);
290 break;
291 case 3:
292 // The update rect in the child should be damaged and the damaged area
293 // should match the invalidation.
294 EXPECT_EQ(gfx::RectF(100+10, 100+11, 12, 13).ToString(),
295 root_damage.ToString());
297 // TODO(danakj): Remove this when impl side painting is always on.
298 if (delegating_renderer() ||
299 host_impl->settings().impl_side_painting) {
300 // When using a delegating renderer, or using impl side painting, the
301 // entire child is considered damaged as we need to replace its
302 // resources with newly created ones. The damaged area is kept as it
303 // is, but entire child is painted.
305 // The paint rect should match the layer bounds.
306 gfx::RectF paint_rect = child_->LastPaintRect();
307 paint_rect.set_origin(child_->position());
308 EXPECT_EQ(gfx::RectF(100, 100, 30, 30).ToString(),
309 paint_rect.ToString());
311 EXPECT_FALSE(frame_data->has_no_damage);
313 // If we damage part of the frame, but also damage the full
314 // frame, then the whole frame should be damaged.
315 child_damage_rect_ = gfx::Rect(10, 11, 12, 13);
316 host_impl->SetFullRootLayerDamage();
317 break;
318 case 4:
319 // The whole frame is damaged.
320 EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
321 root_damage.ToString());
322 EXPECT_FALSE(frame_data->has_no_damage);
324 EndTest();
325 break;
327 return draw_result;
330 void DidCommitAndDrawFrame() override {
331 if (!TestEnded())
332 layer_tree_host()->SetNeedsCommit();
334 if (!child_damage_rect_.IsEmpty()) {
335 child_->SetNeedsDisplayRect(child_damage_rect_);
336 child_damage_rect_ = gfx::Rect();
340 void AfterTest() override {}
342 FakeContentLayerClient client_;
343 scoped_refptr<FakeContentLayer> root_;
344 scoped_refptr<FakeContentLayer> child_;
345 gfx::Rect child_damage_rect_;
348 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostDamageTestForcedFullDamage);
350 class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest {
351 void SetupTree() override {
352 scoped_refptr<Layer> root_layer = Layer::Create();
353 root_layer->SetBounds(gfx::Size(400, 400));
354 root_layer->SetMasksToBounds(true);
355 layer_tree_host()->SetRootLayer(root_layer);
357 scoped_refptr<Layer> scroll_clip_layer = Layer::Create();
358 scoped_refptr<Layer> content_layer = FakeContentLayer::Create(&client_);
359 content_layer->SetScrollClipLayerId(scroll_clip_layer->id());
360 content_layer->SetScrollOffset(gfx::ScrollOffset(10, 20));
361 content_layer->SetBounds(gfx::Size(100, 200));
362 scroll_clip_layer->SetBounds(
363 gfx::Size(content_layer->bounds().width() - 30,
364 content_layer->bounds().height() - 50));
365 scroll_clip_layer->AddChild(content_layer);
366 root_layer->AddChild(scroll_clip_layer);
368 scoped_refptr<Layer> scrollbar_layer =
369 FakePaintedScrollbarLayer::Create(false, true, content_layer->id());
370 scrollbar_layer->SetPosition(gfx::Point(300, 300));
371 scrollbar_layer->SetBounds(gfx::Size(10, 100));
372 scrollbar_layer->ToScrollbarLayer()->SetClipLayer(scroll_clip_layer->id());
373 scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(content_layer->id());
374 root_layer->AddChild(scrollbar_layer);
376 gfx::RectF content_rect(content_layer->position(),
377 content_layer->bounds());
378 gfx::RectF scrollbar_rect(scrollbar_layer->position(),
379 scrollbar_layer->bounds());
380 EXPECT_FALSE(content_rect.Intersects(scrollbar_rect));
382 LayerTreeHostDamageTest::SetupTree();
385 private:
386 FakeContentLayerClient client_;
389 class LayerTreeHostDamageTestScrollbarDoesDamage
390 : public LayerTreeHostScrollbarDamageTest {
391 void BeginTest() override {
392 did_swaps_ = 0;
393 PostSetNeedsCommitToMainThread();
396 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
397 LayerTreeHostImpl::FrameData* frame_data,
398 DrawResult draw_result) override {
399 EXPECT_EQ(DRAW_SUCCESS, draw_result);
400 RenderSurfaceImpl* root_surface =
401 host_impl->active_tree()->root_layer()->render_surface();
402 gfx::RectF root_damage =
403 root_surface->damage_tracker()->current_damage_rect();
404 root_damage.Intersect(root_surface->content_rect());
405 switch (did_swaps_) {
406 case 0:
407 // The first frame has damage, so we should draw and swap.
408 break;
409 case 1:
410 // The second frame should not damage the scrollbars.
411 EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
412 break;
413 case 2:
414 // The third frame should damage the scrollbars.
415 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
416 break;
417 case 3:
418 // The fourth frame should damage the scrollbars.
419 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
420 EndTest();
421 break;
423 return draw_result;
426 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
427 ++did_swaps_;
428 EXPECT_TRUE(result);
429 LayerImpl* root = host_impl->active_tree()->root_layer();
430 LayerImpl* scroll_clip_layer = root->children()[0];
431 LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
432 switch (did_swaps_) {
433 case 1:
434 // Test that modifying the position of the content layer (not
435 // scrolling) won't damage the scrollbar.
436 scroll_layer->SetPosition(gfx::Point(1, 1));
437 scroll_layer->PushScrollOffsetFromMainThread(
438 scroll_layer->BaseScrollOffset());
439 host_impl->SetNeedsRedraw();
440 break;
441 case 2:
442 scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
443 host_impl->SetNeedsRedraw();
444 break;
445 case 3:
446 scroll_layer->SetBounds(gfx::Size(root->bounds().width() + 60,
447 root->bounds().height() + 100));
448 host_impl->SetNeedsRedraw();
449 break;
453 void AfterTest() override { EXPECT_EQ(4, did_swaps_); }
455 int did_swaps_;
458 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarDoesDamage);
460 class LayerTreeHostDamageTestScrollbarCommitDoesNoDamage
461 : public LayerTreeHostScrollbarDamageTest {
462 void BeginTest() override {
463 did_swaps_ = 0;
464 PostSetNeedsCommitToMainThread();
467 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
468 LayerTreeHostImpl::FrameData* frame_data,
469 DrawResult draw_result) override {
470 EXPECT_EQ(DRAW_SUCCESS, draw_result);
471 RenderSurfaceImpl* root_surface =
472 host_impl->active_tree()->root_layer()->render_surface();
473 gfx::RectF root_damage =
474 root_surface->damage_tracker()->current_damage_rect();
475 root_damage.Intersect(root_surface->content_rect());
476 int frame = host_impl->active_tree()->source_frame_number();
477 switch (did_swaps_) {
478 case 0:
479 // The first frame has damage, so we should draw and swap.
480 EXPECT_EQ(0, frame);
481 break;
482 case 1:
483 // The second frame has scrolled, so the scrollbar should be damaged.
484 EXPECT_EQ(0, frame);
485 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
486 break;
487 case 2:
488 // The third frame (after the commit) has no changes, so it shouldn't.
489 EXPECT_EQ(1, frame);
490 EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
491 break;
492 default:
493 NOTREACHED();
494 break;
496 return draw_result;
499 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
500 ++did_swaps_;
501 EXPECT_TRUE(result);
502 LayerImpl* root = host_impl->active_tree()->root_layer();
503 LayerImpl* scroll_clip_layer = root->children()[0];
504 LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
505 switch (did_swaps_) {
506 case 1:
507 // Scroll on the thread. This should damage the scrollbar for the
508 // next draw on the thread.
509 scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
510 host_impl->SetNeedsRedraw();
511 break;
512 case 2:
513 // Forcibly send the scroll to the main thread.
514 PostSetNeedsCommitToMainThread();
515 break;
516 case 3:
517 // First swap after second commit.
518 EndTest();
519 break;
520 default:
521 NOTREACHED();
522 break;
526 void AfterTest() override { EXPECT_EQ(3, did_swaps_); }
528 int did_swaps_;
531 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarCommitDoesNoDamage);
533 } // namespace
534 } // namespace cc