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/basictypes.h" 8 #include "cc/layers/content_layer.h" 9 #include "cc/layers/heads_up_display_layer.h" 10 #include "cc/layers/io_surface_layer.h" 11 #include "cc/layers/layer_impl.h" 12 #include "cc/layers/picture_layer.h" 13 #include "cc/layers/scrollbar_layer.h" 14 #include "cc/layers/texture_layer.h" 15 #include "cc/layers/texture_layer_impl.h" 16 #include "cc/layers/video_layer.h" 17 #include "cc/layers/video_layer_impl.h" 18 #include "cc/output/filter_operations.h" 19 #include "cc/test/fake_content_layer.h" 20 #include "cc/test/fake_content_layer_client.h" 21 #include "cc/test/fake_content_layer_impl.h" 22 #include "cc/test/fake_context_provider.h" 23 #include "cc/test/fake_delegated_renderer_layer.h" 24 #include "cc/test/fake_delegated_renderer_layer_impl.h" 25 #include "cc/test/fake_layer_tree_host_client.h" 26 #include "cc/test/fake_output_surface.h" 27 #include "cc/test/fake_scoped_ui_resource.h" 28 #include "cc/test/fake_scrollbar.h" 29 #include "cc/test/fake_scrollbar_layer.h" 30 #include "cc/test/fake_video_frame_provider.h" 31 #include "cc/test/layer_tree_test.h" 32 #include "cc/test/render_pass_test_common.h" 33 #include "cc/test/test_web_graphics_context_3d.h" 34 #include "cc/trees/layer_tree_host_impl.h" 35 #include "cc/trees/layer_tree_impl.h" 36 #include "cc/trees/single_thread_proxy.h" 37 #include "gpu/GLES2/gl2extchromium.h" 38 #include "media/base/media.h" 39 40 using media::VideoFrame; 41 using WebKit::WebGraphicsContext3D; 42 43 namespace cc { 44 namespace { 45 46 // These tests deal with losing the 3d graphics context. 47 class LayerTreeHostContextTest : public LayerTreeTest { 48 public: 49 LayerTreeHostContextTest() 50 : LayerTreeTest(), 51 context3d_(NULL), 52 times_to_fail_create_(0), 53 times_to_fail_initialize_(0), 54 times_to_lose_on_create_(0), 55 times_to_lose_during_commit_(0), 56 times_to_lose_during_draw_(0), 57 times_to_fail_recreate_(0), 58 times_to_fail_reinitialize_(0), 59 times_to_lose_on_recreate_(0), 60 times_to_fail_create_offscreen_(0), 61 times_to_fail_recreate_offscreen_(0), 62 times_to_expect_create_failed_(0), 63 times_create_failed_(0), 64 times_offscreen_created_(0), 65 committed_at_least_once_(false), 66 context_should_support_io_surface_(false), 67 fallback_context_works_(false) { 68 media::InitializeMediaLibraryForTesting(); 69 } 70 71 void LoseContext() { 72 context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB, 73 GL_INNOCENT_CONTEXT_RESET_ARB); 74 context3d_ = NULL; 75 } 76 77 virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() { 78 return TestWebGraphicsContext3D::Create(); 79 } 80 81 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback) 82 OVERRIDE { 83 if (times_to_fail_create_) { 84 --times_to_fail_create_; 85 ExpectCreateToFail(); 86 return scoped_ptr<OutputSurface>(); 87 } 88 89 scoped_ptr<TestWebGraphicsContext3D> context3d = CreateContext3d(); 90 context3d_ = context3d.get(); 91 92 if (context_should_support_io_surface_) { 93 context3d_->set_have_extension_io_surface(true); 94 context3d_->set_have_extension_egl_image(true); 95 } 96 97 if (times_to_fail_initialize_ && !(fallback && fallback_context_works_)) { 98 --times_to_fail_initialize_; 99 // Make the context get lost during reinitialization. 100 // The number of times MakeCurrent succeeds is not important, and 101 // can be changed if needed to make this pass with future changes. 102 context3d_->set_times_make_current_succeeds(2); 103 ExpectCreateToFail(); 104 } else if (times_to_lose_on_create_) { 105 --times_to_lose_on_create_; 106 LoseContext(); 107 ExpectCreateToFail(); 108 } 109 110 if (delegating_renderer()) { 111 return FakeOutputSurface::CreateDelegating3d( 112 context3d.PassAs<WebGraphicsContext3D>()).PassAs<OutputSurface>(); 113 } 114 return FakeOutputSurface::Create3d( 115 context3d.PassAs<WebGraphicsContext3D>()).PassAs<OutputSurface>(); 116 } 117 118 scoped_ptr<TestWebGraphicsContext3D> CreateOffscreenContext3d() { 119 if (!context3d_) 120 return scoped_ptr<TestWebGraphicsContext3D>(); 121 122 ++times_offscreen_created_; 123 124 if (times_to_fail_create_offscreen_) { 125 --times_to_fail_create_offscreen_; 126 ExpectCreateToFail(); 127 return scoped_ptr<TestWebGraphicsContext3D>(); 128 } 129 130 scoped_ptr<TestWebGraphicsContext3D> offscreen_context3d = 131 TestWebGraphicsContext3D::Create().Pass(); 132 DCHECK(offscreen_context3d); 133 context3d_->add_share_group_context(offscreen_context3d.get()); 134 135 return offscreen_context3d.Pass(); 136 } 137 138 virtual scoped_refptr<cc::ContextProvider> 139 OffscreenContextProviderForMainThread() OVERRIDE { 140 DCHECK(!HasImplThread()); 141 142 if (!offscreen_contexts_main_thread_.get() || 143 offscreen_contexts_main_thread_->DestroyedOnMainThread()) { 144 offscreen_contexts_main_thread_ = FakeContextProvider::Create( 145 base::Bind(&LayerTreeHostContextTest::CreateOffscreenContext3d, 146 base::Unretained(this))); 147 if (offscreen_contexts_main_thread_.get() && 148 !offscreen_contexts_main_thread_->BindToCurrentThread()) 149 offscreen_contexts_main_thread_ = NULL; 150 } 151 return offscreen_contexts_main_thread_; 152 } 153 154 virtual scoped_refptr<cc::ContextProvider> 155 OffscreenContextProviderForCompositorThread() OVERRIDE { 156 DCHECK(HasImplThread()); 157 158 if (!offscreen_contexts_compositor_thread_.get() || 159 offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) { 160 offscreen_contexts_compositor_thread_ = FakeContextProvider::Create( 161 base::Bind(&LayerTreeHostContextTest::CreateOffscreenContext3d, 162 base::Unretained(this))); 163 } 164 return offscreen_contexts_compositor_thread_; 165 } 166 167 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, 168 LayerTreeHostImpl::FrameData* frame, 169 bool result) OVERRIDE { 170 EXPECT_TRUE(result); 171 if (!times_to_lose_during_draw_) 172 return result; 173 174 --times_to_lose_during_draw_; 175 context3d_->set_times_make_current_succeeds(0); 176 177 times_to_fail_create_ = times_to_fail_recreate_; 178 times_to_fail_recreate_ = 0; 179 times_to_fail_initialize_ = times_to_fail_reinitialize_; 180 times_to_fail_reinitialize_ = 0; 181 times_to_lose_on_create_ = times_to_lose_on_recreate_; 182 times_to_lose_on_recreate_ = 0; 183 times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_; 184 times_to_fail_recreate_offscreen_ = 0; 185 186 return result; 187 } 188 189 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { 190 committed_at_least_once_ = true; 191 192 if (!times_to_lose_during_commit_) 193 return; 194 --times_to_lose_during_commit_; 195 LoseContext(); 196 197 times_to_fail_create_ = times_to_fail_recreate_; 198 times_to_fail_recreate_ = 0; 199 times_to_fail_initialize_ = times_to_fail_reinitialize_; 200 times_to_fail_reinitialize_ = 0; 201 times_to_lose_on_create_ = times_to_lose_on_recreate_; 202 times_to_lose_on_recreate_ = 0; 203 times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_; 204 times_to_fail_recreate_offscreen_ = 0; 205 } 206 207 virtual void DidFailToInitializeOutputSurface() OVERRIDE { 208 ++times_create_failed_; 209 } 210 211 virtual void TearDown() OVERRIDE { 212 LayerTreeTest::TearDown(); 213 EXPECT_EQ(times_to_expect_create_failed_, times_create_failed_); 214 } 215 216 void ExpectCreateToFail() { 217 ++times_to_expect_create_failed_; 218 } 219 220 protected: 221 TestWebGraphicsContext3D* context3d_; 222 int times_to_fail_create_; 223 int times_to_fail_initialize_; 224 int times_to_lose_on_create_; 225 int times_to_lose_during_commit_; 226 int times_to_lose_during_draw_; 227 int times_to_fail_recreate_; 228 int times_to_fail_reinitialize_; 229 int times_to_lose_on_recreate_; 230 int times_to_fail_create_offscreen_; 231 int times_to_fail_recreate_offscreen_; 232 int times_to_expect_create_failed_; 233 int times_create_failed_; 234 int times_offscreen_created_; 235 bool committed_at_least_once_; 236 bool context_should_support_io_surface_; 237 bool fallback_context_works_; 238 239 scoped_refptr<FakeContextProvider> offscreen_contexts_main_thread_; 240 scoped_refptr<FakeContextProvider> offscreen_contexts_compositor_thread_; 241 }; 242 243 class LayerTreeHostContextTestLostContextSucceeds 244 : public LayerTreeHostContextTest { 245 public: 246 LayerTreeHostContextTestLostContextSucceeds() 247 : LayerTreeHostContextTest(), 248 test_case_(0), 249 num_losses_(0), 250 recovered_context_(true), 251 first_initialized_(false) {} 252 253 virtual void BeginTest() OVERRIDE { 254 PostSetNeedsCommitToMainThread(); 255 } 256 257 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE { 258 EXPECT_TRUE(succeeded); 259 260 if (first_initialized_) 261 ++num_losses_; 262 else 263 first_initialized_ = true; 264 265 recovered_context_ = true; 266 } 267 268 virtual void AfterTest() OVERRIDE { 269 EXPECT_EQ(11u, test_case_); 270 EXPECT_EQ(8 + 10 + 10 + 1, num_losses_); 271 } 272 273 virtual void DidCommitAndDrawFrame() OVERRIDE { 274 // If the last frame had a context loss, then we'll commit again to 275 // recover. 276 if (!recovered_context_) 277 return; 278 if (times_to_lose_during_commit_) 279 return; 280 if (times_to_lose_during_draw_) 281 return; 282 283 recovered_context_ = false; 284 if (NextTestCase()) 285 InvalidateAndSetNeedsCommit(); 286 else 287 EndTest(); 288 } 289 290 virtual void InvalidateAndSetNeedsCommit() { 291 // Cause damage so we try to draw. 292 layer_tree_host()->root_layer()->SetNeedsDisplay(); 293 layer_tree_host()->SetNeedsCommit(); 294 } 295 296 bool NextTestCase() { 297 static const TestCase kTests[] = { 298 // Losing the context and failing to recreate it (or losing it again 299 // immediately) a small number of times should succeed. 300 { 1, // times_to_lose_during_commit 301 0, // times_to_lose_during_draw 302 3, // times_to_fail_reinitialize 303 0, // times_to_fail_recreate 304 0, // times_to_lose_on_recreate 305 0, // times_to_fail_recreate_offscreen 306 false, // fallback_context_works 307 }, 308 { 0, // times_to_lose_during_commit 309 1, // times_to_lose_during_draw 310 3, // times_to_fail_reinitialize 311 0, // times_to_fail_recreate 312 0, // times_to_lose_on_recreate 313 0, // times_to_fail_recreate_offscreen 314 false, // fallback_context_works 315 }, 316 { 1, // times_to_lose_during_commit 317 0, // times_to_lose_during_draw 318 0, // times_to_fail_reinitialize 319 3, // times_to_fail_recreate 320 0, // times_to_lose_on_recreate 321 0, // times_to_fail_recreate_offscreen 322 false, // fallback_context_works 323 }, 324 { 0, // times_to_lose_during_commit 325 1, // times_to_lose_during_draw 326 0, // times_to_fail_reinitialize 327 3, // times_to_fail_recreate 328 0, // times_to_lose_on_recreate 329 0, // times_to_fail_recreate_offscreen 330 false, // fallback_context_works 331 }, 332 { 1, // times_to_lose_during_commit 333 0, // times_to_lose_during_draw 334 0, // times_to_fail_reinitialize 335 0, // times_to_fail_recreate 336 3, // times_to_lose_on_recreate 337 0, // times_to_fail_recreate_offscreen 338 false, // fallback_context_works 339 }, 340 { 0, // times_to_lose_during_commit 341 1, // times_to_lose_during_draw 342 0, // times_to_fail_reinitialize 343 0, // times_to_fail_recreate 344 3, // times_to_lose_on_recreate 345 0, // times_to_fail_recreate_offscreen 346 false, // fallback_context_works 347 }, 348 { 1, // times_to_lose_during_commit 349 0, // times_to_lose_during_draw 350 0, // times_to_fail_reinitialize 351 0, // times_to_fail_recreate 352 0, // times_to_lose_on_recreate 353 3, // times_to_fail_recreate_offscreen 354 false, // fallback_context_works 355 }, 356 { 0, // times_to_lose_during_commit 357 1, // times_to_lose_during_draw 358 0, // times_to_fail_reinitialize 359 0, // times_to_fail_recreate 360 0, // times_to_lose_on_recreate 361 3, // times_to_fail_recreate_offscreen 362 false, // fallback_context_works 363 }, 364 // Losing the context and recreating it any number of times should 365 // succeed. 366 { 10, // times_to_lose_during_commit 367 0, // times_to_lose_during_draw 368 0, // times_to_fail_reinitialize 369 0, // times_to_fail_recreate 370 0, // times_to_lose_on_recreate 371 0, // times_to_fail_recreate_offscreen 372 false, // fallback_context_works 373 }, 374 { 0, // times_to_lose_during_commit 375 10, // times_to_lose_during_draw 376 0, // times_to_fail_reinitialize 377 0, // times_to_fail_recreate 378 0, // times_to_lose_on_recreate 379 0, // times_to_fail_recreate_offscreen 380 false, // fallback_context_works 381 }, 382 // Losing the context, failing to reinitialize it, and making a fallback 383 // context should work. 384 { 0, // times_to_lose_during_commit 385 1, // times_to_lose_during_draw 386 10, // times_to_fail_reinitialize 387 0, // times_to_fail_recreate 388 0, // times_to_lose_on_recreate 389 0, // times_to_fail_recreate_offscreen 390 true, // fallback_context_works 391 }, 392 }; 393 394 if (test_case_ >= arraysize(kTests)) 395 return false; 396 397 times_to_lose_during_commit_ = 398 kTests[test_case_].times_to_lose_during_commit; 399 times_to_lose_during_draw_ = 400 kTests[test_case_].times_to_lose_during_draw; 401 times_to_fail_reinitialize_ = kTests[test_case_].times_to_fail_reinitialize; 402 times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate; 403 times_to_lose_on_recreate_ = kTests[test_case_].times_to_lose_on_recreate; 404 times_to_fail_recreate_offscreen_ = 405 kTests[test_case_].times_to_fail_recreate_offscreen; 406 fallback_context_works_ = kTests[test_case_].fallback_context_works; 407 ++test_case_; 408 return true; 409 } 410 411 struct TestCase { 412 int times_to_lose_during_commit; 413 int times_to_lose_during_draw; 414 int times_to_fail_reinitialize; 415 int times_to_fail_recreate; 416 int times_to_lose_on_recreate; 417 int times_to_fail_recreate_offscreen; 418 bool fallback_context_works; 419 }; 420 421 protected: 422 size_t test_case_; 423 int num_losses_; 424 bool recovered_context_; 425 bool first_initialized_; 426 }; 427 428 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds); 429 430 class LayerTreeHostContextTestLostContextSucceedsWithContent 431 : public LayerTreeHostContextTestLostContextSucceeds { 432 public: 433 LayerTreeHostContextTestLostContextSucceedsWithContent() 434 : LayerTreeHostContextTestLostContextSucceeds() {} 435 436 virtual void SetupTree() OVERRIDE { 437 root_ = Layer::Create(); 438 root_->SetBounds(gfx::Size(10, 10)); 439 root_->SetAnchorPoint(gfx::PointF()); 440 root_->SetIsDrawable(true); 441 442 content_ = FakeContentLayer::Create(&client_); 443 content_->SetBounds(gfx::Size(10, 10)); 444 content_->SetAnchorPoint(gfx::PointF()); 445 content_->SetIsDrawable(true); 446 if (use_surface_) { 447 content_->SetForceRenderSurface(true); 448 // Filters require us to create an offscreen context. 449 FilterOperations filters; 450 filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f)); 451 content_->SetFilters(filters); 452 content_->SetBackgroundFilters(filters); 453 } 454 455 root_->AddChild(content_); 456 457 layer_tree_host()->SetRootLayer(root_); 458 LayerTreeHostContextTest::SetupTree(); 459 } 460 461 virtual void InvalidateAndSetNeedsCommit() OVERRIDE { 462 // Invalidate the render surface so we don't try to use a cached copy of the 463 // surface. We want to make sure to test the drawing paths for drawing to 464 // a child surface. 465 content_->SetNeedsDisplay(); 466 LayerTreeHostContextTestLostContextSucceeds::InvalidateAndSetNeedsCommit(); 467 } 468 469 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { 470 FakeContentLayerImpl* content_impl = static_cast<FakeContentLayerImpl*>( 471 host_impl->active_tree()->root_layer()->children()[0]); 472 // Even though the context was lost, we should have a resource. The 473 // TestWebGraphicsContext3D ensures that this resource is created with 474 // the active context. 475 EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0)); 476 477 cc::ContextProvider* contexts = 478 host_impl->resource_provider()->offscreen_context_provider(); 479 if (use_surface_) { 480 EXPECT_TRUE(contexts->Context3d()); 481 // TODO(danakj): Make a fake GrContext. 482 // EXPECT_TRUE(contexts->GrContext()); 483 } else { 484 EXPECT_FALSE(contexts); 485 } 486 } 487 488 virtual void AfterTest() OVERRIDE { 489 LayerTreeHostContextTestLostContextSucceeds::AfterTest(); 490 if (use_surface_) { 491 // 1 create to start with + 492 // 6 from test cases that fail on initializing the renderer (after the 493 // offscreen context is created) + 494 // 6 from test cases that lose the offscreen context directly + 495 // 4 from test cases that create a fallback + 496 // All the test cases that recreate both contexts only once 497 // per time it is lost. 498 EXPECT_EQ(6 + 6 + 1 + 4 + num_losses_, times_offscreen_created_); 499 } else { 500 EXPECT_EQ(0, times_offscreen_created_); 501 } 502 } 503 504 protected: 505 bool use_surface_; 506 FakeContentLayerClient client_; 507 scoped_refptr<Layer> root_; 508 scoped_refptr<ContentLayer> content_; 509 }; 510 511 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent, 512 NoSurface_SingleThread_DirectRenderer) { 513 use_surface_ = false; 514 RunTest(false, false, false); 515 } 516 517 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent, 518 NoSurface_SingleThread_DelegatingRenderer) { 519 use_surface_ = false; 520 RunTest(false, true, false); 521 } 522 523 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent, 524 NoSurface_MultiThread_DirectRenderer_MainThreadPaint) { 525 use_surface_ = false; 526 RunTest(true, false, false); 527 } 528 529 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent, 530 NoSurface_MultiThread_DirectRenderer_ImplSidePaint) { 531 use_surface_ = false; 532 RunTest(true, false, true); 533 } 534 535 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent, 536 NoSurface_MultiThread_DelegatingRenderer_MainThreadPaint) { 537 use_surface_ = false; 538 RunTest(true, true, false); 539 } 540 541 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent, 542 NoSurface_MultiThread_DelegatingRenderer_ImplSidePaint) { 543 use_surface_ = false; 544 RunTest(true, true, true); 545 } 546 547 // Surfaces don't exist with a delegating renderer. 548 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent, 549 WithSurface_SingleThread_DirectRenderer) { 550 use_surface_ = true; 551 RunTest(false, false, false); 552 } 553 554 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent, 555 WithSurface_MultiThread_DirectRenderer_MainThreadPaint) { 556 use_surface_ = true; 557 RunTest(true, false, false); 558 } 559 560 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent, 561 WithSurface_MultiThread_DirectRenderer_ImplSidePaint) { 562 use_surface_ = true; 563 RunTest(true, false, true); 564 } 565 566 class LayerTreeHostContextTestOffscreenContextFails 567 : public LayerTreeHostContextTest { 568 public: 569 virtual void SetupTree() OVERRIDE { 570 root_ = Layer::Create(); 571 root_->SetBounds(gfx::Size(10, 10)); 572 root_->SetAnchorPoint(gfx::PointF()); 573 root_->SetIsDrawable(true); 574 575 content_ = FakeContentLayer::Create(&client_); 576 content_->SetBounds(gfx::Size(10, 10)); 577 content_->SetAnchorPoint(gfx::PointF()); 578 content_->SetIsDrawable(true); 579 content_->SetForceRenderSurface(true); 580 // Filters require us to create an offscreen context. 581 FilterOperations filters; 582 filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f)); 583 content_->SetFilters(filters); 584 content_->SetBackgroundFilters(filters); 585 586 root_->AddChild(content_); 587 588 layer_tree_host()->SetRootLayer(root_); 589 LayerTreeHostContextTest::SetupTree(); 590 } 591 592 virtual void BeginTest() OVERRIDE { 593 times_to_fail_create_offscreen_ = 1; 594 PostSetNeedsCommitToMainThread(); 595 } 596 597 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { 598 cc::ContextProvider* contexts = 599 host_impl->resource_provider()->offscreen_context_provider(); 600 EXPECT_FALSE(contexts); 601 602 // This did not lead to create failure. 603 times_to_expect_create_failed_ = 0; 604 EndTest(); 605 } 606 607 virtual void AfterTest() OVERRIDE {} 608 609 protected: 610 FakeContentLayerClient client_; 611 scoped_refptr<Layer> root_; 612 scoped_refptr<ContentLayer> content_; 613 }; 614 615 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestOffscreenContextFails); 616 617 class LayerTreeHostContextTestLostContextFails 618 : public LayerTreeHostContextTest { 619 public: 620 LayerTreeHostContextTestLostContextFails() 621 : LayerTreeHostContextTest(), 622 num_commits_(0), 623 first_initialized_(false) { 624 times_to_lose_during_commit_ = 1; 625 } 626 627 virtual void BeginTest() OVERRIDE { 628 PostSetNeedsCommitToMainThread(); 629 } 630 631 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE { 632 if (first_initialized_) { 633 EXPECT_FALSE(succeeded); 634 EndTest(); 635 } else { 636 first_initialized_ = true; 637 } 638 } 639 640 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { 641 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl); 642 643 ++num_commits_; 644 if (num_commits_ == 1) { 645 // When the context is ok, we should have these things. 646 EXPECT_TRUE(host_impl->output_surface()); 647 EXPECT_TRUE(host_impl->renderer()); 648 EXPECT_TRUE(host_impl->resource_provider()); 649 return; 650 } 651 652 // When context recreation fails we shouldn't be left with any of them. 653 EXPECT_FALSE(host_impl->output_surface()); 654 EXPECT_FALSE(host_impl->renderer()); 655 EXPECT_FALSE(host_impl->resource_provider()); 656 } 657 658 virtual void AfterTest() OVERRIDE {} 659 660 private: 661 int num_commits_; 662 bool first_initialized_; 663 }; 664 665 TEST_F(LayerTreeHostContextTestLostContextFails, 666 FailReinitialize100_SingleThread_DirectRenderer) { 667 times_to_fail_reinitialize_ = 100; 668 times_to_fail_recreate_ = 0; 669 times_to_lose_on_recreate_ = 0; 670 RunTest(false, false, false); 671 } 672 673 TEST_F(LayerTreeHostContextTestLostContextFails, 674 FailReinitialize100_SingleThread_DelegatingRenderer) { 675 times_to_fail_reinitialize_ = 100; 676 times_to_fail_recreate_ = 0; 677 times_to_lose_on_recreate_ = 0; 678 RunTest(false, true, false); 679 } 680 681 TEST_F(LayerTreeHostContextTestLostContextFails, 682 FailReinitialize100_MultiThread_DirectRenderer_MainThreadPaint) { 683 times_to_fail_reinitialize_ = 100; 684 times_to_fail_recreate_ = 0; 685 times_to_lose_on_recreate_ = 0; 686 RunTest(true, false, false); 687 } 688 689 TEST_F(LayerTreeHostContextTestLostContextFails, 690 FailReinitialize100_MultiThread_DirectRenderer_ImplSidePaint) { 691 times_to_fail_reinitialize_ = 100; 692 times_to_fail_recreate_ = 0; 693 times_to_lose_on_recreate_ = 0; 694 RunTest(true, false, true); 695 } 696 697 TEST_F(LayerTreeHostContextTestLostContextFails, 698 FailReinitialize100_MultiThread_DelegatingRenderer_MainThreadPaint) { 699 times_to_fail_reinitialize_ = 100; 700 times_to_fail_recreate_ = 0; 701 times_to_lose_on_recreate_ = 0; 702 RunTest(true, true, false); 703 } 704 705 TEST_F(LayerTreeHostContextTestLostContextFails, 706 FailReinitialize100_MultiThread_DelegatingRenderer_ImplSidePaint) { 707 times_to_fail_reinitialize_ = 100; 708 times_to_fail_recreate_ = 0; 709 times_to_lose_on_recreate_ = 0; 710 RunTest(true, true, true); 711 } 712 713 TEST_F(LayerTreeHostContextTestLostContextFails, 714 FailRecreate100_SingleThread_DirectRenderer) { 715 times_to_fail_reinitialize_ = 0; 716 times_to_fail_recreate_ = 100; 717 times_to_lose_on_recreate_ = 0; 718 RunTest(false, false, false); 719 } 720 721 TEST_F(LayerTreeHostContextTestLostContextFails, 722 FailRecreate100_SingleThread_DelegatingRenderer) { 723 times_to_fail_reinitialize_ = 0; 724 times_to_fail_recreate_ = 100; 725 times_to_lose_on_recreate_ = 0; 726 RunTest(false, true, false); 727 } 728 729 TEST_F(LayerTreeHostContextTestLostContextFails, 730 FailRecreate100_MultiThread_DirectRenderer_MainThreadPaint) { 731 times_to_fail_reinitialize_ = 0; 732 times_to_fail_recreate_ = 100; 733 times_to_lose_on_recreate_ = 0; 734 RunTest(true, false, false); 735 } 736 737 TEST_F(LayerTreeHostContextTestLostContextFails, 738 FailRecreate100_MultiThread_DirectRenderer_ImplSidePaint) { 739 times_to_fail_reinitialize_ = 0; 740 times_to_fail_recreate_ = 100; 741 times_to_lose_on_recreate_ = 0; 742 RunTest(true, false, true); 743 } 744 745 TEST_F(LayerTreeHostContextTestLostContextFails, 746 FailRecreate100_MultiThread_DelegatingRenderer_MainThreadPaint) { 747 times_to_fail_reinitialize_ = 0; 748 times_to_fail_recreate_ = 100; 749 times_to_lose_on_recreate_ = 0; 750 RunTest(true, true, false); 751 } 752 753 TEST_F(LayerTreeHostContextTestLostContextFails, 754 FailRecreate100_MultiThread_DelegatingRenderer_ImplSidePaint) { 755 times_to_fail_reinitialize_ = 0; 756 times_to_fail_recreate_ = 100; 757 times_to_lose_on_recreate_ = 0; 758 RunTest(true, true, true); 759 } 760 761 TEST_F(LayerTreeHostContextTestLostContextFails, 762 LoseOnRecreate100_SingleThread_DirectRenderer) { 763 times_to_fail_reinitialize_ = 0; 764 times_to_fail_recreate_ = 0; 765 times_to_lose_on_recreate_ = 100; 766 RunTest(false, false, false); 767 } 768 769 TEST_F(LayerTreeHostContextTestLostContextFails, 770 LoseOnRecreate100_SingleThread_DelegatingRenderer) { 771 times_to_fail_reinitialize_ = 0; 772 times_to_fail_recreate_ = 0; 773 times_to_lose_on_recreate_ = 100; 774 RunTest(false, true, false); 775 } 776 777 TEST_F(LayerTreeHostContextTestLostContextFails, 778 LoseOnRecreate100_MultiThread_DirectRenderer_MainThreadPaint) { 779 times_to_fail_reinitialize_ = 0; 780 times_to_fail_recreate_ = 0; 781 times_to_lose_on_recreate_ = 100; 782 RunTest(true, false, false); 783 } 784 785 TEST_F(LayerTreeHostContextTestLostContextFails, 786 LoseOnRecreate100_MultiThread_DirectRenderer_ImplSidePaint) { 787 times_to_fail_reinitialize_ = 0; 788 times_to_fail_recreate_ = 0; 789 times_to_lose_on_recreate_ = 100; 790 RunTest(true, false, true); 791 } 792 793 TEST_F(LayerTreeHostContextTestLostContextFails, 794 LoseOnRecreate100_MultiThread_DelegatingRenderer_MainThreadPaint) { 795 times_to_fail_reinitialize_ = 0; 796 times_to_fail_recreate_ = 0; 797 times_to_lose_on_recreate_ = 100; 798 RunTest(true, true, false); 799 } 800 801 TEST_F(LayerTreeHostContextTestLostContextFails, 802 LoseOnRecreate100_MultiThread_DelegatingRenderer_ImplSidePaint) { 803 times_to_fail_reinitialize_ = 0; 804 times_to_fail_recreate_ = 0; 805 times_to_lose_on_recreate_ = 100; 806 RunTest(true, true, true); 807 } 808 809 class LayerTreeHostContextTestFinishAllRenderingAfterLoss 810 : public LayerTreeHostContextTest { 811 public: 812 virtual void BeginTest() OVERRIDE { 813 // Lose the context until the compositor gives up on it. 814 first_initialized_ = false; 815 times_to_lose_during_commit_ = 1; 816 times_to_fail_reinitialize_ = 10; 817 PostSetNeedsCommitToMainThread(); 818 } 819 820 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE { 821 if (first_initialized_) { 822 EXPECT_FALSE(succeeded); 823 layer_tree_host()->FinishAllRendering(); 824 EndTest(); 825 } else { 826 first_initialized_ = true; 827 } 828 } 829 830 virtual void AfterTest() OVERRIDE {} 831 832 private: 833 bool first_initialized_; 834 }; 835 836 SINGLE_AND_MULTI_THREAD_TEST_F( 837 LayerTreeHostContextTestFinishAllRenderingAfterLoss); 838 839 class LayerTreeHostContextTestLostContextAndEvictTextures 840 : public LayerTreeHostContextTest { 841 public: 842 LayerTreeHostContextTestLostContextAndEvictTextures() 843 : LayerTreeHostContextTest(), 844 layer_(FakeContentLayer::Create(&client_)), 845 impl_host_(0), 846 num_commits_(0) {} 847 848 virtual void SetupTree() OVERRIDE { 849 layer_->SetBounds(gfx::Size(10, 20)); 850 layer_tree_host()->SetRootLayer(layer_); 851 LayerTreeHostContextTest::SetupTree(); 852 } 853 854 virtual void BeginTest() OVERRIDE { 855 PostSetNeedsCommitToMainThread(); 856 } 857 858 void PostEvictTextures() { 859 if (HasImplThread()) { 860 ImplThreadTaskRunner()->PostTask( 861 FROM_HERE, 862 base::Bind( 863 &LayerTreeHostContextTestLostContextAndEvictTextures:: 864 EvictTexturesOnImplThread, 865 base::Unretained(this))); 866 } else { 867 DebugScopedSetImplThread impl(proxy()); 868 EvictTexturesOnImplThread(); 869 } 870 } 871 872 void EvictTexturesOnImplThread() { 873 impl_host_->EvictTexturesForTesting(); 874 if (lose_after_evict_) 875 LoseContext(); 876 } 877 878 virtual void DidCommitAndDrawFrame() OVERRIDE { 879 if (num_commits_ > 1) 880 return; 881 EXPECT_TRUE(layer_->HaveBackingAt(0, 0)); 882 PostEvictTextures(); 883 } 884 885 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE { 886 LayerTreeHostContextTest::CommitCompleteOnThread(impl); 887 if (num_commits_ > 1) 888 return; 889 ++num_commits_; 890 if (!lose_after_evict_) 891 LoseContext(); 892 impl_host_ = impl; 893 } 894 895 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE { 896 EXPECT_TRUE(succeeded); 897 EndTest(); 898 } 899 900 virtual void AfterTest() OVERRIDE {} 901 902 protected: 903 bool lose_after_evict_; 904 FakeContentLayerClient client_; 905 scoped_refptr<FakeContentLayer> layer_; 906 LayerTreeHostImpl* impl_host_; 907 int num_commits_; 908 }; 909 910 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, 911 LoseAfterEvict_SingleThread_DirectRenderer) { 912 lose_after_evict_ = true; 913 RunTest(false, false, false); 914 } 915 916 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, 917 LoseAfterEvict_SingleThread_DelegatingRenderer) { 918 lose_after_evict_ = true; 919 RunTest(false, true, false); 920 } 921 922 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, 923 LoseAfterEvict_MultiThread_DirectRenderer_MainThreadPaint) { 924 lose_after_evict_ = true; 925 RunTest(true, false, false); 926 } 927 928 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, 929 LoseAfterEvict_MultiThread_DirectRenderer_ImplSidePaint) { 930 lose_after_evict_ = true; 931 RunTest(true, false, true); 932 } 933 934 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, 935 LoseAfterEvict_MultiThread_DelegatingRenderer_MainThreadPaint) { 936 lose_after_evict_ = true; 937 RunTest(true, true, false); 938 } 939 940 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, 941 LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint) { 942 lose_after_evict_ = true; 943 RunTest(true, true, true); 944 } 945 946 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, 947 LoseBeforeEvict_SingleThread_DirectRenderer) { 948 lose_after_evict_ = false; 949 RunTest(false, false, false); 950 } 951 952 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, 953 LoseBeforeEvict_SingleThread_DelegatingRenderer) { 954 lose_after_evict_ = false; 955 RunTest(false, true, false); 956 } 957 958 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, 959 LoseBeforeEvict_MultiThread_DirectRenderer_MainThreadPaint) { 960 lose_after_evict_ = false; 961 RunTest(true, false, false); 962 } 963 964 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, 965 LoseBeforeEvict_MultiThread_DirectRenderer_ImplSidePaint) { 966 lose_after_evict_ = false; 967 RunTest(true, false, true); 968 } 969 970 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, 971 LoseBeforeEvict_MultiThread_DelegatingRenderer_MainThreadPaint) { 972 lose_after_evict_ = false; 973 RunTest(true, true, false); 974 } 975 976 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, 977 LoseBeforeEvict_MultiThread_DelegatingRenderer_ImplSidePaint) { 978 lose_after_evict_ = false; 979 RunTest(true, true, true); 980 } 981 982 class LayerTreeHostContextTestLostContextWhileUpdatingResources 983 : public LayerTreeHostContextTest { 984 public: 985 LayerTreeHostContextTestLostContextWhileUpdatingResources() 986 : parent_(FakeContentLayer::Create(&client_)), 987 num_children_(50), 988 times_to_lose_on_end_query_(3) {} 989 990 virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() OVERRIDE { 991 scoped_ptr<TestWebGraphicsContext3D> context = 992 LayerTreeHostContextTest::CreateContext3d(); 993 if (times_to_lose_on_end_query_) { 994 --times_to_lose_on_end_query_; 995 context->set_times_end_query_succeeds(5); 996 } 997 return context.Pass(); 998 } 999 1000 virtual void SetupTree() OVERRIDE { 1001 parent_->SetBounds(gfx::Size(num_children_, 1)); 1002 1003 for (int i = 0; i < num_children_; i++) { 1004 scoped_refptr<FakeContentLayer> child = 1005 FakeContentLayer::Create(&client_); 1006 child->SetPosition(gfx::PointF(i, 0.f)); 1007 child->SetBounds(gfx::Size(1, 1)); 1008 parent_->AddChild(child); 1009 } 1010 1011 layer_tree_host()->SetRootLayer(parent_); 1012 LayerTreeHostContextTest::SetupTree(); 1013 } 1014 1015 virtual void BeginTest() OVERRIDE { 1016 PostSetNeedsCommitToMainThread(); 1017 } 1018 1019 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE { 1020 LayerTreeHostContextTest::CommitCompleteOnThread(impl); 1021 EndTest(); 1022 } 1023 1024 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE { 1025 EXPECT_TRUE(succeeded); 1026 } 1027 1028 virtual void AfterTest() OVERRIDE { 1029 EXPECT_EQ(0, times_to_lose_on_end_query_); 1030 } 1031 1032 private: 1033 FakeContentLayerClient client_; 1034 scoped_refptr<FakeContentLayer> parent_; 1035 int num_children_; 1036 int times_to_lose_on_end_query_; 1037 }; 1038 1039 SINGLE_AND_MULTI_THREAD_TEST_F( 1040 LayerTreeHostContextTestLostContextWhileUpdatingResources); 1041 1042 class LayerTreeHostContextTestLayersNotified 1043 : public LayerTreeHostContextTest { 1044 public: 1045 LayerTreeHostContextTestLayersNotified() 1046 : LayerTreeHostContextTest(), 1047 num_commits_(0) {} 1048 1049 virtual void SetupTree() OVERRIDE { 1050 root_ = FakeContentLayer::Create(&client_); 1051 child_ = FakeContentLayer::Create(&client_); 1052 grandchild_ = FakeContentLayer::Create(&client_); 1053 1054 root_->AddChild(child_); 1055 child_->AddChild(grandchild_); 1056 1057 layer_tree_host()->SetRootLayer(root_); 1058 LayerTreeHostContextTest::SetupTree(); 1059 } 1060 1061 virtual void BeginTest() OVERRIDE { 1062 PostSetNeedsCommitToMainThread(); 1063 } 1064 1065 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { 1066 LayerTreeHostContextTest::DidActivateTreeOnThread(host_impl); 1067 1068 FakeContentLayerImpl* root = static_cast<FakeContentLayerImpl*>( 1069 host_impl->active_tree()->root_layer()); 1070 FakeContentLayerImpl* child = static_cast<FakeContentLayerImpl*>( 1071 root->children()[0]); 1072 FakeContentLayerImpl* grandchild = static_cast<FakeContentLayerImpl*>( 1073 child->children()[0]); 1074 1075 ++num_commits_; 1076 switch (num_commits_) { 1077 case 1: 1078 EXPECT_EQ(0u, root->lost_output_surface_count()); 1079 EXPECT_EQ(0u, child->lost_output_surface_count()); 1080 EXPECT_EQ(0u, grandchild->lost_output_surface_count()); 1081 // Lose the context and struggle to recreate it. 1082 LoseContext(); 1083 times_to_fail_create_ = 1; 1084 break; 1085 case 2: 1086 EXPECT_EQ(1u, root->lost_output_surface_count()); 1087 EXPECT_EQ(1u, child->lost_output_surface_count()); 1088 EXPECT_EQ(1u, grandchild->lost_output_surface_count()); 1089 // Lose the context and again during recreate. 1090 LoseContext(); 1091 times_to_lose_on_create_ = 1; 1092 break; 1093 case 3: 1094 EXPECT_EQ(3u, root->lost_output_surface_count()); 1095 EXPECT_EQ(3u, child->lost_output_surface_count()); 1096 EXPECT_EQ(3u, grandchild->lost_output_surface_count()); 1097 // Lose the context and again during reinitialization. 1098 LoseContext(); 1099 times_to_fail_initialize_ = 1; 1100 break; 1101 case 4: 1102 EXPECT_EQ(5u, root->lost_output_surface_count()); 1103 EXPECT_EQ(5u, child->lost_output_surface_count()); 1104 EXPECT_EQ(5u, grandchild->lost_output_surface_count()); 1105 EndTest(); 1106 break; 1107 default: 1108 NOTREACHED(); 1109 } 1110 } 1111 1112 virtual void AfterTest() OVERRIDE {} 1113 1114 private: 1115 int num_commits_; 1116 1117 FakeContentLayerClient client_; 1118 scoped_refptr<FakeContentLayer> root_; 1119 scoped_refptr<FakeContentLayer> child_; 1120 scoped_refptr<FakeContentLayer> grandchild_; 1121 }; 1122 1123 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified); 1124 1125 class LayerTreeHostContextTestDontUseLostResources 1126 : public LayerTreeHostContextTest { 1127 public: 1128 virtual void SetupTree() OVERRIDE { 1129 scoped_refptr<Layer> root_ = Layer::Create(); 1130 root_->SetBounds(gfx::Size(10, 10)); 1131 root_->SetAnchorPoint(gfx::PointF()); 1132 root_->SetIsDrawable(true); 1133 1134 scoped_refptr<FakeDelegatedRendererLayer> delegated_ = 1135 FakeDelegatedRendererLayer::Create(NULL); 1136 delegated_->SetBounds(gfx::Size(10, 10)); 1137 delegated_->SetAnchorPoint(gfx::PointF()); 1138 delegated_->SetIsDrawable(true); 1139 root_->AddChild(delegated_); 1140 1141 scoped_refptr<ContentLayer> content_ = ContentLayer::Create(&client_); 1142 content_->SetBounds(gfx::Size(10, 10)); 1143 content_->SetAnchorPoint(gfx::PointF()); 1144 content_->SetIsDrawable(true); 1145 root_->AddChild(content_); 1146 1147 scoped_refptr<TextureLayer> texture_ = TextureLayer::Create(NULL); 1148 texture_->SetBounds(gfx::Size(10, 10)); 1149 texture_->SetAnchorPoint(gfx::PointF()); 1150 texture_->SetIsDrawable(true); 1151 root_->AddChild(texture_); 1152 1153 scoped_refptr<ContentLayer> mask_ = ContentLayer::Create(&client_); 1154 mask_->SetBounds(gfx::Size(10, 10)); 1155 mask_->SetAnchorPoint(gfx::PointF()); 1156 1157 scoped_refptr<ContentLayer> content_with_mask_ = 1158 ContentLayer::Create(&client_); 1159 content_with_mask_->SetBounds(gfx::Size(10, 10)); 1160 content_with_mask_->SetAnchorPoint(gfx::PointF()); 1161 content_with_mask_->SetIsDrawable(true); 1162 content_with_mask_->SetMaskLayer(mask_.get()); 1163 root_->AddChild(content_with_mask_); 1164 1165 scoped_refptr<VideoLayer> video_color_ = VideoLayer::Create( 1166 &color_frame_provider_); 1167 video_color_->SetBounds(gfx::Size(10, 10)); 1168 video_color_->SetAnchorPoint(gfx::PointF()); 1169 video_color_->SetIsDrawable(true); 1170 root_->AddChild(video_color_); 1171 1172 scoped_refptr<VideoLayer> video_hw_ = VideoLayer::Create( 1173 &hw_frame_provider_); 1174 video_hw_->SetBounds(gfx::Size(10, 10)); 1175 video_hw_->SetAnchorPoint(gfx::PointF()); 1176 video_hw_->SetIsDrawable(true); 1177 root_->AddChild(video_hw_); 1178 1179 scoped_refptr<VideoLayer> video_scaled_hw_ = VideoLayer::Create( 1180 &scaled_hw_frame_provider_); 1181 video_scaled_hw_->SetBounds(gfx::Size(10, 10)); 1182 video_scaled_hw_->SetAnchorPoint(gfx::PointF()); 1183 video_scaled_hw_->SetIsDrawable(true); 1184 root_->AddChild(video_scaled_hw_); 1185 1186 if (!delegating_renderer()) { 1187 // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335 1188 scoped_refptr<IOSurfaceLayer> io_surface_ = IOSurfaceLayer::Create(); 1189 io_surface_->SetBounds(gfx::Size(10, 10)); 1190 io_surface_->SetAnchorPoint(gfx::PointF()); 1191 io_surface_->SetIsDrawable(true); 1192 io_surface_->SetIOSurfaceProperties(1, gfx::Size(10, 10)); 1193 root_->AddChild(io_surface_); 1194 } 1195 1196 // Enable the hud. 1197 LayerTreeDebugState debug_state; 1198 debug_state.show_property_changed_rects = true; 1199 layer_tree_host()->SetDebugState(debug_state); 1200 1201 scoped_refptr<ScrollbarLayer> scrollbar_ = ScrollbarLayer::Create( 1202 scoped_ptr<Scrollbar>(new FakeScrollbar).Pass(), 1203 content_->id()); 1204 scrollbar_->SetBounds(gfx::Size(10, 10)); 1205 scrollbar_->SetAnchorPoint(gfx::PointF()); 1206 scrollbar_->SetIsDrawable(true); 1207 root_->AddChild(scrollbar_); 1208 1209 layer_tree_host()->SetRootLayer(root_); 1210 LayerTreeHostContextTest::SetupTree(); 1211 } 1212 1213 virtual void BeginTest() OVERRIDE { 1214 context_should_support_io_surface_ = true; 1215 PostSetNeedsCommitToMainThread(); 1216 } 1217 1218 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { 1219 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl); 1220 1221 ResourceProvider* resource_provider = host_impl->resource_provider(); 1222 1223 if (host_impl->active_tree()->source_frame_number() == 0) { 1224 // Set up impl resources on the first commit. 1225 1226 scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create(); 1227 pass_for_quad->SetNew( 1228 // AppendOneOfEveryQuadType() makes a RenderPass quad with this id. 1229 RenderPass::Id(1, 1), 1230 gfx::Rect(0, 0, 10, 10), 1231 gfx::Rect(0, 0, 10, 10), 1232 gfx::Transform()); 1233 1234 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create(); 1235 pass->SetNew( 1236 RenderPass::Id(2, 1), 1237 gfx::Rect(0, 0, 10, 10), 1238 gfx::Rect(0, 0, 10, 10), 1239 gfx::Transform()); 1240 pass->AppendOneOfEveryQuadType(resource_provider, RenderPass::Id(2, 1)); 1241 1242 ScopedPtrVector<RenderPass> pass_list; 1243 pass_list.push_back(pass_for_quad.PassAs<RenderPass>()); 1244 pass_list.push_back(pass.PassAs<RenderPass>()); 1245 1246 // First child is the delegated layer. 1247 FakeDelegatedRendererLayerImpl* delegated_impl = 1248 static_cast<FakeDelegatedRendererLayerImpl*>( 1249 host_impl->active_tree()->root_layer()->children()[0]); 1250 delegated_impl->SetFrameDataForRenderPasses(&pass_list); 1251 EXPECT_TRUE(pass_list.empty()); 1252 1253 // Third child is the texture layer. 1254 TextureLayerImpl* texture_impl = 1255 static_cast<TextureLayerImpl*>( 1256 host_impl->active_tree()->root_layer()->children()[2]); 1257 texture_impl->set_texture_id( 1258 resource_provider->GraphicsContext3D()->createTexture()); 1259 1260 DCHECK(resource_provider->GraphicsContext3D()); 1261 ResourceProvider::ResourceId texture = resource_provider->CreateResource( 1262 gfx::Size(4, 4), 1263 resource_provider->default_resource_type(), 1264 ResourceProvider::TextureUsageAny); 1265 ResourceProvider::ScopedWriteLockGL lock(resource_provider, texture); 1266 1267 gpu::Mailbox mailbox; 1268 resource_provider->GraphicsContext3D()->genMailboxCHROMIUM(mailbox.name); 1269 unsigned sync_point = 1270 resource_provider->GraphicsContext3D()->insertSyncPoint(); 1271 1272 color_video_frame_ = VideoFrame::CreateColorFrame( 1273 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta()); 1274 hw_video_frame_ = VideoFrame::WrapNativeTexture( 1275 new VideoFrame::MailboxHolder( 1276 mailbox, 1277 sync_point, 1278 VideoFrame::MailboxHolder::TextureNoLongerNeededCallback()), 1279 GL_TEXTURE_2D, 1280 gfx::Size(4, 4), gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), 1281 base::TimeDelta(), 1282 VideoFrame::ReadPixelsCB(), 1283 base::Closure()); 1284 scaled_hw_video_frame_ = VideoFrame::WrapNativeTexture( 1285 new VideoFrame::MailboxHolder( 1286 mailbox, 1287 sync_point, 1288 VideoFrame::MailboxHolder::TextureNoLongerNeededCallback()), 1289 GL_TEXTURE_2D, 1290 gfx::Size(4, 4), gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), 1291 base::TimeDelta(), 1292 VideoFrame::ReadPixelsCB(), 1293 base::Closure()); 1294 1295 color_frame_provider_.set_frame(color_video_frame_); 1296 hw_frame_provider_.set_frame(hw_video_frame_); 1297 scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_); 1298 return; 1299 } 1300 1301 if (host_impl->active_tree()->source_frame_number() == 3) { 1302 // On the third commit we're recovering from context loss. Hardware 1303 // video frames should not be reused by the VideoFrameProvider, but 1304 // software frames can be. 1305 hw_frame_provider_.set_frame(NULL); 1306 scaled_hw_frame_provider_.set_frame(NULL); 1307 } 1308 } 1309 1310 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, 1311 LayerTreeHostImpl::FrameData* frame, 1312 bool result) OVERRIDE { 1313 if (host_impl->active_tree()->source_frame_number() == 2) { 1314 // Lose the context during draw on the second commit. This will cause 1315 // a third commit to recover. 1316 if (context3d_) 1317 context3d_->set_times_bind_texture_succeeds(4); 1318 } 1319 return true; 1320 } 1321 1322 virtual void DidCommitAndDrawFrame() OVERRIDE { 1323 ASSERT_TRUE(layer_tree_host()->hud_layer()); 1324 // End the test once we know the 3nd frame drew. 1325 if (layer_tree_host()->source_frame_number() == 4) 1326 EndTest(); 1327 else 1328 layer_tree_host()->SetNeedsCommit(); 1329 } 1330 1331 virtual void AfterTest() OVERRIDE {} 1332 1333 private: 1334 FakeContentLayerClient client_; 1335 1336 scoped_refptr<Layer> root_; 1337 scoped_refptr<DelegatedRendererLayer> delegated_; 1338 scoped_refptr<ContentLayer> content_; 1339 scoped_refptr<TextureLayer> texture_; 1340 scoped_refptr<ContentLayer> mask_; 1341 scoped_refptr<ContentLayer> content_with_mask_; 1342 scoped_refptr<VideoLayer> video_color_; 1343 scoped_refptr<VideoLayer> video_hw_; 1344 scoped_refptr<VideoLayer> video_scaled_hw_; 1345 scoped_refptr<IOSurfaceLayer> io_surface_; 1346 scoped_refptr<ScrollbarLayer> scrollbar_; 1347 1348 scoped_refptr<VideoFrame> color_video_frame_; 1349 scoped_refptr<VideoFrame> hw_video_frame_; 1350 scoped_refptr<VideoFrame> scaled_hw_video_frame_; 1351 1352 FakeVideoFrameProvider color_frame_provider_; 1353 FakeVideoFrameProvider hw_frame_provider_; 1354 FakeVideoFrameProvider scaled_hw_frame_provider_; 1355 }; 1356 1357 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources); 1358 1359 class LayerTreeHostContextTestLosesFirstOutputSurface 1360 : public LayerTreeHostContextTest { 1361 public: 1362 LayerTreeHostContextTestLosesFirstOutputSurface() { 1363 // Always fail. This needs to be set before LayerTreeHost is created. 1364 times_to_lose_on_create_ = 1000; 1365 } 1366 1367 virtual void BeginTest() OVERRIDE { 1368 PostSetNeedsCommitToMainThread(); 1369 } 1370 1371 virtual void AfterTest() OVERRIDE {} 1372 1373 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE { 1374 EXPECT_FALSE(succeeded); 1375 1376 // If we make it this far without crashing, we pass! 1377 EndTest(); 1378 } 1379 1380 virtual void DidCommitAndDrawFrame() OVERRIDE { 1381 EXPECT_TRUE(false); 1382 } 1383 }; 1384 1385 SINGLE_AND_MULTI_THREAD_TEST_F( 1386 LayerTreeHostContextTestLosesFirstOutputSurface); 1387 1388 class LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds 1389 : public LayerTreeHostContextTest { 1390 public: 1391 virtual void AfterTest() OVERRIDE {} 1392 1393 virtual void BeginTest() OVERRIDE { 1394 times_to_fail_initialize_ = 2; 1395 PostSetNeedsCommitToMainThread(); 1396 } 1397 1398 virtual void DidCommitAndDrawFrame() OVERRIDE { 1399 EndTest(); 1400 } 1401 }; 1402 1403 SINGLE_AND_MULTI_THREAD_TEST_F( 1404 LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds); 1405 1406 class LayerTreeHostContextTestRetryWorksWithForcedInit 1407 : public LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds { 1408 public: 1409 virtual void DidFailToInitializeOutputSurface() OVERRIDE { 1410 LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds 1411 ::DidFailToInitializeOutputSurface(); 1412 1413 if (times_create_failed_ == 1) { 1414 // CompositeAndReadback force recreates the output surface, which should 1415 // fail. 1416 char pixels[4]; 1417 EXPECT_FALSE(layer_tree_host()->CompositeAndReadback( 1418 &pixels, gfx::Rect(1, 1))); 1419 } 1420 } 1421 }; 1422 1423 SINGLE_AND_MULTI_THREAD_TEST_F( 1424 LayerTreeHostContextTestRetryWorksWithForcedInit); 1425 1426 class LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit 1427 : public LayerTreeHostContextTest { 1428 public: 1429 virtual void BeginTest() OVERRIDE { 1430 // This must be called immediately after creating LTH, before the first 1431 // OutputSurface is initialized. 1432 ASSERT_TRUE(layer_tree_host()->output_surface_lost()); 1433 1434 times_output_surface_created_ = 0; 1435 1436 char pixels[4]; 1437 bool result = layer_tree_host()->CompositeAndReadback( 1438 &pixels, gfx::Rect(1, 1)); 1439 EXPECT_EQ(!delegating_renderer(), result); 1440 EXPECT_EQ(1, times_output_surface_created_); 1441 1442 PostSetNeedsCommitToMainThread(); 1443 } 1444 1445 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE { 1446 EXPECT_TRUE(succeeded); 1447 ++times_output_surface_created_; 1448 } 1449 1450 virtual void DidCommitAndDrawFrame() OVERRIDE { 1451 EndTest(); 1452 } 1453 1454 virtual void AfterTest() OVERRIDE { 1455 // Should not try to create output surface again after successfully 1456 // created by CompositeAndReadback. 1457 EXPECT_EQ(1, times_output_surface_created_); 1458 } 1459 1460 private: 1461 int times_output_surface_created_; 1462 }; 1463 1464 SINGLE_AND_MULTI_THREAD_TEST_F( 1465 LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit); 1466 1467 class ImplSidePaintingLayerTreeHostContextTest 1468 : public LayerTreeHostContextTest { 1469 public: 1470 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE { 1471 settings->impl_side_painting = true; 1472 } 1473 }; 1474 1475 class LayerTreeHostContextTestImplSidePainting 1476 : public ImplSidePaintingLayerTreeHostContextTest { 1477 public: 1478 virtual void SetupTree() OVERRIDE { 1479 scoped_refptr<Layer> root = Layer::Create(); 1480 root->SetBounds(gfx::Size(10, 10)); 1481 root->SetAnchorPoint(gfx::PointF()); 1482 root->SetIsDrawable(true); 1483 1484 scoped_refptr<PictureLayer> picture = PictureLayer::Create(&client_); 1485 picture->SetBounds(gfx::Size(10, 10)); 1486 picture->SetAnchorPoint(gfx::PointF()); 1487 picture->SetIsDrawable(true); 1488 root->AddChild(picture); 1489 1490 layer_tree_host()->SetRootLayer(root); 1491 LayerTreeHostContextTest::SetupTree(); 1492 } 1493 1494 virtual void BeginTest() OVERRIDE { 1495 times_to_lose_during_commit_ = 1; 1496 PostSetNeedsCommitToMainThread(); 1497 } 1498 1499 virtual void AfterTest() OVERRIDE {} 1500 1501 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE { 1502 EXPECT_TRUE(succeeded); 1503 EndTest(); 1504 } 1505 1506 private: 1507 FakeContentLayerClient client_; 1508 }; 1509 1510 MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting); 1511 1512 class ScrollbarLayerLostContext : public LayerTreeHostContextTest { 1513 public: 1514 ScrollbarLayerLostContext() : commits_(0) {} 1515 1516 virtual void BeginTest() OVERRIDE { 1517 scoped_refptr<Layer> scroll_layer = Layer::Create(); 1518 scrollbar_layer_ = FakeScrollbarLayer::Create( 1519 false, true, scroll_layer->id()); 1520 scrollbar_layer_->SetBounds(gfx::Size(10, 100)); 1521 layer_tree_host()->root_layer()->AddChild(scrollbar_layer_); 1522 layer_tree_host()->root_layer()->AddChild(scroll_layer); 1523 PostSetNeedsCommitToMainThread(); 1524 } 1525 1526 virtual void AfterTest() OVERRIDE {} 1527 1528 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE { 1529 LayerTreeHostContextTest::CommitCompleteOnThread(impl); 1530 1531 ++commits_; 1532 switch (commits_) { 1533 case 1: 1534 // First (regular) update, we should upload 2 resources (thumb, and 1535 // backtrack). 1536 EXPECT_EQ(1, scrollbar_layer_->update_count()); 1537 LoseContext(); 1538 break; 1539 case 2: 1540 // Second update, after the lost context, we should still upload 2 1541 // resources even if the contents haven't changed. 1542 EXPECT_EQ(2, scrollbar_layer_->update_count()); 1543 EndTest(); 1544 break; 1545 default: 1546 NOTREACHED(); 1547 } 1548 } 1549 1550 private: 1551 int commits_; 1552 scoped_refptr<FakeScrollbarLayer> scrollbar_layer_; 1553 }; 1554 1555 SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext); 1556 1557 class LayerTreeHostContextTestFailsToCreateSurface 1558 : public LayerTreeHostContextTest { 1559 public: 1560 LayerTreeHostContextTestFailsToCreateSurface() 1561 : LayerTreeHostContextTest(), 1562 failure_count_(0) { 1563 times_to_lose_on_create_ = 10; 1564 } 1565 1566 virtual void BeginTest() OVERRIDE { 1567 PostSetNeedsCommitToMainThread(); 1568 } 1569 1570 virtual void AfterTest() OVERRIDE {} 1571 1572 virtual void DidInitializeOutputSurface(bool success) OVERRIDE { 1573 EXPECT_FALSE(success); 1574 EXPECT_EQ(0, failure_count_); 1575 times_to_lose_on_create_ = 0; 1576 failure_count_++; 1577 // Normally, the embedder should stop trying to use the compositor at 1578 // this point, but let's force it back into action when we shouldn't. 1579 char pixels[4]; 1580 EXPECT_FALSE( 1581 layer_tree_host()->CompositeAndReadback(pixels, gfx::Rect(1, 1))); 1582 // If we've made it this far without crashing, we've succeeded. 1583 EndTest(); 1584 } 1585 1586 private: 1587 int failure_count_; 1588 }; 1589 1590 SINGLE_AND_MULTI_THREAD_TEST_F( 1591 LayerTreeHostContextTestFailsToCreateSurface); 1592 1593 // Not reusing LayerTreeTest because it expects creating LTH to always succeed. 1594 class LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface 1595 : public testing::Test, 1596 public FakeLayerTreeHostClient { 1597 public: 1598 LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface() 1599 : FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D) {} 1600 1601 // FakeLayerTreeHostClient implementation. 1602 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback) 1603 OVERRIDE { 1604 return scoped_ptr<OutputSurface>(); 1605 } 1606 1607 void RunTest(bool threaded, 1608 bool delegating_renderer, 1609 bool impl_side_painting) { 1610 scoped_ptr<base::Thread> impl_thread; 1611 if (threaded) { 1612 impl_thread.reset(new base::Thread("LayerTreeTest")); 1613 ASSERT_TRUE(impl_thread->Start()); 1614 ASSERT_TRUE(impl_thread->message_loop_proxy().get()); 1615 } 1616 1617 LayerTreeSettings settings; 1618 settings.impl_side_painting = impl_side_painting; 1619 scoped_ptr<LayerTreeHost> layer_tree_host = LayerTreeHost::Create( 1620 this, 1621 settings, 1622 impl_thread ? impl_thread->message_loop_proxy() : NULL); 1623 EXPECT_FALSE(layer_tree_host); 1624 } 1625 }; 1626 1627 SINGLE_AND_MULTI_THREAD_TEST_F( 1628 LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface); 1629 1630 class UIResourceLostTest : public LayerTreeHostContextTest { 1631 public: 1632 UIResourceLostTest() : time_step_(0) {} 1633 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); } 1634 virtual void AfterTest() OVERRIDE {} 1635 1636 protected: 1637 int time_step_; 1638 scoped_ptr<FakeScopedUIResource> ui_resource_; 1639 }; 1640 1641 // Losing context after an UI resource has been created. 1642 class UIResourceLostAfterCommit : public UIResourceLostTest { 1643 public: 1644 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE { 1645 LayerTreeHostContextTest::CommitCompleteOnThread(impl); 1646 switch (time_step_) { 1647 case 0: 1648 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()); 1649 // Expects a valid UIResourceId. 1650 EXPECT_NE(0, ui_resource_->id()); 1651 PostSetNeedsCommitToMainThread(); 1652 break; 1653 case 1: 1654 // The resource should have been created on LTHI after the commit. 1655 if (!layer_tree_host()->settings().impl_side_painting) 1656 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); 1657 PostSetNeedsCommitToMainThread(); 1658 break; 1659 case 2: 1660 LoseContext(); 1661 break; 1662 case 3: 1663 // The resources should have been recreated. The bitmap callback should 1664 // have been called once with the resource_lost flag set to true. 1665 EXPECT_EQ(1, ui_resource_->lost_resource_count); 1666 // Resource Id on the impl-side have been recreated as well. Note 1667 // that the same UIResourceId persists after the context lost. 1668 if (!layer_tree_host()->settings().impl_side_painting) 1669 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); 1670 PostSetNeedsCommitToMainThread(); 1671 break; 1672 case 4: 1673 // Release resource before ending test. 1674 ui_resource_.reset(); 1675 EndTest(); 1676 break; 1677 } 1678 } 1679 1680 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { 1681 LayerTreeHostContextTest::DidActivateTreeOnThread(impl); 1682 switch (time_step_) { 1683 case 1: 1684 if (layer_tree_host()->settings().impl_side_painting) 1685 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); 1686 break; 1687 case 3: 1688 if (layer_tree_host()->settings().impl_side_painting) 1689 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); 1690 break; 1691 } 1692 ++time_step_; 1693 } 1694 }; 1695 1696 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit); 1697 1698 // Losing context before UI resource requests can be commited. Three sequences 1699 // of creation/deletion are considered: 1700 // 1. Create one resource -> Context Lost => Expect the resource to have been 1701 // created. 1702 // 2. Delete an exisiting resource (test_id0_) -> create a second resource 1703 // (test_id1_) -> Context Lost => Expect the test_id0_ to be removed and 1704 // test_id1_ to have been created. 1705 // 3. Create one resource -> Delete that same resource -> Context Lost => Expect 1706 // the resource to not exist in the manager. 1707 class UIResourceLostBeforeCommit : public UIResourceLostTest { 1708 public: 1709 UIResourceLostBeforeCommit() 1710 : test_id0_(0), 1711 test_id1_(0) {} 1712 1713 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE { 1714 LayerTreeHostContextTest::CommitCompleteOnThread(impl); 1715 switch (time_step_) { 1716 case 0: 1717 // Sequence 1: 1718 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()); 1719 LoseContext(); 1720 // Resource Id on the impl-side should no longer be valid after 1721 // context is lost. 1722 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id())); 1723 break; 1724 case 1: 1725 // The resources should have been recreated. 1726 EXPECT_EQ(2, ui_resource_->resource_create_count); 1727 // "resource lost" callback was called once for the resource in the 1728 // resource map. 1729 EXPECT_EQ(1, ui_resource_->lost_resource_count); 1730 // Resource Id on the impl-side have been recreated as well. Note 1731 // that the same UIResourceId persists after the context lost. 1732 if (!layer_tree_host()->settings().impl_side_painting) 1733 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); 1734 PostSetNeedsCommitToMainThread(); 1735 break; 1736 case 2: 1737 // Sequence 2: 1738 // Currently one resource has been created. 1739 test_id0_ = ui_resource_->id(); 1740 // Delete this resource. 1741 ui_resource_.reset(); 1742 // Create another resource. 1743 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()); 1744 test_id1_ = ui_resource_->id(); 1745 // Sanity check that two resource creations return different ids. 1746 EXPECT_NE(test_id0_, test_id1_); 1747 // Lose the context before commit. 1748 LoseContext(); 1749 break; 1750 case 3: 1751 if (!layer_tree_host()->settings().impl_side_painting) { 1752 // The previous resource should have been deleted. 1753 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_)); 1754 // The second resource should have been created. 1755 EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_)); 1756 } 1757 1758 // The second resource called the resource callback once and since the 1759 // context is lost, a "resource lost" callback was also issued. 1760 EXPECT_EQ(2, ui_resource_->resource_create_count); 1761 EXPECT_EQ(1, ui_resource_->lost_resource_count); 1762 // Clear the manager of resources. 1763 ui_resource_.reset(); 1764 PostSetNeedsCommitToMainThread(); 1765 break; 1766 case 4: 1767 // Sequence 3: 1768 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()); 1769 test_id0_ = ui_resource_->id(); 1770 // Sanity check the UIResourceId should not be 0. 1771 EXPECT_NE(0, test_id0_); 1772 // Usually ScopedUIResource are deleted from the manager in their 1773 // destructor (so usually ui_resource_.reset()). But here we need 1774 // ui_resource_ for the next step, so call DeleteUIResource directly. 1775 layer_tree_host()->DeleteUIResource(test_id0_); 1776 LoseContext(); 1777 break; 1778 case 5: 1779 // Expect the resource callback to have been called once. 1780 EXPECT_EQ(1, ui_resource_->resource_create_count); 1781 // No "resource lost" callbacks. 1782 EXPECT_EQ(0, ui_resource_->lost_resource_count); 1783 if (!layer_tree_host()->settings().impl_side_painting) { 1784 // The UI resource id should not be valid 1785 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_)); 1786 } 1787 PostSetNeedsCommitToMainThread(); 1788 break; 1789 case 6: 1790 ui_resource_.reset(); 1791 EndTest(); 1792 break; 1793 } 1794 } 1795 1796 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { 1797 LayerTreeHostContextTest::DidActivateTreeOnThread(impl); 1798 switch (time_step_) { 1799 case 1: 1800 if (layer_tree_host()->settings().impl_side_painting) 1801 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); 1802 break; 1803 case 3: 1804 if (layer_tree_host()->settings().impl_side_painting) { 1805 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_)); 1806 EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_)); 1807 } 1808 break; 1809 case 5: 1810 if (layer_tree_host()->settings().impl_side_painting) 1811 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_)); 1812 break; 1813 } 1814 ++time_step_; 1815 } 1816 1817 private: 1818 UIResourceId test_id0_; 1819 UIResourceId test_id1_; 1820 }; 1821 1822 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit); 1823 1824 // Losing UI resource before the pending trees is activated but after the 1825 // commit. Impl-side-painting only. 1826 class UIResourceLostBeforeActivateTree : public UIResourceLostTest { 1827 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE { 1828 LayerTreeHostContextTest::CommitCompleteOnThread(impl); 1829 switch (time_step_) { 1830 case 0: 1831 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host()); 1832 PostSetNeedsCommitToMainThread(); 1833 break; 1834 case 2: 1835 PostSetNeedsCommitToMainThread(); 1836 break; 1837 case 3: 1838 test_id_ = ui_resource_->id(); 1839 ui_resource_.reset(); 1840 PostSetNeedsCommitToMainThread(); 1841 break; 1842 case 4: 1843 PostSetNeedsCommitToMainThread(); 1844 break; 1845 case 5: 1846 EndTest(); 1847 break; 1848 } 1849 } 1850 1851 virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { 1852 switch (time_step_) { 1853 case 0: 1854 break; 1855 case 1: 1856 // The resource creation callback has been called. 1857 EXPECT_EQ(1, ui_resource_->resource_create_count); 1858 // The resource is not yet lost (sanity check). 1859 EXPECT_EQ(0, ui_resource_->lost_resource_count); 1860 // The resource should not have been created yet on the impl-side. 1861 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id())); 1862 LoseContext(); 1863 break; 1864 case 3: 1865 LoseContext(); 1866 break; 1867 } 1868 } 1869 1870 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { 1871 LayerTreeHostContextTest::DidActivateTreeOnThread(impl); 1872 switch (time_step_) { 1873 case 1: 1874 // The pending requests on the impl-side should have been processed. 1875 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id())); 1876 break; 1877 case 2: 1878 // The "lost resource" callback should have been called once. 1879 EXPECT_EQ(1, ui_resource_->lost_resource_count); 1880 break; 1881 case 4: 1882 // The resource is deleted and should not be in the manager. Use 1883 // test_id_ since ui_resource_ has been deleted. 1884 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id_)); 1885 break; 1886 } 1887 ++time_step_; 1888 } 1889 1890 private: 1891 UIResourceId test_id_; 1892 }; 1893 1894 TEST_F(UIResourceLostBeforeActivateTree, 1895 RunMultiThread_DirectRenderer_ImplSidePaint) { 1896 RunTest(true, false, true); 1897 } 1898 1899 TEST_F(UIResourceLostBeforeActivateTree, 1900 RunMultiThread_DelegatingRenderer_ImplSidePaint) { 1901 RunTest(true, true, true); 1902 } 1903 1904 } // namespace 1905 } // namespace cc 1906