1 // Copyright 2013 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/output/copy_output_request.h" 6 #include "cc/output/copy_output_result.h" 7 #include "cc/test/fake_content_layer.h" 8 #include "cc/test/fake_content_layer_client.h" 9 #include "cc/test/fake_output_surface.h" 10 #include "cc/test/layer_tree_test.h" 11 #include "cc/trees/layer_tree_impl.h" 12 #include "gpu/GLES2/gl2extchromium.h" 13 14 namespace cc { 15 namespace { 16 17 // These tests only use direct rendering, as there is no output to copy for 18 // delegated renderers. 19 class LayerTreeHostCopyRequestTest : public LayerTreeTest {}; 20 21 class LayerTreeHostCopyRequestTestMultipleRequests 22 : public LayerTreeHostCopyRequestTest { 23 protected: 24 virtual void SetupTree() OVERRIDE { 25 root = FakeContentLayer::Create(&client_); 26 root->SetBounds(gfx::Size(20, 20)); 27 28 child = FakeContentLayer::Create(&client_); 29 child->SetBounds(gfx::Size(10, 10)); 30 root->AddChild(child); 31 32 layer_tree_host()->SetRootLayer(root); 33 LayerTreeHostCopyRequestTest::SetupTree(); 34 } 35 36 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); } 37 38 virtual void DidCommitAndDrawFrame() OVERRIDE { WaitForCallback(); } 39 40 void WaitForCallback() { 41 base::MessageLoop::current()->PostTask( 42 FROM_HERE, 43 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::NextStep, 44 base::Unretained(this))); 45 } 46 47 void NextStep() { 48 int frame = layer_tree_host()->source_frame_number(); 49 switch (frame) { 50 case 1: 51 child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest( 52 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests:: 53 CopyOutputCallback, 54 base::Unretained(this)))); 55 EXPECT_EQ(0u, callbacks_.size()); 56 break; 57 case 2: 58 if (callbacks_.size() < 1u) { 59 WaitForCallback(); 60 return; 61 } 62 EXPECT_EQ(1u, callbacks_.size()); 63 EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[0].ToString()); 64 65 child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest( 66 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests:: 67 CopyOutputCallback, 68 base::Unretained(this)))); 69 root->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest( 70 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests:: 71 CopyOutputCallback, 72 base::Unretained(this)))); 73 child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest( 74 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests:: 75 CopyOutputCallback, 76 base::Unretained(this)))); 77 EXPECT_EQ(1u, callbacks_.size()); 78 break; 79 case 3: 80 if (callbacks_.size() < 4u) { 81 WaitForCallback(); 82 return; 83 } 84 EXPECT_EQ(4u, callbacks_.size()); 85 // The child was copied to a bitmap and passed back twice. 86 EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[1].ToString()); 87 EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[2].ToString()); 88 // The root was copied to a bitmap and passed back also. 89 EXPECT_EQ(gfx::Size(20, 20).ToString(), callbacks_[3].ToString()); 90 EndTest(); 91 break; 92 } 93 } 94 95 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { 96 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread()); 97 EXPECT_TRUE(result->HasBitmap()); 98 scoped_ptr<SkBitmap> bitmap = result->TakeBitmap().Pass(); 99 EXPECT_EQ(result->size().ToString(), 100 gfx::Size(bitmap->width(), bitmap->height()).ToString()); 101 callbacks_.push_back(result->size()); 102 } 103 104 virtual void AfterTest() OVERRIDE { EXPECT_EQ(4u, callbacks_.size()); } 105 106 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback) 107 OVERRIDE { 108 if (use_gl_renderer_) 109 return FakeOutputSurface::Create3d(); 110 return FakeOutputSurface::CreateSoftware( 111 make_scoped_ptr(new SoftwareOutputDevice)); 112 } 113 114 bool use_gl_renderer_; 115 std::vector<gfx::Size> callbacks_; 116 FakeContentLayerClient client_; 117 scoped_refptr<FakeContentLayer> root; 118 scoped_refptr<FakeContentLayer> child; 119 }; 120 121 // Readback can't be done with a delegating renderer. 122 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests, 123 GLRenderer_RunSingleThread) { 124 use_gl_renderer_ = true; 125 RunTest(false, false, false); 126 } 127 128 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests, 129 GLRenderer_RunMultiThread_MainThreadPainting) { 130 use_gl_renderer_ = true; 131 RunTest(true, false, false); 132 } 133 134 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests, 135 SoftwareRenderer_RunSingleThread) { 136 use_gl_renderer_ = false; 137 RunTest(false, false, false); 138 } 139 140 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests, 141 SoftwareRenderer_RunMultiThread_MainThreadPainting) { 142 use_gl_renderer_ = false; 143 RunTest(true, false, false); 144 } 145 146 class LayerTreeHostCopyRequestTestLayerDestroyed 147 : public LayerTreeHostCopyRequestTest { 148 protected: 149 virtual void SetupTree() OVERRIDE { 150 root_ = FakeContentLayer::Create(&client_); 151 root_->SetBounds(gfx::Size(20, 20)); 152 153 main_destroyed_ = FakeContentLayer::Create(&client_); 154 main_destroyed_->SetBounds(gfx::Size(15, 15)); 155 root_->AddChild(main_destroyed_); 156 157 impl_destroyed_ = FakeContentLayer::Create(&client_); 158 impl_destroyed_->SetBounds(gfx::Size(10, 10)); 159 root_->AddChild(impl_destroyed_); 160 161 layer_tree_host()->SetRootLayer(root_); 162 LayerTreeHostCopyRequestTest::SetupTree(); 163 } 164 165 virtual void BeginTest() OVERRIDE { 166 callback_count_ = 0; 167 PostSetNeedsCommitToMainThread(); 168 } 169 170 virtual void DidCommit() OVERRIDE { 171 int frame = layer_tree_host()->source_frame_number(); 172 switch (frame) { 173 case 1: 174 main_destroyed_->RequestCopyOfOutput( 175 CopyOutputRequest::CreateBitmapRequest(base::Bind( 176 &LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback, 177 base::Unretained(this)))); 178 impl_destroyed_->RequestCopyOfOutput( 179 CopyOutputRequest::CreateBitmapRequest(base::Bind( 180 &LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback, 181 base::Unretained(this)))); 182 EXPECT_EQ(0, callback_count_); 183 184 // Destroy the main thread layer right away. 185 main_destroyed_->RemoveFromParent(); 186 main_destroyed_ = NULL; 187 188 // Should callback with a NULL bitmap. 189 EXPECT_EQ(1, callback_count_); 190 191 // Prevent drawing so we can't make a copy of the impl_destroyed layer. 192 layer_tree_host()->SetViewportSize(gfx::Size()); 193 break; 194 case 2: 195 // Flush the message loops and make sure the callbacks run. 196 layer_tree_host()->SetNeedsCommit(); 197 break; 198 case 3: 199 // No drawing means no readback yet. 200 EXPECT_EQ(1, callback_count_); 201 202 // Destroy the impl thread layer. 203 impl_destroyed_->RemoveFromParent(); 204 impl_destroyed_ = NULL; 205 206 // No callback yet because it's on the impl side. 207 EXPECT_EQ(1, callback_count_); 208 break; 209 case 4: 210 // Flush the message loops and make sure the callbacks run. 211 layer_tree_host()->SetNeedsCommit(); 212 break; 213 case 5: 214 // We should get another callback with a NULL bitmap. 215 EXPECT_EQ(2, callback_count_); 216 EndTest(); 217 break; 218 } 219 } 220 221 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { 222 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread()); 223 EXPECT_TRUE(result->IsEmpty()); 224 ++callback_count_; 225 } 226 227 virtual void AfterTest() OVERRIDE {} 228 229 int callback_count_; 230 FakeContentLayerClient client_; 231 scoped_refptr<FakeContentLayer> root_; 232 scoped_refptr<FakeContentLayer> main_destroyed_; 233 scoped_refptr<FakeContentLayer> impl_destroyed_; 234 }; 235 236 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestLayerDestroyed); 237 238 class LayerTreeHostCopyRequestTestInHiddenSubtree 239 : public LayerTreeHostCopyRequestTest { 240 protected: 241 virtual void SetupTree() OVERRIDE { 242 root_ = FakeContentLayer::Create(&client_); 243 root_->SetBounds(gfx::Size(20, 20)); 244 245 grand_parent_layer_ = FakeContentLayer::Create(&client_); 246 grand_parent_layer_->SetBounds(gfx::Size(15, 15)); 247 root_->AddChild(grand_parent_layer_); 248 249 // parent_layer_ owns a render surface. 250 parent_layer_ = FakeContentLayer::Create(&client_); 251 parent_layer_->SetBounds(gfx::Size(15, 15)); 252 parent_layer_->SetForceRenderSurface(true); 253 grand_parent_layer_->AddChild(parent_layer_); 254 255 copy_layer_ = FakeContentLayer::Create(&client_); 256 copy_layer_->SetBounds(gfx::Size(10, 10)); 257 parent_layer_->AddChild(copy_layer_); 258 259 layer_tree_host()->SetRootLayer(root_); 260 LayerTreeHostCopyRequestTest::SetupTree(); 261 } 262 263 void AddCopyRequest(Layer* layer) { 264 layer->RequestCopyOfOutput( 265 CopyOutputRequest::CreateBitmapRequest(base::Bind( 266 &LayerTreeHostCopyRequestTestInHiddenSubtree::CopyOutputCallback, 267 base::Unretained(this)))); 268 } 269 270 virtual void BeginTest() OVERRIDE { 271 callback_count_ = 0; 272 PostSetNeedsCommitToMainThread(); 273 274 AddCopyRequest(copy_layer_.get()); 275 } 276 277 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { 278 ++callback_count_; 279 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread()); 280 EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString()) 281 << callback_count_; 282 switch (callback_count_) { 283 case 1: 284 // Hide the copy request layer. 285 grand_parent_layer_->SetHideLayerAndSubtree(false); 286 parent_layer_->SetHideLayerAndSubtree(false); 287 copy_layer_->SetHideLayerAndSubtree(true); 288 AddCopyRequest(copy_layer_.get()); 289 break; 290 case 2: 291 // Hide the copy request layer's parent only. 292 grand_parent_layer_->SetHideLayerAndSubtree(false); 293 parent_layer_->SetHideLayerAndSubtree(true); 294 copy_layer_->SetHideLayerAndSubtree(false); 295 AddCopyRequest(copy_layer_.get()); 296 break; 297 case 3: 298 // Hide the copy request layer's grand parent only. 299 grand_parent_layer_->SetHideLayerAndSubtree(true); 300 parent_layer_->SetHideLayerAndSubtree(false); 301 copy_layer_->SetHideLayerAndSubtree(false); 302 AddCopyRequest(copy_layer_.get()); 303 break; 304 case 4: 305 // Hide the copy request layer's parent and grandparent. 306 grand_parent_layer_->SetHideLayerAndSubtree(true); 307 parent_layer_->SetHideLayerAndSubtree(true); 308 copy_layer_->SetHideLayerAndSubtree(false); 309 AddCopyRequest(copy_layer_.get()); 310 break; 311 case 5: 312 // Hide the copy request layer as well as its parent and grandparent. 313 grand_parent_layer_->SetHideLayerAndSubtree(true); 314 parent_layer_->SetHideLayerAndSubtree(true); 315 copy_layer_->SetHideLayerAndSubtree(true); 316 AddCopyRequest(copy_layer_.get()); 317 break; 318 case 6: 319 EndTest(); 320 break; 321 } 322 } 323 324 virtual void AfterTest() OVERRIDE {} 325 326 int callback_count_; 327 FakeContentLayerClient client_; 328 scoped_refptr<FakeContentLayer> root_; 329 scoped_refptr<FakeContentLayer> grand_parent_layer_; 330 scoped_refptr<FakeContentLayer> parent_layer_; 331 scoped_refptr<FakeContentLayer> copy_layer_; 332 }; 333 334 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F( 335 LayerTreeHostCopyRequestTestInHiddenSubtree); 336 337 class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest 338 : public LayerTreeHostCopyRequestTest { 339 protected: 340 virtual void SetupTree() OVERRIDE { 341 root_ = FakeContentLayer::Create(&client_); 342 root_->SetBounds(gfx::Size(20, 20)); 343 344 grand_parent_layer_ = FakeContentLayer::Create(&client_); 345 grand_parent_layer_->SetBounds(gfx::Size(15, 15)); 346 grand_parent_layer_->SetHideLayerAndSubtree(true); 347 root_->AddChild(grand_parent_layer_); 348 349 // parent_layer_ owns a render surface. 350 parent_layer_ = FakeContentLayer::Create(&client_); 351 parent_layer_->SetBounds(gfx::Size(15, 15)); 352 parent_layer_->SetForceRenderSurface(true); 353 grand_parent_layer_->AddChild(parent_layer_); 354 355 copy_layer_ = FakeContentLayer::Create(&client_); 356 copy_layer_->SetBounds(gfx::Size(10, 10)); 357 parent_layer_->AddChild(copy_layer_); 358 359 layer_tree_host()->SetRootLayer(root_); 360 LayerTreeHostCopyRequestTest::SetupTree(); 361 } 362 363 virtual void BeginTest() OVERRIDE { 364 did_draw_ = false; 365 PostSetNeedsCommitToMainThread(); 366 367 copy_layer_->RequestCopyOfOutput( 368 CopyOutputRequest::CreateBitmapRequest(base::Bind( 369 &LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest:: 370 CopyOutputCallback, 371 base::Unretained(this)))); 372 } 373 374 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { 375 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread()); 376 EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString()); 377 EndTest(); 378 } 379 380 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { 381 Renderer* renderer = host_impl->renderer(); 382 383 LayerImpl* root = host_impl->active_tree()->root_layer(); 384 LayerImpl* grand_parent = root->children()[0]; 385 LayerImpl* parent = grand_parent->children()[0]; 386 LayerImpl* copy_layer = parent->children()[0]; 387 388 // |parent| owns a surface, but it was hidden and not part of the copy 389 // request so it should not allocate any resource. 390 EXPECT_FALSE(renderer->HasAllocatedResourcesForTesting( 391 parent->render_surface()->RenderPassId())); 392 393 // |copy_layer| should have been rendered to a texture since it was needed 394 // for a copy request. 395 EXPECT_TRUE(renderer->HasAllocatedResourcesForTesting( 396 copy_layer->render_surface()->RenderPassId())); 397 398 did_draw_ = true; 399 } 400 401 virtual void AfterTest() OVERRIDE { EXPECT_TRUE(did_draw_); } 402 403 FakeContentLayerClient client_; 404 bool did_draw_; 405 scoped_refptr<FakeContentLayer> root_; 406 scoped_refptr<FakeContentLayer> grand_parent_layer_; 407 scoped_refptr<FakeContentLayer> parent_layer_; 408 scoped_refptr<FakeContentLayer> copy_layer_; 409 }; 410 411 // No output to copy for delegated renderers. 412 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( 413 LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest); 414 415 class LayerTreeHostCopyRequestTestClippedOut 416 : public LayerTreeHostCopyRequestTest { 417 protected: 418 virtual void SetupTree() OVERRIDE { 419 root_ = FakeContentLayer::Create(&client_); 420 root_->SetBounds(gfx::Size(20, 20)); 421 422 parent_layer_ = FakeContentLayer::Create(&client_); 423 parent_layer_->SetBounds(gfx::Size(15, 15)); 424 parent_layer_->SetMasksToBounds(true); 425 root_->AddChild(parent_layer_); 426 427 copy_layer_ = FakeContentLayer::Create(&client_); 428 copy_layer_->SetPosition(gfx::Point(15, 15)); 429 copy_layer_->SetBounds(gfx::Size(10, 10)); 430 parent_layer_->AddChild(copy_layer_); 431 432 layer_tree_host()->SetRootLayer(root_); 433 LayerTreeHostCopyRequestTest::SetupTree(); 434 } 435 436 virtual void BeginTest() OVERRIDE { 437 PostSetNeedsCommitToMainThread(); 438 439 copy_layer_->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest( 440 base::Bind(&LayerTreeHostCopyRequestTestClippedOut::CopyOutputCallback, 441 base::Unretained(this)))); 442 } 443 444 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { 445 // We should still get a callback with no output if the copy requested layer 446 // was completely clipped away. 447 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread()); 448 EXPECT_EQ(gfx::Size().ToString(), result->size().ToString()); 449 EndTest(); 450 } 451 452 virtual void AfterTest() OVERRIDE {} 453 454 FakeContentLayerClient client_; 455 scoped_refptr<FakeContentLayer> root_; 456 scoped_refptr<FakeContentLayer> parent_layer_; 457 scoped_refptr<FakeContentLayer> copy_layer_; 458 }; 459 460 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( 461 LayerTreeHostCopyRequestTestClippedOut); 462 463 class LayerTreeHostTestAsyncTwoReadbacksWithoutDraw 464 : public LayerTreeHostCopyRequestTest { 465 protected: 466 virtual void SetupTree() OVERRIDE { 467 root_ = FakeContentLayer::Create(&client_); 468 root_->SetBounds(gfx::Size(20, 20)); 469 470 copy_layer_ = FakeContentLayer::Create(&client_); 471 copy_layer_->SetBounds(gfx::Size(10, 10)); 472 root_->AddChild(copy_layer_); 473 474 layer_tree_host()->SetRootLayer(root_); 475 LayerTreeHostCopyRequestTest::SetupTree(); 476 } 477 478 void AddCopyRequest(Layer* layer) { 479 layer->RequestCopyOfOutput( 480 CopyOutputRequest::CreateBitmapRequest(base::Bind( 481 &LayerTreeHostTestAsyncTwoReadbacksWithoutDraw::CopyOutputCallback, 482 base::Unretained(this)))); 483 } 484 485 virtual void BeginTest() OVERRIDE { 486 saw_copy_request_ = false; 487 callback_count_ = 0; 488 PostSetNeedsCommitToMainThread(); 489 490 // Prevent drawing. 491 layer_tree_host()->SetViewportSize(gfx::Size(0, 0)); 492 493 AddCopyRequest(copy_layer_.get()); 494 } 495 496 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { 497 if (impl->active_tree()->source_frame_number() == 0) { 498 LayerImpl* root = impl->active_tree()->root_layer(); 499 EXPECT_TRUE(root->children()[0]->HasCopyRequest()); 500 saw_copy_request_ = true; 501 } 502 } 503 504 virtual void DidCommit() OVERRIDE { 505 if (layer_tree_host()->source_frame_number() == 1) { 506 // Allow drawing. 507 layer_tree_host()->SetViewportSize(gfx::Size(root_->bounds())); 508 509 AddCopyRequest(copy_layer_.get()); 510 } 511 } 512 513 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { 514 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread()); 515 EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString()); 516 ++callback_count_; 517 518 if (callback_count_ == 2) 519 EndTest(); 520 } 521 522 virtual void AfterTest() OVERRIDE { EXPECT_TRUE(saw_copy_request_); } 523 524 bool saw_copy_request_; 525 int callback_count_; 526 FakeContentLayerClient client_; 527 scoped_refptr<FakeContentLayer> root_; 528 scoped_refptr<FakeContentLayer> copy_layer_; 529 }; 530 531 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F( 532 LayerTreeHostTestAsyncTwoReadbacksWithoutDraw); 533 534 class LayerTreeHostCopyRequestTestLostOutputSurface 535 : public LayerTreeHostCopyRequestTest { 536 protected: 537 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback) 538 OVERRIDE { 539 if (!first_context_provider_.get()) { 540 first_context_provider_ = TestContextProvider::Create(); 541 return FakeOutputSurface::Create3d(first_context_provider_); 542 } 543 544 EXPECT_FALSE(second_context_provider_.get()); 545 second_context_provider_ = TestContextProvider::Create(); 546 return FakeOutputSurface::Create3d(second_context_provider_); 547 } 548 549 virtual void SetupTree() OVERRIDE { 550 root_ = FakeContentLayer::Create(&client_); 551 root_->SetBounds(gfx::Size(20, 20)); 552 553 copy_layer_ = FakeContentLayer::Create(&client_); 554 copy_layer_->SetBounds(gfx::Size(10, 10)); 555 root_->AddChild(copy_layer_); 556 557 layer_tree_host()->SetRootLayer(root_); 558 LayerTreeHostCopyRequestTest::SetupTree(); 559 } 560 561 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); } 562 563 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { 564 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread()); 565 EXPECT_EQ(gfx::Size(10, 10).ToString(), result->size().ToString()); 566 EXPECT_TRUE(result->HasTexture()); 567 568 // Save the result for later. 569 EXPECT_FALSE(result_); 570 result_ = result.Pass(); 571 572 // Post a commit to lose the output surface. 573 layer_tree_host()->SetNeedsCommit(); 574 } 575 576 virtual void DidCommitAndDrawFrame() OVERRIDE { 577 switch (layer_tree_host()->source_frame_number()) { 578 case 1: 579 // The layers have been pushed to the impl side. The layer textures have 580 // been allocated. 581 582 // Request a copy of the layer. This will use another texture. 583 copy_layer_->RequestCopyOfOutput(CopyOutputRequest::CreateRequest( 584 base::Bind(&LayerTreeHostCopyRequestTestLostOutputSurface:: 585 CopyOutputCallback, 586 base::Unretained(this)))); 587 break; 588 case 4: 589 // With SingleThreadProxy it takes two commits to finally swap after a 590 // context loss. 591 case 5: 592 // Now destroy the CopyOutputResult, releasing the texture inside back 593 // to the compositor. 594 EXPECT_TRUE(result_); 595 result_.reset(); 596 597 // Check that it is released. 598 ImplThreadTaskRunner()->PostTask( 599 FROM_HERE, 600 base::Bind(&LayerTreeHostCopyRequestTestLostOutputSurface:: 601 CheckNumTextures, 602 base::Unretained(this), 603 num_textures_after_loss_ - 1)); 604 break; 605 } 606 } 607 608 virtual void SwapBuffersOnThread(LayerTreeHostImpl* impl, 609 bool result) OVERRIDE { 610 switch (impl->active_tree()->source_frame_number()) { 611 case 0: 612 // The layers have been drawn, so their textures have been allocated. 613 EXPECT_FALSE(result_); 614 num_textures_without_readback_ = 615 first_context_provider_->TestContext3d()->NumTextures(); 616 break; 617 case 1: 618 // We did a readback, so there will be a readback texture around now. 619 EXPECT_LT(num_textures_without_readback_, 620 first_context_provider_->TestContext3d()->NumTextures()); 621 break; 622 case 2: 623 // The readback texture is collected. 624 EXPECT_TRUE(result_); 625 626 // Lose the output surface. 627 first_context_provider_->TestContext3d()->loseContextCHROMIUM( 628 GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB); 629 break; 630 case 3: 631 // With SingleThreadProxy it takes two commits to finally swap after a 632 // context loss. 633 case 4: 634 // The output surface has been recreated. 635 EXPECT_TRUE(second_context_provider_.get()); 636 637 num_textures_after_loss_ = 638 first_context_provider_->TestContext3d()->NumTextures(); 639 break; 640 } 641 } 642 643 void CheckNumTextures(size_t expected_num_textures) { 644 EXPECT_EQ(expected_num_textures, 645 first_context_provider_->TestContext3d()->NumTextures()); 646 EndTest(); 647 } 648 649 virtual void AfterTest() OVERRIDE {} 650 651 scoped_refptr<TestContextProvider> first_context_provider_; 652 scoped_refptr<TestContextProvider> second_context_provider_; 653 size_t num_textures_without_readback_; 654 size_t num_textures_after_loss_; 655 FakeContentLayerClient client_; 656 scoped_refptr<FakeContentLayer> root_; 657 scoped_refptr<FakeContentLayer> copy_layer_; 658 scoped_ptr<CopyOutputResult> result_; 659 }; 660 661 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F( 662 LayerTreeHostCopyRequestTestLostOutputSurface); 663 664 class LayerTreeHostCopyRequestTestCountTextures 665 : public LayerTreeHostCopyRequestTest { 666 protected: 667 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback) 668 OVERRIDE { 669 context_provider_ = TestContextProvider::Create(); 670 return FakeOutputSurface::Create3d(context_provider_); 671 } 672 673 virtual void SetupTree() OVERRIDE { 674 root_ = FakeContentLayer::Create(&client_); 675 root_->SetBounds(gfx::Size(20, 20)); 676 677 copy_layer_ = FakeContentLayer::Create(&client_); 678 copy_layer_->SetBounds(gfx::Size(10, 10)); 679 root_->AddChild(copy_layer_); 680 681 layer_tree_host()->SetRootLayer(root_); 682 LayerTreeHostCopyRequestTest::SetupTree(); 683 } 684 685 virtual void BeginTest() OVERRIDE { 686 num_textures_without_readback_ = 0; 687 num_textures_with_readback_ = 0; 688 waited_sync_point_after_readback_ = 0; 689 PostSetNeedsCommitToMainThread(); 690 } 691 692 virtual void RequestCopy(Layer* layer) = 0; 693 694 virtual void DidCommitAndDrawFrame() OVERRIDE { 695 switch (layer_tree_host()->source_frame_number()) { 696 case 1: 697 // The layers have been pushed to the impl side. The layer textures have 698 // been allocated. 699 RequestCopy(copy_layer_.get()); 700 break; 701 } 702 } 703 704 virtual void SwapBuffersOnThread(LayerTreeHostImpl* impl, 705 bool result) OVERRIDE { 706 switch (impl->active_tree()->source_frame_number()) { 707 case 0: 708 // The layers have been drawn, so their textures have been allocated. 709 num_textures_without_readback_ = 710 context_provider_->TestContext3d()->NumTextures(); 711 break; 712 case 1: 713 // We did a readback, so there will be a readback texture around now. 714 num_textures_with_readback_ = 715 context_provider_->TestContext3d()->NumTextures(); 716 waited_sync_point_after_readback_ = 717 context_provider_->TestContext3d()->last_waited_sync_point(); 718 719 MainThreadTaskRunner()->PostTask( 720 FROM_HERE, 721 base::Bind(&LayerTreeHostCopyRequestTestCountTextures::DoEndTest, 722 base::Unretained(this))); 723 break; 724 } 725 } 726 727 virtual void DoEndTest() { EndTest(); } 728 729 scoped_refptr<TestContextProvider> context_provider_; 730 size_t num_textures_without_readback_; 731 size_t num_textures_with_readback_; 732 unsigned waited_sync_point_after_readback_; 733 FakeContentLayerClient client_; 734 scoped_refptr<FakeContentLayer> root_; 735 scoped_refptr<FakeContentLayer> copy_layer_; 736 }; 737 738 class LayerTreeHostCopyRequestTestCreatesTexture 739 : public LayerTreeHostCopyRequestTestCountTextures { 740 protected: 741 virtual void RequestCopy(Layer* layer) OVERRIDE { 742 // Request a normal texture copy. This should create a new texture. 743 copy_layer_->RequestCopyOfOutput( 744 CopyOutputRequest::CreateRequest(base::Bind( 745 &LayerTreeHostCopyRequestTestCreatesTexture::CopyOutputCallback, 746 base::Unretained(this)))); 747 } 748 749 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { 750 EXPECT_FALSE(result->IsEmpty()); 751 EXPECT_TRUE(result->HasTexture()); 752 753 TextureMailbox mailbox; 754 scoped_ptr<SingleReleaseCallback> release; 755 result->TakeTexture(&mailbox, &release); 756 EXPECT_TRUE(release); 757 758 release->Run(0, false); 759 } 760 761 virtual void AfterTest() OVERRIDE { 762 // No sync point was needed. 763 EXPECT_EQ(0u, waited_sync_point_after_readback_); 764 // Except the copy to have made another texture. 765 EXPECT_EQ(num_textures_without_readback_ + 1, num_textures_with_readback_); 766 } 767 }; 768 769 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F( 770 LayerTreeHostCopyRequestTestCreatesTexture); 771 772 class LayerTreeHostCopyRequestTestProvideTexture 773 : public LayerTreeHostCopyRequestTestCountTextures { 774 protected: 775 virtual void BeginTest() OVERRIDE { 776 external_context_provider_ = TestContextProvider::Create(); 777 EXPECT_TRUE(external_context_provider_->BindToCurrentThread()); 778 LayerTreeHostCopyRequestTestCountTextures::BeginTest(); 779 } 780 781 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { 782 EXPECT_FALSE(result->IsEmpty()); 783 EXPECT_TRUE(result->HasTexture()); 784 785 TextureMailbox mailbox; 786 scoped_ptr<SingleReleaseCallback> release; 787 result->TakeTexture(&mailbox, &release); 788 EXPECT_FALSE(release); 789 } 790 791 virtual void RequestCopy(Layer* layer) OVERRIDE { 792 // Request a copy to a provided texture. This should not create a new 793 // texture. 794 scoped_ptr<CopyOutputRequest> request = 795 CopyOutputRequest::CreateRequest(base::Bind( 796 &LayerTreeHostCopyRequestTestProvideTexture::CopyOutputCallback, 797 base::Unretained(this))); 798 799 gpu::gles2::GLES2Interface* gl = external_context_provider_->ContextGL(); 800 gpu::Mailbox mailbox; 801 gl->GenMailboxCHROMIUM(mailbox.name); 802 sync_point_ = gl->InsertSyncPointCHROMIUM(); 803 request->SetTextureMailbox( 804 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point_)); 805 EXPECT_TRUE(request->has_texture_mailbox()); 806 807 copy_layer_->RequestCopyOfOutput(request.Pass()); 808 } 809 810 virtual void AfterTest() OVERRIDE { 811 // Expect the compositor to have waited for the sync point in the provided 812 // TextureMailbox. 813 EXPECT_EQ(sync_point_, waited_sync_point_after_readback_); 814 // Except the copy to have *not* made another texture. 815 EXPECT_EQ(num_textures_without_readback_, num_textures_with_readback_); 816 } 817 818 scoped_refptr<TestContextProvider> external_context_provider_; 819 unsigned sync_point_; 820 }; 821 822 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F( 823 LayerTreeHostCopyRequestTestProvideTexture); 824 825 class LayerTreeHostCopyRequestTestDestroyBeforeCopy 826 : public LayerTreeHostCopyRequestTest { 827 protected: 828 virtual void SetupTree() OVERRIDE { 829 root_ = FakeContentLayer::Create(&client_); 830 root_->SetBounds(gfx::Size(20, 20)); 831 832 copy_layer_ = FakeContentLayer::Create(&client_); 833 copy_layer_->SetBounds(gfx::Size(10, 10)); 834 root_->AddChild(copy_layer_); 835 836 layer_tree_host()->SetRootLayer(root_); 837 LayerTreeHostCopyRequestTest::SetupTree(); 838 } 839 840 virtual void BeginTest() OVERRIDE { 841 callback_count_ = 0; 842 PostSetNeedsCommitToMainThread(); 843 } 844 845 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { 846 EXPECT_TRUE(result->IsEmpty()); 847 ++callback_count_; 848 } 849 850 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { 851 MainThreadTaskRunner()->PostTask( 852 FROM_HERE, 853 base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::DidActivate, 854 base::Unretained(this))); 855 } 856 857 void DidActivate() { 858 switch (layer_tree_host()->source_frame_number()) { 859 case 1: { 860 EXPECT_EQ(0, callback_count_); 861 // Put a copy request on the layer, but then don't allow any 862 // drawing to take place. 863 scoped_ptr<CopyOutputRequest> request = 864 CopyOutputRequest::CreateRequest( 865 base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy:: 866 CopyOutputCallback, 867 base::Unretained(this))); 868 copy_layer_->RequestCopyOfOutput(request.Pass()); 869 870 layer_tree_host()->SetViewportSize(gfx::Size()); 871 break; 872 } 873 case 2: 874 EXPECT_EQ(0, callback_count_); 875 // Remove the copy layer before we were able to draw. 876 copy_layer_->RemoveFromParent(); 877 break; 878 case 3: 879 EXPECT_EQ(1, callback_count_); 880 // Allow us to draw now. 881 layer_tree_host()->SetViewportSize( 882 layer_tree_host()->root_layer()->bounds()); 883 break; 884 case 4: 885 EXPECT_EQ(1, callback_count_); 886 // We should not have crashed. 887 EndTest(); 888 } 889 } 890 891 virtual void AfterTest() OVERRIDE {} 892 893 int callback_count_; 894 FakeContentLayerClient client_; 895 scoped_refptr<FakeContentLayer> root_; 896 scoped_refptr<FakeContentLayer> copy_layer_; 897 }; 898 899 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( 900 LayerTreeHostCopyRequestTestDestroyBeforeCopy); 901 902 class LayerTreeHostCopyRequestTestShutdownBeforeCopy 903 : public LayerTreeHostCopyRequestTest { 904 protected: 905 virtual void SetupTree() OVERRIDE { 906 root_ = FakeContentLayer::Create(&client_); 907 root_->SetBounds(gfx::Size(20, 20)); 908 909 copy_layer_ = FakeContentLayer::Create(&client_); 910 copy_layer_->SetBounds(gfx::Size(10, 10)); 911 root_->AddChild(copy_layer_); 912 913 layer_tree_host()->SetRootLayer(root_); 914 LayerTreeHostCopyRequestTest::SetupTree(); 915 } 916 917 virtual void BeginTest() OVERRIDE { 918 callback_count_ = 0; 919 PostSetNeedsCommitToMainThread(); 920 } 921 922 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { 923 EXPECT_TRUE(result->IsEmpty()); 924 ++callback_count_; 925 } 926 927 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { 928 MainThreadTaskRunner()->PostTask( 929 FROM_HERE, 930 base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::DidActivate, 931 base::Unretained(this))); 932 } 933 934 void DidActivate() { 935 switch (layer_tree_host()->source_frame_number()) { 936 case 1: { 937 EXPECT_EQ(0, callback_count_); 938 // Put a copy request on the layer, but then don't allow any 939 // drawing to take place. 940 scoped_ptr<CopyOutputRequest> request = 941 CopyOutputRequest::CreateRequest( 942 base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy:: 943 CopyOutputCallback, 944 base::Unretained(this))); 945 copy_layer_->RequestCopyOfOutput(request.Pass()); 946 947 layer_tree_host()->SetViewportSize(gfx::Size()); 948 break; 949 } 950 case 2: 951 DestroyLayerTreeHost(); 952 // End the test after the copy result has had a chance to get back to 953 // the main thread. 954 MainThreadTaskRunner()->PostTask( 955 FROM_HERE, 956 base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::EndTest, 957 base::Unretained(this))); 958 break; 959 } 960 } 961 962 virtual void AfterTest() OVERRIDE { EXPECT_EQ(1, callback_count_); } 963 964 int callback_count_; 965 FakeContentLayerClient client_; 966 scoped_refptr<FakeContentLayer> root_; 967 scoped_refptr<FakeContentLayer> copy_layer_; 968 }; 969 970 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( 971 LayerTreeHostCopyRequestTestShutdownBeforeCopy); 972 973 } // namespace 974 } // namespace cc 975