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,bool result)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 AfterTest()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 { SetupTree()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 BeginTest()99 virtual void BeginTest() OVERRIDE { 100 draw_count_ = 0; 101 PostSetNeedsCommitToMainThread(); 102 } 103 DidCommitAndDrawFrame()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 PrepareToDrawOnThread(LayerTreeHostImpl * impl,LayerTreeHostImpl::FrameData * frame_data,bool result)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 AfterTest()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 { BeginTest()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 SetupTree()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 PrepareToDrawOnThread(LayerTreeHostImpl * host_impl,LayerTreeHostImpl::FrameData * frame_data,bool result)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 SwapBuffersOnThread(LayerTreeHostImpl * host_impl,bool result)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 DidCommit()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 AfterTest()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 { BeginTest()242 virtual void BeginTest() OVERRIDE { 243 PostSetNeedsCommitToMainThread(); 244 } 245 SetupTree()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 PrepareToDrawOnThread(LayerTreeHostImpl * host_impl,LayerTreeHostImpl::FrameData * frame_data,bool result)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 DidCommitAndDrawFrame()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 AfterTest()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 { BeginTest()312 virtual void BeginTest() OVERRIDE { 313 PostSetNeedsCommitToMainThread(); 314 } 315 SetupTree()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 PrepareToDrawOnThread(LayerTreeHostImpl * host_impl,LayerTreeHostImpl::FrameData * frame_data,bool result)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 DidCommitAndDrawFrame()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 AfterTest()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 { SetupTree()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 { BeginTest()459 virtual void BeginTest() OVERRIDE { 460 did_swaps_ = 0; 461 PostSetNeedsCommitToMainThread(); 462 } 463 PrepareToDrawOnThread(LayerTreeHostImpl * host_impl,LayerTreeHostImpl::FrameData * frame_data,bool result)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 SwapBuffersOnThread(LayerTreeHostImpl * host_impl,bool result)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 AfterTest()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 { BeginTest()530 virtual void BeginTest() OVERRIDE { 531 did_swaps_ = 0; 532 PostSetNeedsCommitToMainThread(); 533 } 534 PrepareToDrawOnThread(LayerTreeHostImpl * host_impl,LayerTreeHostImpl::FrameData * frame_data,bool result)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 SwapBuffersOnThread(LayerTreeHostImpl * host_impl,bool result)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 AfterTest()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 InitializeSettings(LayerTreeSettings * settings)606 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE { 607 settings->impl_side_painting = true; 608 } 609 BeginTest()610 virtual void BeginTest() OVERRIDE { 611 PostSetNeedsCommitToMainThread(); 612 } 613 SetupTree()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 PrepareToDrawOnThread(LayerTreeHostImpl * host_impl,LayerTreeHostImpl::FrameData * frame_data,bool result)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 UpdateVisibleTilesOnThread(LayerTreeHostImpl * host_impl)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 SwapBuffersOnThread(LayerTreeHostImpl * host_impl,bool didSwap)675 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, 676 bool didSwap) OVERRIDE { 677 if (!didSwap) 678 return; 679 ++swap_count_; 680 } 681 AfterTest()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 702