Upstream version 5.34.104.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   virtual 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   virtual void BeginTest() OVERRIDE {
39     draw_count_ = 0;
40     PostSetNeedsCommitToMainThread();
41   }
42
43   virtual 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   virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
52       LayerTreeHostImpl* impl,
53       LayerTreeHostImpl::FrameData* frame_data,
54       DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
55     EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
56
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();
61
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();
74     }
75
76     ++draw_count_;
77     return draw_result;
78   }
79
80   virtual void AfterTest() OVERRIDE {}
81
82   int draw_count_;
83   FakeContentLayerClient client_;
84 };
85
86 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetNeedsRedraw);
87
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));
95
96     layer_tree_host()->SetRootLayer(root);
97     LayerTreeHostDamageTest::SetupTree();
98   }
99
100   virtual void BeginTest() OVERRIDE {
101     draw_count_ = 0;
102     PostSetNeedsCommitToMainThread();
103   }
104
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;
110     }
111   }
112
113   virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
114       LayerTreeHostImpl* impl,
115       LayerTreeHostImpl::FrameData* frame_data,
116       DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
117     EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
118
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();
123
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();
136     }
137
138     ++draw_count_;
139     return draw_result;
140   }
141
142   virtual void AfterTest() OVERRIDE {}
143
144   int draw_count_;
145   FakeContentLayerClient client_;
146 };
147
148 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetViewportSize);
149
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();
157   }
158
159   virtual void SetupTree() OVERRIDE {
160     scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
161     root->SetBounds(gfx::Size(10, 10));
162
163     // Most of the layer isn't visible.
164     content_ = FakeContentLayer::Create(&client_);
165     content_->SetBounds(gfx::Size(2000, 100));
166     root->AddChild(content_);
167
168     layer_tree_host()->SetRootLayer(root);
169     LayerTreeHostDamageTest::SetupTree();
170   }
171
172   virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
173       LayerTreeHostImpl* host_impl,
174       LayerTreeHostImpl::FrameData* frame_data,
175       DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
176     EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
177
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;
196     }
197     return draw_result;
198   }
199
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_);
206   }
207
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;
224     }
225   }
226
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_);
231   }
232
233   FakeContentLayerClient client_;
234   scoped_refptr<FakeContentLayer> content_;
235   int expect_swap_and_succeed_;
236   int did_swaps_;
237   int did_swap_and_succeed_;
238 };
239
240 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
241     LayerTreeHostDamageTestNoDamageDoesNotSwap);
242
243 class LayerTreeHostDamageTestNoDamageReadbackDoesDraw
244     : public LayerTreeHostDamageTest {
245   virtual void BeginTest() OVERRIDE {
246     PostSetNeedsCommitToMainThread();
247   }
248
249   virtual void SetupTree() OVERRIDE {
250     scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
251     root->SetBounds(gfx::Size(10, 10));
252
253     // Most of the layer isn't visible.
254     content_ = FakeContentLayer::Create(&client_);
255     content_->SetBounds(gfx::Size(100, 100));
256     root->AddChild(content_);
257
258     layer_tree_host()->SetRootLayer(root);
259     LayerTreeHostDamageTest::SetupTree();
260   }
261
262   virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
263       LayerTreeHostImpl* host_impl,
264       LayerTreeHostImpl::FrameData* frame_data,
265       DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
266     EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
267
268     int source_frame = host_impl->active_tree()->source_frame_number();
269     switch (source_frame) {
270       case 0:
271         // The first frame draws and clears any damage.
272         break;
273       case 1: {
274         // The second frame is a readback, we should have damage in the readback
275         // rect, but not swap.
276         RenderSurfaceImpl* root_surface =
277             host_impl->active_tree()->root_layer()->render_surface();
278         gfx::RectF root_damage =
279             root_surface->damage_tracker()->current_damage_rect();
280         root_damage.Intersect(root_surface->content_rect());
281         EXPECT_TRUE(root_damage.Contains(gfx::Rect(3, 3, 1, 1)));
282         break;
283       }
284       case 2:
285         // CompositeAndReadback causes a follow-up commit.
286         break;
287       case 3:
288         NOTREACHED();
289         break;
290     }
291     return draw_result;
292   }
293
294   virtual void DidCommitAndDrawFrame() OVERRIDE {
295     int next_frame = layer_tree_host()->source_frame_number();
296     switch (next_frame) {
297       case 1: {
298         char pixels[4];
299         layer_tree_host()->CompositeAndReadback(static_cast<void*>(&pixels),
300                                                 gfx::Rect(3, 3, 1, 1));
301         EndTest();
302         break;
303       }
304     }
305   }
306
307   virtual void AfterTest() OVERRIDE {}
308
309   FakeContentLayerClient client_;
310   scoped_refptr<FakeContentLayer> content_;
311 };
312
313 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestNoDamageReadbackDoesDraw);
314
315 class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
316   virtual void BeginTest() OVERRIDE {
317     PostSetNeedsCommitToMainThread();
318   }
319
320   virtual void SetupTree() OVERRIDE {
321     root_ = FakeContentLayer::Create(&client_);
322     child_ = FakeContentLayer::Create(&client_);
323
324     root_->SetBounds(gfx::Size(500, 500));
325     child_->SetPosition(gfx::Point(100, 100));
326     child_->SetBounds(gfx::Size(30, 30));
327
328     root_->AddChild(child_);
329     layer_tree_host()->SetRootLayer(root_);
330     LayerTreeHostDamageTest::SetupTree();
331   }
332
333   virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
334       LayerTreeHostImpl* host_impl,
335       LayerTreeHostImpl::FrameData* frame_data,
336       DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
337     EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
338
339     RenderSurfaceImpl* root_surface =
340         host_impl->active_tree()->root_layer()->render_surface();
341     gfx::RectF root_damage =
342         root_surface->damage_tracker()->current_damage_rect();
343     root_damage.Intersect(root_surface->content_rect());
344
345     int source_frame = host_impl->active_tree()->source_frame_number();
346     switch (source_frame) {
347       case 0:
348         // The first frame draws and clears any damage.
349         EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
350                   root_damage.ToString());
351         EXPECT_FALSE(frame_data->has_no_damage);
352         break;
353       case 1:
354         // If we get a frame without damage then we don't draw.
355         EXPECT_EQ(gfx::RectF().ToString(), root_damage.ToString());
356         EXPECT_TRUE(frame_data->has_no_damage);
357
358         // Then we set full damage for the next frame.
359         host_impl->SetFullRootLayerDamage();
360         break;
361       case 2:
362         // The whole frame should be damaged as requested.
363         EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
364                   root_damage.ToString());
365         EXPECT_FALSE(frame_data->has_no_damage);
366
367         // Just a part of the next frame should be damaged.
368         child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
369         break;
370       case 3:
371         // The update rect in the child should be damaged and the damaged area
372         // should match the invalidation.
373         EXPECT_EQ(gfx::RectF(100+10, 100+11, 12, 13).ToString(),
374                   root_damage.ToString());
375
376         // TODO(danakj): Remove this when impl side painting is always on.
377         if (delegating_renderer() ||
378             host_impl->settings().impl_side_painting) {
379           // When using a delegating renderer, or using impl side painting, the
380           // entire child is considered damaged as we need to replace its
381           // resources with newly created ones. The damaged area is kept as it
382           // is, but entire child is painted.
383
384           // The paint rect should match the layer bounds.
385           gfx::RectF paint_rect = child_->LastPaintRect();
386           paint_rect.set_origin(child_->position());
387           EXPECT_EQ(gfx::RectF(100, 100, 30, 30).ToString(),
388                     paint_rect.ToString());
389         }
390         EXPECT_FALSE(frame_data->has_no_damage);
391
392         // If we damage part of the frame, but also damage the full
393         // frame, then the whole frame should be damaged.
394         child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
395         host_impl->SetFullRootLayerDamage();
396         break;
397       case 4:
398         // The whole frame is damaged.
399         EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
400                   root_damage.ToString());
401         EXPECT_FALSE(frame_data->has_no_damage);
402
403         EndTest();
404         break;
405     }
406     return draw_result;
407   }
408
409   virtual void DidCommitAndDrawFrame() OVERRIDE {
410     if (!TestEnded())
411       layer_tree_host()->SetNeedsCommit();
412
413     if (!child_damage_rect_.IsEmpty()) {
414       child_->SetNeedsDisplayRect(child_damage_rect_);
415       child_damage_rect_ = gfx::RectF();
416     }
417   }
418
419   virtual void AfterTest() OVERRIDE {}
420
421   FakeContentLayerClient client_;
422   scoped_refptr<FakeContentLayer> root_;
423   scoped_refptr<FakeContentLayer> child_;
424   gfx::RectF child_damage_rect_;
425 };
426
427 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostDamageTestForcedFullDamage);
428
429 class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest {
430   virtual void SetupTree() OVERRIDE {
431     scoped_refptr<Layer> root_layer = Layer::Create();
432     root_layer->SetBounds(gfx::Size(400, 400));
433     root_layer->SetMasksToBounds(true);
434     layer_tree_host()->SetRootLayer(root_layer);
435
436     scoped_refptr<Layer> scroll_clip_layer = Layer::Create();
437     scoped_refptr<Layer> content_layer = FakeContentLayer::Create(&client_);
438     content_layer->SetScrollClipLayerId(scroll_clip_layer->id());
439     content_layer->SetScrollOffset(gfx::Vector2d(10, 20));
440     content_layer->SetBounds(gfx::Size(100, 200));
441     scroll_clip_layer->SetBounds(
442         gfx::Size(content_layer->bounds().width() - 30,
443                   content_layer->bounds().height() - 50));
444     scroll_clip_layer->AddChild(content_layer);
445     root_layer->AddChild(scroll_clip_layer);
446
447     scoped_refptr<Layer> scrollbar_layer =
448         FakePaintedScrollbarLayer::Create(false, true, content_layer->id());
449     scrollbar_layer->SetPosition(gfx::Point(300, 300));
450     scrollbar_layer->SetBounds(gfx::Size(10, 100));
451     scrollbar_layer->ToScrollbarLayer()->SetClipLayer(scroll_clip_layer->id());
452     scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(content_layer->id());
453     root_layer->AddChild(scrollbar_layer);
454
455     gfx::RectF content_rect(content_layer->position(),
456                             content_layer->bounds());
457     gfx::RectF scrollbar_rect(scrollbar_layer->position(),
458                               scrollbar_layer->bounds());
459     EXPECT_FALSE(content_rect.Intersects(scrollbar_rect));
460
461     LayerTreeHostDamageTest::SetupTree();
462   }
463
464  private:
465   FakeContentLayerClient client_;
466 };
467
468 class LayerTreeHostDamageTestScrollbarDoesDamage
469     : public LayerTreeHostScrollbarDamageTest {
470   virtual void BeginTest() OVERRIDE {
471     did_swaps_ = 0;
472     PostSetNeedsCommitToMainThread();
473   }
474
475   virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
476       LayerTreeHostImpl* host_impl,
477       LayerTreeHostImpl::FrameData* frame_data,
478       DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
479     EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
480     RenderSurfaceImpl* root_surface =
481         host_impl->active_tree()->root_layer()->render_surface();
482     gfx::RectF root_damage =
483         root_surface->damage_tracker()->current_damage_rect();
484     root_damage.Intersect(root_surface->content_rect());
485     switch (did_swaps_) {
486       case 0:
487         // The first frame has damage, so we should draw and swap.
488         break;
489       case 1:
490         // The second frame should not damage the scrollbars.
491         EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
492         break;
493       case 2:
494         // The third frame should damage the scrollbars.
495         EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
496         break;
497       case 3:
498         // The fourth frame should damage the scrollbars.
499         EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
500         EndTest();
501         break;
502     }
503     return draw_result;
504   }
505
506   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
507                                    bool result) OVERRIDE {
508     ++did_swaps_;
509     EXPECT_TRUE(result);
510     LayerImpl* root = host_impl->active_tree()->root_layer();
511     LayerImpl* scroll_clip_layer = root->children()[0];
512     LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
513     switch (did_swaps_) {
514       case 1:
515         // Test that modifying the position of the content layer (not
516         // scrolling) won't damage the scrollbar.
517         scroll_layer->SetPosition(gfx::Point(1, 1));
518         scroll_layer->SetScrollOffset(scroll_layer->scroll_offset());
519         host_impl->SetNeedsRedraw();
520         break;
521       case 2:
522         scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
523         host_impl->SetNeedsRedraw();
524         break;
525       case 3:
526         scroll_layer->SetBounds(gfx::Size(root->bounds().width() + 60,
527                                           root->bounds().height() + 100));
528         host_impl->SetNeedsRedraw();
529         break;
530     }
531   }
532
533   virtual void AfterTest() OVERRIDE {
534     EXPECT_EQ(4, did_swaps_);
535   }
536
537   int did_swaps_;
538 };
539
540 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarDoesDamage);
541
542 class LayerTreeHostDamageTestScrollbarCommitDoesNoDamage
543     : public LayerTreeHostScrollbarDamageTest {
544   virtual void BeginTest() OVERRIDE {
545     did_swaps_ = 0;
546     PostSetNeedsCommitToMainThread();
547   }
548
549   virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
550       LayerTreeHostImpl* host_impl,
551       LayerTreeHostImpl::FrameData* frame_data,
552       DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
553     EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
554     RenderSurfaceImpl* root_surface =
555         host_impl->active_tree()->root_layer()->render_surface();
556     gfx::RectF root_damage =
557         root_surface->damage_tracker()->current_damage_rect();
558     root_damage.Intersect(root_surface->content_rect());
559     int frame = host_impl->active_tree()->source_frame_number();
560     switch (did_swaps_) {
561       case 0:
562         // The first frame has damage, so we should draw and swap.
563         EXPECT_EQ(0, frame);
564         break;
565       case 1:
566         // The second frame has scrolled, so the scrollbar should be damaged.
567         EXPECT_EQ(0, frame);
568         EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
569         break;
570       case 2:
571         // The third frame (after the commit) has no changes, so it shouldn't.
572         EXPECT_EQ(1, frame);
573         EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
574         break;
575       default:
576         NOTREACHED();
577         break;
578     }
579     return draw_result;
580   }
581
582   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
583                                    bool result) OVERRIDE {
584     ++did_swaps_;
585     EXPECT_TRUE(result);
586     LayerImpl* root = host_impl->active_tree()->root_layer();
587     LayerImpl* scroll_clip_layer = root->children()[0];
588     LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
589     switch (did_swaps_) {
590       case 1:
591         // Scroll on the thread.  This should damage the scrollbar for the
592         // next draw on the thread.
593         scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
594         host_impl->SetNeedsRedraw();
595         break;
596       case 2:
597         // Forcibly send the scroll to the main thread.
598         PostSetNeedsCommitToMainThread();
599         break;
600       case 3:
601         // First swap after second commit.
602         EndTest();
603         break;
604       default:
605         NOTREACHED();
606         break;
607     }
608   }
609
610   virtual void AfterTest() OVERRIDE {
611     EXPECT_EQ(3, did_swaps_);
612   }
613
614   int did_swaps_;
615 };
616
617 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarCommitDoesNoDamage);
618
619 class LayerTreeHostDamageTestVisibleTilesStillTriggerDraws
620     : public LayerTreeHostDamageTest {
621
622   virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
623     settings->impl_side_painting = true;
624   }
625
626   virtual void BeginTest() OVERRIDE {
627     PostSetNeedsCommitToMainThread();
628   }
629
630   virtual void SetupTree() OVERRIDE {
631     scoped_refptr<FakePictureLayer> root = FakePictureLayer::Create(&client_);
632     root->SetBounds(gfx::Size(500, 500));
633     layer_tree_host()->SetRootLayer(root);
634     LayerTreeHostDamageTest::SetupTree();
635
636     swap_count_ = 0;
637     prepare_to_draw_count_ = 0;
638     update_visible_tile_count_ = 0;
639   }
640
641   virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
642       LayerTreeHostImpl* host_impl,
643       LayerTreeHostImpl::FrameData* frame_data,
644       DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
645     EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
646     prepare_to_draw_count_++;
647     switch (prepare_to_draw_count_) {
648       case 1:
649         // Detect that we have an incomplete tile, during the first frame.
650         // The first frame should have damage.
651         frame_data->contains_incomplete_tile = true;
652         DCHECK(!frame_data->has_no_damage);
653         break;
654       case 2:
655         // Make a no-damage frame. We early out and can't detect
656         // incomplete tiles, even if they still exist.
657         frame_data->contains_incomplete_tile = false;
658         frame_data->has_no_damage = true;
659         break;
660       case 3:
661         // Trigger the last swap for the completed tile.
662         frame_data->contains_incomplete_tile = false;
663         frame_data->has_no_damage = false;
664         EndTest();
665         break;
666       default:
667         NOTREACHED();
668         break;
669     }
670
671     return draw_result;
672   }
673
674   virtual void UpdateVisibleTilesOnThread(
675       LayerTreeHostImpl* host_impl) OVERRIDE {
676     // Simulate creating some visible tiles (that trigger prepare-to-draws).
677     // The first we make into a no-damage-frame during prepare-to-draw (see
678     // above). This is to ensure we still get UpdateVisibleTiles calls after
679     // a no-damage or aborted frame.
680     update_visible_tile_count_++;
681     switch (update_visible_tile_count_) {
682       case 3:
683       case 6:
684         host_impl->DidInitializeVisibleTileForTesting();
685         break;
686       case 7:
687         NOTREACHED();
688         break;
689     }
690   }
691
692   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
693                                    bool didSwap) OVERRIDE {
694     if (!didSwap)
695       return;
696     ++swap_count_;
697   }
698
699   virtual void AfterTest() OVERRIDE {
700     // We should keep getting update-visible-tiles calls
701     // until we report there are no more incomplete-tiles.
702     EXPECT_EQ(update_visible_tile_count_, 6);
703     // First frame, plus two triggered by DidInitializeVisibleTile()
704     EXPECT_EQ(prepare_to_draw_count_, 3);
705     // First swap, plus final swap (contained damage).
706     EXPECT_EQ(swap_count_, 2);
707   }
708
709   FakeContentLayerClient client_;
710   int swap_count_;
711   int prepare_to_draw_count_;
712   int update_visible_tile_count_;
713 };
714
715 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestVisibleTilesStillTriggerDraws);
716
717 }  // namespace
718 }  // namespace cc