Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / cc / trees / layer_tree_host_unittest_damage.cc
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.
4
5 #include "cc/trees/layer_tree_host.h"
6
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"
19
20 namespace cc {
21 namespace {
22
23 // These tests deal with damage tracking.
24 class LayerTreeHostDamageTest : public LayerTreeTest {};
25
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));
33
34     layer_tree_host()->SetRootLayer(root);
35     LayerTreeHostDamageTest::SetupTree();
36   }
37
38   void BeginTest() override {
39     draw_count_ = 0;
40     PostSetNeedsCommitToMainThread();
41   }
42
43   void DidCommitAndDrawFrame() override {
44     switch (layer_tree_host()->source_frame_number()) {
45       case 1:
46         layer_tree_host()->SetNeedsRedraw();
47         break;
48     }
49   }
50
51   DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* impl,
52                                    LayerTreeHostImpl::FrameData* frame_data,
53                                    DrawResult draw_result) override {
54     EXPECT_EQ(DRAW_SUCCESS, draw_result);
55
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();
60
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();
73     }
74
75     ++draw_count_;
76     return draw_result;
77   }
78
79   void AfterTest() override {}
80
81   int draw_count_;
82   FakeContentLayerClient client_;
83 };
84
85 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetNeedsRedraw);
86
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));
94
95     layer_tree_host()->SetRootLayer(root);
96     LayerTreeHostDamageTest::SetupTree();
97   }
98
99   void BeginTest() override {
100     draw_count_ = 0;
101     PostSetNeedsCommitToMainThread();
102   }
103
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;
109     }
110   }
111
112   DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* impl,
113                                    LayerTreeHostImpl::FrameData* frame_data,
114                                    DrawResult draw_result) override {
115     EXPECT_EQ(DRAW_SUCCESS, draw_result);
116
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();
121
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();
134     }
135
136     ++draw_count_;
137     return draw_result;
138   }
139
140   void AfterTest() override {}
141
142   int draw_count_;
143   FakeContentLayerClient client_;
144 };
145
146 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetViewportSize);
147
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();
155   }
156
157   void SetupTree() override {
158     scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
159     root->SetBounds(gfx::Size(10, 10));
160
161     // Most of the layer isn't visible.
162     content_ = FakeContentLayer::Create(&client_);
163     content_->SetBounds(gfx::Size(2000, 100));
164     root->AddChild(content_);
165
166     layer_tree_host()->SetRootLayer(root);
167     LayerTreeHostDamageTest::SetupTree();
168   }
169
170   DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
171                                    LayerTreeHostImpl::FrameData* frame_data,
172                                    DrawResult draw_result) override {
173     EXPECT_EQ(DRAW_SUCCESS, draw_result);
174
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;
193     }
194     return draw_result;
195   }
196
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_);
202   }
203
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;
220     }
221   }
222
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_);
227   }
228
229   FakeContentLayerClient client_;
230   scoped_refptr<FakeContentLayer> content_;
231   int expect_swap_and_succeed_;
232   int did_swaps_;
233   int did_swap_and_succeed_;
234 };
235
236 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
237     LayerTreeHostDamageTestNoDamageDoesNotSwap);
238
239 class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
240   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
241
242   void SetupTree() override {
243     root_ = FakeContentLayer::Create(&client_);
244     child_ = FakeContentLayer::Create(&client_);
245
246     root_->SetBounds(gfx::Size(500, 500));
247     child_->SetPosition(gfx::Point(100, 100));
248     child_->SetBounds(gfx::Size(30, 30));
249
250     root_->AddChild(child_);
251     layer_tree_host()->SetRootLayer(root_);
252     LayerTreeHostDamageTest::SetupTree();
253   }
254
255   DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
256                                    LayerTreeHostImpl::FrameData* frame_data,
257                                    DrawResult draw_result) override {
258     EXPECT_EQ(DRAW_SUCCESS, draw_result);
259
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());
265
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);
278
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);
287
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());
296
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.
304
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());
310         }
311         EXPECT_FALSE(frame_data->has_no_damage);
312
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);
323
324         EndTest();
325         break;
326     }
327     return draw_result;
328   }
329
330   void DidCommitAndDrawFrame() override {
331     if (!TestEnded())
332       layer_tree_host()->SetNeedsCommit();
333
334     if (!child_damage_rect_.IsEmpty()) {
335       child_->SetNeedsDisplayRect(child_damage_rect_);
336       child_damage_rect_ = gfx::Rect();
337     }
338   }
339
340   void AfterTest() override {}
341
342   FakeContentLayerClient client_;
343   scoped_refptr<FakeContentLayer> root_;
344   scoped_refptr<FakeContentLayer> child_;
345   gfx::Rect child_damage_rect_;
346 };
347
348 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostDamageTestForcedFullDamage);
349
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);
356
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);
367
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);
375
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));
381
382     LayerTreeHostDamageTest::SetupTree();
383   }
384
385  private:
386   FakeContentLayerClient client_;
387 };
388
389 class LayerTreeHostDamageTestScrollbarDoesDamage
390     : public LayerTreeHostScrollbarDamageTest {
391   void BeginTest() override {
392     did_swaps_ = 0;
393     PostSetNeedsCommitToMainThread();
394   }
395
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;
422     }
423     return draw_result;
424   }
425
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->SetScrollOffset(scroll_layer->scroll_offset());
438         host_impl->SetNeedsRedraw();
439         break;
440       case 2:
441         scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
442         host_impl->SetNeedsRedraw();
443         break;
444       case 3:
445         scroll_layer->SetBounds(gfx::Size(root->bounds().width() + 60,
446                                           root->bounds().height() + 100));
447         host_impl->SetNeedsRedraw();
448         break;
449     }
450   }
451
452   void AfterTest() override { EXPECT_EQ(4, did_swaps_); }
453
454   int did_swaps_;
455 };
456
457 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarDoesDamage);
458
459 class LayerTreeHostDamageTestScrollbarCommitDoesNoDamage
460     : public LayerTreeHostScrollbarDamageTest {
461   void BeginTest() override {
462     did_swaps_ = 0;
463     PostSetNeedsCommitToMainThread();
464   }
465
466   DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
467                                    LayerTreeHostImpl::FrameData* frame_data,
468                                    DrawResult draw_result) override {
469     EXPECT_EQ(DRAW_SUCCESS, draw_result);
470     RenderSurfaceImpl* root_surface =
471         host_impl->active_tree()->root_layer()->render_surface();
472     gfx::RectF root_damage =
473         root_surface->damage_tracker()->current_damage_rect();
474     root_damage.Intersect(root_surface->content_rect());
475     int frame = host_impl->active_tree()->source_frame_number();
476     switch (did_swaps_) {
477       case 0:
478         // The first frame has damage, so we should draw and swap.
479         EXPECT_EQ(0, frame);
480         break;
481       case 1:
482         // The second frame has scrolled, so the scrollbar should be damaged.
483         EXPECT_EQ(0, frame);
484         EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
485         break;
486       case 2:
487         // The third frame (after the commit) has no changes, so it shouldn't.
488         EXPECT_EQ(1, frame);
489         EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
490         break;
491       default:
492         NOTREACHED();
493         break;
494     }
495     return draw_result;
496   }
497
498   void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
499     ++did_swaps_;
500     EXPECT_TRUE(result);
501     LayerImpl* root = host_impl->active_tree()->root_layer();
502     LayerImpl* scroll_clip_layer = root->children()[0];
503     LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
504     switch (did_swaps_) {
505       case 1:
506         // Scroll on the thread.  This should damage the scrollbar for the
507         // next draw on the thread.
508         scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
509         host_impl->SetNeedsRedraw();
510         break;
511       case 2:
512         // Forcibly send the scroll to the main thread.
513         PostSetNeedsCommitToMainThread();
514         break;
515       case 3:
516         // First swap after second commit.
517         EndTest();
518         break;
519       default:
520         NOTREACHED();
521         break;
522     }
523   }
524
525   void AfterTest() override { EXPECT_EQ(3, did_swaps_); }
526
527   int did_swaps_;
528 };
529
530 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarCommitDoesNoDamage);
531
532 class LayerTreeHostDamageTestVisibleTilesStillTriggerDraws
533     : public LayerTreeHostDamageTest {
534   void InitializeSettings(LayerTreeSettings* settings) override {
535     settings->impl_side_painting = true;
536   }
537
538   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
539
540   void SetupTree() override {
541     scoped_refptr<FakePictureLayer> root = FakePictureLayer::Create(&client_);
542     root->SetBounds(gfx::Size(500, 500));
543     layer_tree_host()->SetRootLayer(root);
544     LayerTreeHostDamageTest::SetupTree();
545
546     swap_count_ = 0;
547     prepare_to_draw_count_ = 0;
548     update_visible_tile_count_ = 0;
549   }
550
551   DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
552                                    LayerTreeHostImpl::FrameData* frame_data,
553                                    DrawResult draw_result) override {
554     EXPECT_EQ(DRAW_SUCCESS, draw_result);
555     prepare_to_draw_count_++;
556     switch (prepare_to_draw_count_) {
557       case 1:
558         // Detect that we have an incomplete tile, during the first frame.
559         // The first frame should have damage.
560         frame_data->contains_incomplete_tile = true;
561         DCHECK(!frame_data->has_no_damage);
562         break;
563       case 2:
564         // Make a no-damage frame. We early out and can't detect
565         // incomplete tiles, even if they still exist.
566         frame_data->contains_incomplete_tile = false;
567         frame_data->has_no_damage = true;
568         break;
569       case 3:
570         // Trigger the last swap for the completed tile.
571         frame_data->contains_incomplete_tile = false;
572         frame_data->has_no_damage = false;
573         EndTest();
574         break;
575       default:
576         NOTREACHED();
577         break;
578     }
579
580     return draw_result;
581   }
582
583   void UpdateVisibleTilesOnThread(LayerTreeHostImpl* host_impl) override {
584     // Simulate creating some visible tiles (that trigger prepare-to-draws).
585     // The first we make into a no-damage-frame during prepare-to-draw (see
586     // above). This is to ensure we still get UpdateVisibleTiles calls after
587     // a no-damage or aborted frame.
588     update_visible_tile_count_++;
589     switch (update_visible_tile_count_) {
590       case 3:
591       case 6:
592         host_impl->DidInitializeVisibleTileForTesting();
593         break;
594       case 7:
595         NOTREACHED();
596         break;
597     }
598   }
599
600   void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
601                            bool didSwap) override {
602     if (!didSwap)
603       return;
604     ++swap_count_;
605   }
606
607   void AfterTest() override {
608     // We should keep getting update-visible-tiles calls
609     // until we report there are no more incomplete-tiles.
610     EXPECT_EQ(update_visible_tile_count_, 6);
611     // First frame, plus two triggered by DidInitializeVisibleTile()
612     EXPECT_EQ(prepare_to_draw_count_, 3);
613     // First swap, plus final swap (contained damage).
614     EXPECT_EQ(swap_count_, 2);
615   }
616
617   FakeContentLayerClient client_;
618   int swap_count_;
619   int prepare_to_draw_count_;
620   int update_visible_tile_count_;
621 };
622
623 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestVisibleTilesStillTriggerDraws);
624
625 }  // namespace
626 }  // namespace cc