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