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