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