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