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/layers/texture_layer.h" 6 7 #include <algorithm> 8 #include <string> 9 10 #include "base/bind.h" 11 #include "base/callback.h" 12 #include "base/synchronization/waitable_event.h" 13 #include "base/threading/thread.h" 14 #include "base/time/time.h" 15 #include "cc/layers/solid_color_layer.h" 16 #include "cc/layers/texture_layer_client.h" 17 #include "cc/layers/texture_layer_impl.h" 18 #include "cc/output/compositor_frame_ack.h" 19 #include "cc/output/context_provider.h" 20 #include "cc/resources/returned_resource.h" 21 #include "cc/test/fake_impl_proxy.h" 22 #include "cc/test/fake_layer_tree_host_client.h" 23 #include "cc/test/fake_layer_tree_host_impl.h" 24 #include "cc/test/fake_output_surface.h" 25 #include "cc/test/layer_test_common.h" 26 #include "cc/test/layer_tree_test.h" 27 #include "cc/test/test_web_graphics_context_3d.h" 28 #include "cc/trees/blocking_task_runner.h" 29 #include "cc/trees/layer_tree_host.h" 30 #include "cc/trees/layer_tree_impl.h" 31 #include "cc/trees/single_thread_proxy.h" 32 #include "gpu/GLES2/gl2extchromium.h" 33 #include "testing/gmock/include/gmock/gmock.h" 34 #include "testing/gtest/include/gtest/gtest.h" 35 36 using ::testing::Mock; 37 using ::testing::_; 38 using ::testing::AtLeast; 39 using ::testing::AnyNumber; 40 using ::testing::InvokeWithoutArgs; 41 42 namespace cc { 43 namespace { 44 45 gpu::Mailbox MailboxFromChar(char value) { 46 gpu::Mailbox mailbox; 47 memset(mailbox.name, value, sizeof(mailbox.name)); 48 return mailbox; 49 } 50 51 class MockLayerTreeHost : public LayerTreeHost { 52 public: 53 explicit MockLayerTreeHost(FakeLayerTreeHostClient* client) 54 : LayerTreeHost(client, NULL, LayerTreeSettings()) { 55 InitializeSingleThreaded(client); 56 } 57 58 MOCK_METHOD0(SetNeedsCommit, void()); 59 MOCK_METHOD0(SetNeedsUpdateLayers, void()); 60 MOCK_METHOD0(StartRateLimiter, void()); 61 MOCK_METHOD0(StopRateLimiter, void()); 62 }; 63 64 class FakeTextureLayerClient : public TextureLayerClient { 65 public: 66 FakeTextureLayerClient() : mailbox_changed_(true) {} 67 68 virtual bool PrepareTextureMailbox( 69 TextureMailbox* mailbox, 70 scoped_ptr<SingleReleaseCallback>* release_callback, 71 bool use_shared_memory) OVERRIDE { 72 if (!mailbox_changed_) 73 return false; 74 75 *mailbox = mailbox_; 76 *release_callback = release_callback_.Pass(); 77 mailbox_changed_ = false; 78 return true; 79 } 80 81 void set_mailbox(const TextureMailbox& mailbox, 82 scoped_ptr<SingleReleaseCallback> release_callback) { 83 mailbox_ = mailbox; 84 release_callback_ = release_callback.Pass(); 85 mailbox_changed_ = true; 86 } 87 88 private: 89 TextureMailbox mailbox_; 90 scoped_ptr<SingleReleaseCallback> release_callback_; 91 bool mailbox_changed_; 92 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient); 93 }; 94 95 class MockMailboxCallback { 96 public: 97 MOCK_METHOD3(Release, 98 void(const gpu::Mailbox& mailbox, 99 uint32 sync_point, 100 bool lost_resource)); 101 MOCK_METHOD3(Release2, 102 void(base::SharedMemory* shared_memory, 103 uint32 sync_point, 104 bool lost_resource)); 105 }; 106 107 struct CommonMailboxObjects { 108 CommonMailboxObjects() 109 : mailbox_name1_(MailboxFromChar('1')), 110 mailbox_name2_(MailboxFromChar('2')), 111 sync_point1_(1), 112 sync_point2_(2), 113 shared_memory_(new base::SharedMemory) { 114 release_mailbox1_ = base::Bind(&MockMailboxCallback::Release, 115 base::Unretained(&mock_callback_), 116 mailbox_name1_); 117 release_mailbox2_ = base::Bind(&MockMailboxCallback::Release, 118 base::Unretained(&mock_callback_), 119 mailbox_name2_); 120 const uint32 arbitrary_target1 = GL_TEXTURE_2D; 121 const uint32 arbitrary_target2 = GL_TEXTURE_EXTERNAL_OES; 122 mailbox1_ = TextureMailbox(mailbox_name1_, arbitrary_target1, sync_point1_); 123 mailbox2_ = TextureMailbox(mailbox_name2_, arbitrary_target2, sync_point2_); 124 gfx::Size size(128, 128); 125 EXPECT_TRUE(shared_memory_->CreateAndMapAnonymous(4 * size.GetArea())); 126 release_mailbox3_ = base::Bind(&MockMailboxCallback::Release2, 127 base::Unretained(&mock_callback_), 128 shared_memory_.get()); 129 mailbox3_ = TextureMailbox(shared_memory_.get(), size); 130 } 131 132 gpu::Mailbox mailbox_name1_; 133 gpu::Mailbox mailbox_name2_; 134 MockMailboxCallback mock_callback_; 135 ReleaseCallback release_mailbox1_; 136 ReleaseCallback release_mailbox2_; 137 ReleaseCallback release_mailbox3_; 138 TextureMailbox mailbox1_; 139 TextureMailbox mailbox2_; 140 TextureMailbox mailbox3_; 141 uint32 sync_point1_; 142 uint32 sync_point2_; 143 scoped_ptr<base::SharedMemory> shared_memory_; 144 }; 145 146 class TextureLayerTest : public testing::Test { 147 public: 148 TextureLayerTest() 149 : fake_client_( 150 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)), 151 host_impl_(&proxy_, &shared_bitmap_manager_) {} 152 153 protected: 154 virtual void SetUp() { 155 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_)); 156 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); 157 layer_tree_host_->SetViewportSize(gfx::Size(10, 10)); 158 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 159 } 160 161 virtual void TearDown() { 162 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 163 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); 164 165 layer_tree_host_->SetRootLayer(NULL); 166 layer_tree_host_.reset(); 167 } 168 169 scoped_ptr<MockLayerTreeHost> layer_tree_host_; 170 FakeImplProxy proxy_; 171 FakeLayerTreeHostClient fake_client_; 172 TestSharedBitmapManager shared_bitmap_manager_; 173 FakeLayerTreeHostImpl host_impl_; 174 }; 175 176 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) { 177 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL); 178 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer)); 179 180 // Test properties that should call SetNeedsCommit. All properties need to 181 // be set to new values in order for SetNeedsCommit to be called. 182 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false)); 183 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV( 184 gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f))); 185 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity( 186 0.5f, 0.5f, 0.5f, 0.5f)); 187 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false)); 188 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true)); 189 } 190 191 TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) { 192 const gfx::Size layer_bounds(100, 100); 193 const gfx::Rect layer_rect(layer_bounds); 194 const Region layer_region(layer_rect); 195 196 scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(NULL); 197 layer->SetBounds(layer_bounds); 198 layer->draw_properties().visible_content_rect = layer_rect; 199 layer->SetBlendBackgroundColor(true); 200 201 // Verify initial conditions. 202 EXPECT_FALSE(layer->contents_opaque()); 203 EXPECT_EQ(0u, layer->background_color()); 204 EXPECT_EQ(Region().ToString(), 205 layer->VisibleContentOpaqueRegion().ToString()); 206 207 // Opaque background. 208 layer->SetBackgroundColor(SK_ColorWHITE); 209 EXPECT_EQ(layer_region.ToString(), 210 layer->VisibleContentOpaqueRegion().ToString()); 211 212 // Transparent background. 213 layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255)); 214 EXPECT_EQ(Region().ToString(), 215 layer->VisibleContentOpaqueRegion().ToString()); 216 } 217 218 TEST_F(TextureLayerTest, RateLimiter) { 219 FakeTextureLayerClient client; 220 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox( 221 &client); 222 test_layer->SetIsDrawable(true); 223 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); 224 layer_tree_host_->SetRootLayer(test_layer); 225 226 // Don't rate limit until we invalidate. 227 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0); 228 test_layer->SetRateLimitContext(true); 229 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 230 231 // Do rate limit after we invalidate. 232 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()); 233 test_layer->SetNeedsDisplay(); 234 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 235 236 // Stop rate limiter when we don't want it any more. 237 EXPECT_CALL(*layer_tree_host_, StopRateLimiter()); 238 test_layer->SetRateLimitContext(false); 239 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 240 241 // Or we clear the client. 242 test_layer->SetRateLimitContext(true); 243 EXPECT_CALL(*layer_tree_host_, StopRateLimiter()); 244 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); 245 test_layer->ClearClient(); 246 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 247 248 // Reset to a layer with a client, that started the rate limiter. 249 test_layer = TextureLayer::CreateForMailbox( 250 &client); 251 test_layer->SetIsDrawable(true); 252 test_layer->SetRateLimitContext(true); 253 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); 254 layer_tree_host_->SetRootLayer(test_layer); 255 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0); 256 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 257 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()); 258 test_layer->SetNeedsDisplay(); 259 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 260 261 // Stop rate limiter when we're removed from the tree. 262 EXPECT_CALL(*layer_tree_host_, StopRateLimiter()); 263 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); 264 layer_tree_host_->SetRootLayer(NULL); 265 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 266 } 267 268 class TestMailboxHolder : public TextureLayer::TextureMailboxHolder { 269 public: 270 using TextureLayer::TextureMailboxHolder::Create; 271 272 protected: 273 virtual ~TestMailboxHolder() {} 274 }; 275 276 class TextureLayerWithMailboxTest : public TextureLayerTest { 277 protected: 278 virtual void TearDown() { 279 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 280 EXPECT_CALL(test_data_.mock_callback_, 281 Release(test_data_.mailbox_name1_, 282 test_data_.sync_point1_, 283 false)).Times(1); 284 TextureLayerTest::TearDown(); 285 } 286 287 CommonMailboxObjects test_data_; 288 }; 289 290 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) { 291 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL); 292 ASSERT_TRUE(test_layer.get()); 293 294 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); 295 layer_tree_host_->SetRootLayer(test_layer); 296 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 297 298 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); 299 test_layer->SetTextureMailbox( 300 test_data_.mailbox1_, 301 SingleReleaseCallback::Create(test_data_.release_mailbox1_)); 302 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 303 304 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); 305 EXPECT_CALL(test_data_.mock_callback_, 306 Release(test_data_.mailbox_name1_, 307 test_data_.sync_point1_, 308 false)) 309 .Times(1); 310 test_layer->SetTextureMailbox( 311 test_data_.mailbox2_, 312 SingleReleaseCallback::Create(test_data_.release_mailbox2_)); 313 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 314 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 315 316 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); 317 EXPECT_CALL(test_data_.mock_callback_, 318 Release(test_data_.mailbox_name2_, 319 test_data_.sync_point2_, 320 false)) 321 .Times(1); 322 test_layer->SetTextureMailbox(TextureMailbox(), 323 scoped_ptr<SingleReleaseCallback>()); 324 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 325 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 326 327 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); 328 test_layer->SetTextureMailbox( 329 test_data_.mailbox3_, 330 SingleReleaseCallback::Create(test_data_.release_mailbox3_)); 331 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 332 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 333 334 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); 335 EXPECT_CALL(test_data_.mock_callback_, 336 Release2(test_data_.shared_memory_.get(), 337 0, false)) 338 .Times(1); 339 test_layer->SetTextureMailbox(TextureMailbox(), 340 scoped_ptr<SingleReleaseCallback>()); 341 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 342 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 343 344 // Test destructor. 345 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); 346 test_layer->SetTextureMailbox( 347 test_data_.mailbox1_, 348 SingleReleaseCallback::Create(test_data_.release_mailbox1_)); 349 } 350 351 TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) { 352 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL); 353 ASSERT_TRUE(test_layer.get()); 354 355 // These use the same gpu::Mailbox, but different sync points. 356 TextureMailbox mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D, 1); 357 TextureMailbox mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D, 2); 358 359 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); 360 layer_tree_host_->SetRootLayer(test_layer); 361 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 362 363 // Set the mailbox the first time. It should cause a commit. 364 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); 365 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox1); 366 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 367 368 // Set the mailbox again with a new sync point, as the backing texture has 369 // been updated. It should cause a new commit. 370 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); 371 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox2); 372 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); 373 } 374 375 class TextureLayerMailboxHolderTest : public TextureLayerTest { 376 public: 377 TextureLayerMailboxHolderTest() 378 : main_thread_("MAIN") { 379 main_thread_.Start(); 380 } 381 382 void Wait(const base::Thread& thread) { 383 bool manual_reset = false; 384 bool initially_signaled = false; 385 base::WaitableEvent event(manual_reset, initially_signaled); 386 thread.message_loop()->PostTask( 387 FROM_HERE, 388 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event))); 389 event.Wait(); 390 } 391 392 void CreateMainRef() { 393 main_ref_ = TestMailboxHolder::Create( 394 test_data_.mailbox1_, 395 SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass(); 396 } 397 398 void ReleaseMainRef() { 399 main_ref_.reset(); 400 } 401 402 void CreateImplRef(scoped_ptr<SingleReleaseCallback>* impl_ref) { 403 *impl_ref = main_ref_->holder()->GetCallbackForImplThread(); 404 } 405 406 void CapturePostTasksAndWait(base::WaitableEvent* begin_capture, 407 base::WaitableEvent* wait_for_capture, 408 base::WaitableEvent* stop_capture) { 409 begin_capture->Wait(); 410 BlockingTaskRunner::CapturePostTasks capture; 411 wait_for_capture->Signal(); 412 stop_capture->Wait(); 413 } 414 415 protected: 416 scoped_ptr<TestMailboxHolder::MainThreadReference> 417 main_ref_; 418 base::Thread main_thread_; 419 CommonMailboxObjects test_data_; 420 }; 421 422 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) { 423 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL); 424 ASSERT_TRUE(test_layer.get()); 425 426 main_thread_.message_loop()->PostTask( 427 FROM_HERE, 428 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef, 429 base::Unretained(this))); 430 431 Wait(main_thread_); 432 433 // The texture layer is attached to compositor1, and passes a reference to its 434 // impl tree. 435 scoped_ptr<SingleReleaseCallback> compositor1; 436 main_thread_.message_loop()->PostTask( 437 FROM_HERE, 438 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, 439 base::Unretained(this), 440 &compositor1)); 441 442 // Then the texture layer is removed and attached to compositor2, and passes a 443 // reference to its impl tree. 444 scoped_ptr<SingleReleaseCallback> compositor2; 445 main_thread_.message_loop()->PostTask( 446 FROM_HERE, 447 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, 448 base::Unretained(this), 449 &compositor2)); 450 451 Wait(main_thread_); 452 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 453 454 // The compositors both destroy their impl trees before the main thread layer 455 // is destroyed. 456 compositor1->Run(100, false); 457 compositor2->Run(200, false); 458 459 Wait(main_thread_); 460 461 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); 462 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 463 464 // The main thread ref is the last one, so the mailbox is released back to the 465 // embedder, with the last sync point provided by the impl trees. 466 EXPECT_CALL(test_data_.mock_callback_, 467 Release(test_data_.mailbox_name1_, 200, false)).Times(1); 468 469 main_thread_.message_loop()->PostTask( 470 FROM_HERE, 471 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef, 472 base::Unretained(this))); 473 Wait(main_thread_); 474 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 475 } 476 477 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) { 478 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL); 479 ASSERT_TRUE(test_layer.get()); 480 481 main_thread_.message_loop()->PostTask( 482 FROM_HERE, 483 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef, 484 base::Unretained(this))); 485 486 Wait(main_thread_); 487 488 // The texture layer is attached to compositor1, and passes a reference to its 489 // impl tree. 490 scoped_ptr<SingleReleaseCallback> compositor1; 491 main_thread_.message_loop()->PostTask( 492 FROM_HERE, 493 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, 494 base::Unretained(this), 495 &compositor1)); 496 497 // Then the texture layer is removed and attached to compositor2, and passes a 498 // reference to its impl tree. 499 scoped_ptr<SingleReleaseCallback> compositor2; 500 main_thread_.message_loop()->PostTask( 501 FROM_HERE, 502 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, 503 base::Unretained(this), 504 &compositor2)); 505 506 Wait(main_thread_); 507 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 508 509 // One compositor destroys their impl tree. 510 compositor1->Run(100, false); 511 512 // Then the main thread reference is destroyed. 513 main_thread_.message_loop()->PostTask( 514 FROM_HERE, 515 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef, 516 base::Unretained(this))); 517 518 Wait(main_thread_); 519 520 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); 521 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 522 523 // The second impl reference is destroyed last, causing the mailbox to be 524 // released back to the embedder with the last sync point from the impl tree. 525 EXPECT_CALL(test_data_.mock_callback_, 526 Release(test_data_.mailbox_name1_, 200, true)).Times(1); 527 528 compositor2->Run(200, true); 529 Wait(main_thread_); 530 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 531 } 532 533 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) { 534 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL); 535 ASSERT_TRUE(test_layer.get()); 536 537 main_thread_.message_loop()->PostTask( 538 FROM_HERE, 539 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef, 540 base::Unretained(this))); 541 542 Wait(main_thread_); 543 544 // The texture layer is attached to compositor1, and passes a reference to its 545 // impl tree. 546 scoped_ptr<SingleReleaseCallback> compositor1; 547 main_thread_.message_loop()->PostTask( 548 FROM_HERE, 549 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, 550 base::Unretained(this), 551 &compositor1)); 552 553 // Then the texture layer is removed and attached to compositor2, and passes a 554 // reference to its impl tree. 555 scoped_ptr<SingleReleaseCallback> compositor2; 556 main_thread_.message_loop()->PostTask( 557 FROM_HERE, 558 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, 559 base::Unretained(this), 560 &compositor2)); 561 562 Wait(main_thread_); 563 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 564 565 // The main thread reference is destroyed first. 566 main_thread_.message_loop()->PostTask( 567 FROM_HERE, 568 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef, 569 base::Unretained(this))); 570 571 // One compositor destroys their impl tree. 572 compositor2->Run(200, false); 573 574 Wait(main_thread_); 575 576 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); 577 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 578 579 // The second impl reference is destroyed last, causing the mailbox to be 580 // released back to the embedder with the last sync point from the impl tree. 581 EXPECT_CALL(test_data_.mock_callback_, 582 Release(test_data_.mailbox_name1_, 100, true)).Times(1); 583 584 compositor1->Run(100, true); 585 Wait(main_thread_); 586 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 587 } 588 589 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) { 590 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL); 591 ASSERT_TRUE(test_layer.get()); 592 593 main_thread_.message_loop()->PostTask( 594 FROM_HERE, 595 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef, 596 base::Unretained(this))); 597 598 Wait(main_thread_); 599 600 // The texture layer is attached to compositor1, and passes a reference to its 601 // impl tree. 602 scoped_ptr<SingleReleaseCallback> compositor1; 603 main_thread_.message_loop()->PostTask( 604 FROM_HERE, 605 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, 606 base::Unretained(this), 607 &compositor1)); 608 609 // Then the texture layer is removed and attached to compositor2, and passes a 610 // reference to its impl tree. 611 scoped_ptr<SingleReleaseCallback> compositor2; 612 main_thread_.message_loop()->PostTask( 613 FROM_HERE, 614 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, 615 base::Unretained(this), 616 &compositor2)); 617 618 Wait(main_thread_); 619 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 620 621 // The main thread reference is destroyed first. 622 main_thread_.message_loop()->PostTask( 623 FROM_HERE, 624 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef, 625 base::Unretained(this))); 626 627 EXPECT_CALL(test_data_.mock_callback_, 628 Release(test_data_.mailbox_name1_, 200, true)).Times(1); 629 630 bool manual_reset = false; 631 bool initially_signaled = false; 632 base::WaitableEvent begin_capture(manual_reset, initially_signaled); 633 base::WaitableEvent wait_for_capture(manual_reset, initially_signaled); 634 base::WaitableEvent stop_capture(manual_reset, initially_signaled); 635 636 // Post a task to start capturing tasks on the main thread. This will block 637 // the main thread until we signal the |stop_capture| event. 638 main_thread_.message_loop()->PostTask( 639 FROM_HERE, 640 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait, 641 base::Unretained(this), 642 &begin_capture, 643 &wait_for_capture, 644 &stop_capture)); 645 646 // Before the main thread capturing starts, one compositor destroys their 647 // impl reference. Since capturing did not start, this gets post-tasked to 648 // the main thread. 649 compositor1->Run(100, false); 650 651 // Start capturing on the main thread. 652 begin_capture.Signal(); 653 wait_for_capture.Wait(); 654 655 // Meanwhile, the second compositor released its impl reference, but this task 656 // gets shortcutted directly to the main thread. This means the reference is 657 // released before compositor1, whose reference will be released later when 658 // the post-task is serviced. But since it was destroyed _on the impl thread_ 659 // last, its sync point values should be used. 660 compositor2->Run(200, true); 661 662 stop_capture.Signal(); 663 Wait(main_thread_); 664 665 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 666 } 667 668 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest { 669 public: 670 TextureLayerImplWithMailboxThreadedCallback() 671 : callback_count_(0), 672 commit_count_(0) {} 673 674 // Make sure callback is received on main and doesn't block the impl thread. 675 void ReleaseCallback(uint32 sync_point, bool lost_resource) { 676 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); 677 EXPECT_FALSE(lost_resource); 678 ++callback_count_; 679 } 680 681 void SetMailbox(char mailbox_char) { 682 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); 683 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( 684 base::Bind( 685 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback, 686 base::Unretained(this))); 687 layer_->SetTextureMailbox( 688 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0), 689 callback.Pass()); 690 } 691 692 virtual void BeginTest() OVERRIDE { 693 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); 694 695 gfx::Size bounds(100, 100); 696 root_ = Layer::Create(); 697 root_->SetBounds(bounds); 698 699 layer_ = TextureLayer::CreateForMailbox(NULL); 700 layer_->SetIsDrawable(true); 701 layer_->SetBounds(bounds); 702 703 root_->AddChild(layer_); 704 layer_tree_host()->SetRootLayer(root_); 705 layer_tree_host()->SetViewportSize(bounds); 706 SetMailbox('1'); 707 EXPECT_EQ(0, callback_count_); 708 709 // Case #1: change mailbox before the commit. The old mailbox should be 710 // released immediately. 711 SetMailbox('2'); 712 EXPECT_EQ(1, callback_count_); 713 PostSetNeedsCommitToMainThread(); 714 } 715 716 virtual void DidCommit() OVERRIDE { 717 ++commit_count_; 718 switch (commit_count_) { 719 case 1: 720 // Case #2: change mailbox after the commit (and draw), where the 721 // layer draws. The old mailbox should be released during the next 722 // commit. 723 SetMailbox('3'); 724 EXPECT_EQ(1, callback_count_); 725 break; 726 case 2: 727 EXPECT_EQ(2, callback_count_); 728 // Case #3: change mailbox when the layer doesn't draw. The old 729 // mailbox should be released during the next commit. 730 layer_->SetBounds(gfx::Size()); 731 SetMailbox('4'); 732 break; 733 case 3: 734 EXPECT_EQ(3, callback_count_); 735 // Case #4: release mailbox that was committed but never drawn. The 736 // old mailbox should be released during the next commit. 737 layer_->SetTextureMailbox(TextureMailbox(), 738 scoped_ptr<SingleReleaseCallback>()); 739 break; 740 case 4: 741 if (layer_tree_host()->settings().impl_side_painting) { 742 // With impl painting, the texture mailbox will still be on the impl 743 // thread when the commit finishes, because the layer is not drawble 744 // when it has no texture mailbox, and thus does not block the commit 745 // on activation. So, we wait for activation. 746 // TODO(danakj): fix this. crbug.com/277953 747 layer_tree_host()->SetNeedsCommit(); 748 break; 749 } else { 750 ++commit_count_; 751 } 752 case 5: 753 EXPECT_EQ(4, callback_count_); 754 // Restore a mailbox for the next step. 755 SetMailbox('5'); 756 break; 757 case 6: 758 // Case #5: remove layer from tree. Callback should *not* be called, the 759 // mailbox is returned to the main thread. 760 EXPECT_EQ(4, callback_count_); 761 layer_->RemoveFromParent(); 762 break; 763 case 7: 764 if (layer_tree_host()->settings().impl_side_painting) { 765 // With impl painting, the texture mailbox will still be on the impl 766 // thread when the commit finishes, because the layer is not around to 767 // block the commit on activation anymore. So, we wait for activation. 768 // TODO(danakj): fix this. crbug.com/277953 769 layer_tree_host()->SetNeedsCommit(); 770 break; 771 } else { 772 ++commit_count_; 773 } 774 case 8: 775 EXPECT_EQ(4, callback_count_); 776 // Resetting the mailbox will call the callback now. 777 layer_->SetTextureMailbox(TextureMailbox(), 778 scoped_ptr<SingleReleaseCallback>()); 779 EXPECT_EQ(5, callback_count_); 780 EndTest(); 781 break; 782 default: 783 NOTREACHED(); 784 break; 785 } 786 } 787 788 virtual void AfterTest() OVERRIDE {} 789 790 private: 791 base::ThreadChecker main_thread_; 792 int callback_count_; 793 int commit_count_; 794 scoped_refptr<Layer> root_; 795 scoped_refptr<TextureLayer> layer_; 796 }; 797 798 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( 799 TextureLayerImplWithMailboxThreadedCallback); 800 801 802 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest { 803 protected: 804 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {} 805 806 static void ReleaseCallback(uint32 sync_point, bool lost_resource) {} 807 808 void SetMailbox(char mailbox_char) { 809 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( 810 base::Bind( 811 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback)); 812 layer_->SetTextureMailbox( 813 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0), 814 callback.Pass()); 815 } 816 817 virtual void BeginTest() OVERRIDE { 818 gfx::Size bounds(100, 100); 819 root_ = Layer::Create(); 820 root_->SetBounds(bounds); 821 822 layer_ = TextureLayer::CreateForMailbox(NULL); 823 layer_->SetIsDrawable(true); 824 layer_->SetBounds(bounds); 825 826 root_->AddChild(layer_); 827 layer_tree_host()->SetRootLayer(root_); 828 layer_tree_host()->SetViewportSize(bounds); 829 SetMailbox('1'); 830 831 PostSetNeedsCommitToMainThread(); 832 } 833 834 virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE { 835 ++activate_count_; 836 } 837 838 virtual void DidCommit() OVERRIDE { 839 switch (layer_tree_host()->source_frame_number()) { 840 case 1: 841 // The first mailbox has been activated. Set a new mailbox, and 842 // expect the next commit to finish *after* it is activated. 843 SetMailbox('2'); 844 break; 845 case 2: 846 // The second mailbox has been activated. Remove the layer from 847 // the tree to cause another commit/activation. The commit should 848 // finish *after* the layer is removed from the active tree. 849 layer_->RemoveFromParent(); 850 break; 851 case 3: 852 EndTest(); 853 break; 854 } 855 } 856 857 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { 858 switch (host_impl->active_tree()->source_frame_number()) { 859 case 2: { 860 // The activate for the 2nd mailbox should have happened before now. 861 EXPECT_EQ(2, activate_count_); 862 break; 863 } 864 case 3: { 865 // The activate to remove the layer should have happened before now. 866 EXPECT_EQ(3, activate_count_); 867 break; 868 } 869 } 870 } 871 872 873 virtual void AfterTest() OVERRIDE {} 874 875 int activate_count_; 876 scoped_refptr<Layer> root_; 877 scoped_refptr<TextureLayer> layer_; 878 }; 879 880 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( 881 TextureLayerMailboxIsActivatedDuringCommit); 882 883 class TextureLayerImplWithMailboxTest : public TextureLayerTest { 884 protected: 885 TextureLayerImplWithMailboxTest() 886 : fake_client_( 887 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {} 888 889 virtual void SetUp() { 890 TextureLayerTest::SetUp(); 891 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_)); 892 EXPECT_TRUE(host_impl_.InitializeRenderer( 893 FakeOutputSurface::Create3d().PassAs<OutputSurface>())); 894 } 895 896 bool WillDraw(TextureLayerImpl* layer, DrawMode mode) { 897 bool will_draw = layer->WillDraw( 898 mode, host_impl_.active_tree()->resource_provider()); 899 if (will_draw) 900 layer->DidDraw(host_impl_.active_tree()->resource_provider()); 901 return will_draw; 902 } 903 904 CommonMailboxObjects test_data_; 905 FakeLayerTreeHostClient fake_client_; 906 }; 907 908 // Test conditions for results of TextureLayerImpl::WillDraw under 909 // different configurations of different mailbox, texture_id, and draw_mode. 910 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) { 911 EXPECT_CALL(test_data_.mock_callback_, 912 Release(test_data_.mailbox_name1_, 913 test_data_.sync_point1_, 914 false)) 915 .Times(AnyNumber()); 916 EXPECT_CALL(test_data_.mock_callback_, 917 Release2(test_data_.shared_memory_.get(), 0, false)) 918 .Times(AnyNumber()); 919 // Hardware mode. 920 { 921 scoped_ptr<TextureLayerImpl> impl_layer = 922 TextureLayerImpl::Create(host_impl_.active_tree(), 1); 923 impl_layer->SetTextureMailbox( 924 test_data_.mailbox1_, 925 SingleReleaseCallback::Create(test_data_.release_mailbox1_)); 926 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE)); 927 } 928 929 { 930 scoped_ptr<TextureLayerImpl> impl_layer = 931 TextureLayerImpl::Create(host_impl_.active_tree(), 1); 932 impl_layer->SetTextureMailbox(TextureMailbox(), 933 scoped_ptr<SingleReleaseCallback>()); 934 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE)); 935 } 936 937 { 938 // Software resource. 939 scoped_ptr<TextureLayerImpl> impl_layer = 940 TextureLayerImpl::Create(host_impl_.active_tree(), 1); 941 impl_layer->SetTextureMailbox( 942 test_data_.mailbox3_, 943 SingleReleaseCallback::Create(test_data_.release_mailbox3_)); 944 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE)); 945 } 946 947 // Software mode. 948 { 949 scoped_ptr<TextureLayerImpl> impl_layer = 950 TextureLayerImpl::Create(host_impl_.active_tree(), 1); 951 impl_layer->SetTextureMailbox( 952 test_data_.mailbox1_, 953 SingleReleaseCallback::Create(test_data_.release_mailbox1_)); 954 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE)); 955 } 956 957 { 958 scoped_ptr<TextureLayerImpl> impl_layer = 959 TextureLayerImpl::Create(host_impl_.active_tree(), 1); 960 impl_layer->SetTextureMailbox(TextureMailbox(), 961 scoped_ptr<SingleReleaseCallback>()); 962 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE)); 963 } 964 965 { 966 // Software resource. 967 scoped_ptr<TextureLayerImpl> impl_layer = 968 TextureLayerImpl::Create(host_impl_.active_tree(), 1); 969 impl_layer->SetTextureMailbox( 970 test_data_.mailbox3_, 971 SingleReleaseCallback::Create(test_data_.release_mailbox3_)); 972 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE)); 973 } 974 975 // Resourceless software mode. 976 { 977 scoped_ptr<TextureLayerImpl> impl_layer = 978 TextureLayerImpl::Create(host_impl_.active_tree(), 1); 979 impl_layer->SetTextureMailbox( 980 test_data_.mailbox1_, 981 SingleReleaseCallback::Create(test_data_.release_mailbox1_)); 982 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE)); 983 } 984 } 985 986 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) { 987 host_impl_.CreatePendingTree(); 988 scoped_ptr<TextureLayerImpl> pending_layer; 989 pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1); 990 ASSERT_TRUE(pending_layer); 991 992 scoped_ptr<LayerImpl> active_layer( 993 pending_layer->CreateLayerImpl(host_impl_.active_tree())); 994 ASSERT_TRUE(active_layer); 995 996 pending_layer->SetTextureMailbox( 997 test_data_.mailbox1_, 998 SingleReleaseCallback::Create(test_data_.release_mailbox1_)); 999 1000 // Test multiple commits without an activation. 1001 EXPECT_CALL(test_data_.mock_callback_, 1002 Release(test_data_.mailbox_name1_, 1003 test_data_.sync_point1_, 1004 false)) 1005 .Times(1); 1006 pending_layer->SetTextureMailbox( 1007 test_data_.mailbox2_, 1008 SingleReleaseCallback::Create(test_data_.release_mailbox2_)); 1009 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 1010 1011 // Test callback after activation. 1012 pending_layer->PushPropertiesTo(active_layer.get()); 1013 active_layer->DidBecomeActive(); 1014 1015 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); 1016 pending_layer->SetTextureMailbox( 1017 test_data_.mailbox1_, 1018 SingleReleaseCallback::Create(test_data_.release_mailbox1_)); 1019 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 1020 1021 EXPECT_CALL(test_data_.mock_callback_, 1022 Release(test_data_.mailbox_name2_, _, false)) 1023 .Times(1); 1024 pending_layer->PushPropertiesTo(active_layer.get()); 1025 active_layer->DidBecomeActive(); 1026 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 1027 1028 // Test resetting the mailbox. 1029 EXPECT_CALL(test_data_.mock_callback_, 1030 Release(test_data_.mailbox_name1_, _, false)) 1031 .Times(1); 1032 pending_layer->SetTextureMailbox(TextureMailbox(), 1033 scoped_ptr<SingleReleaseCallback>()); 1034 pending_layer->PushPropertiesTo(active_layer.get()); 1035 active_layer->DidBecomeActive(); 1036 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 1037 1038 // Test destructor. 1039 EXPECT_CALL(test_data_.mock_callback_, 1040 Release(test_data_.mailbox_name1_, 1041 test_data_.sync_point1_, 1042 false)) 1043 .Times(1); 1044 pending_layer->SetTextureMailbox( 1045 test_data_.mailbox1_, 1046 SingleReleaseCallback::Create(test_data_.release_mailbox1_)); 1047 } 1048 1049 TEST_F(TextureLayerImplWithMailboxTest, 1050 TestDestructorCallbackOnCreatedResource) { 1051 scoped_ptr<TextureLayerImpl> impl_layer; 1052 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1); 1053 ASSERT_TRUE(impl_layer); 1054 1055 EXPECT_CALL(test_data_.mock_callback_, 1056 Release(test_data_.mailbox_name1_, _, false)) 1057 .Times(1); 1058 impl_layer->SetTextureMailbox( 1059 test_data_.mailbox1_, 1060 SingleReleaseCallback::Create(test_data_.release_mailbox1_)); 1061 impl_layer->DidBecomeActive(); 1062 EXPECT_TRUE(impl_layer->WillDraw( 1063 DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider())); 1064 impl_layer->DidDraw(host_impl_.active_tree()->resource_provider()); 1065 impl_layer->SetTextureMailbox(TextureMailbox(), 1066 scoped_ptr<SingleReleaseCallback>()); 1067 } 1068 1069 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) { 1070 ResourceProvider* provider = host_impl_.active_tree()->resource_provider(); 1071 ResourceProvider::ResourceId id = 1072 provider->CreateResourceFromTextureMailbox( 1073 test_data_.mailbox1_, 1074 SingleReleaseCallback::Create(test_data_.release_mailbox1_)); 1075 provider->AllocateForTesting(id); 1076 1077 // Transfer some resources to the parent. 1078 ResourceProvider::ResourceIdArray resource_ids_to_transfer; 1079 resource_ids_to_transfer.push_back(id); 1080 TransferableResourceArray list; 1081 provider->PrepareSendToParent(resource_ids_to_transfer, &list); 1082 EXPECT_TRUE(provider->InUseByConsumer(id)); 1083 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); 1084 provider->DeleteResource(id); 1085 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); 1086 EXPECT_CALL(test_data_.mock_callback_, 1087 Release(test_data_.mailbox_name1_, _, false)) 1088 .Times(1); 1089 ReturnedResourceArray returned; 1090 TransferableResource::ReturnResources(list, &returned); 1091 provider->ReceiveReturnsFromParent(returned); 1092 } 1093 1094 // Checks that TextureLayer::Update does not cause an extra commit when setting 1095 // the texture mailbox. 1096 class TextureLayerNoExtraCommitForMailboxTest 1097 : public LayerTreeTest, 1098 public TextureLayerClient { 1099 public: 1100 // TextureLayerClient implementation. 1101 virtual bool PrepareTextureMailbox( 1102 TextureMailbox* texture_mailbox, 1103 scoped_ptr<SingleReleaseCallback>* release_callback, 1104 bool use_shared_memory) OVERRIDE { 1105 if (layer_tree_host()->source_frame_number() == 1) { 1106 // Once this has been committed, the mailbox will be released. 1107 *texture_mailbox = TextureMailbox(); 1108 return true; 1109 } 1110 1111 *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0); 1112 *release_callback = SingleReleaseCallback::Create( 1113 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased, 1114 base::Unretained(this))); 1115 return true; 1116 } 1117 1118 void MailboxReleased(uint32 sync_point, bool lost_resource) { 1119 // Source frame number during callback is the same as the source frame 1120 // on which it was released. 1121 EXPECT_EQ(1, layer_tree_host()->source_frame_number()); 1122 EndTest(); 1123 } 1124 1125 virtual void SetupTree() OVERRIDE { 1126 scoped_refptr<Layer> root = Layer::Create(); 1127 root->SetBounds(gfx::Size(10, 10)); 1128 root->SetIsDrawable(true); 1129 1130 texture_layer_ = TextureLayer::CreateForMailbox(this); 1131 texture_layer_->SetBounds(gfx::Size(10, 10)); 1132 texture_layer_->SetIsDrawable(true); 1133 root->AddChild(texture_layer_); 1134 1135 layer_tree_host()->SetRootLayer(root); 1136 LayerTreeTest::SetupTree(); 1137 } 1138 1139 virtual void BeginTest() OVERRIDE { 1140 PostSetNeedsCommitToMainThread(); 1141 } 1142 1143 virtual void DidCommitAndDrawFrame() OVERRIDE { 1144 switch (layer_tree_host()->source_frame_number()) { 1145 case 1: 1146 EXPECT_FALSE(proxy()->CommitPendingForTesting()); 1147 // Invalidate the texture layer to clear the mailbox before 1148 // ending the test. 1149 texture_layer_->SetNeedsDisplay(); 1150 break; 1151 case 2: 1152 break; 1153 default: 1154 NOTREACHED(); 1155 break; 1156 } 1157 } 1158 1159 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, 1160 bool result) OVERRIDE { 1161 ASSERT_TRUE(result); 1162 DelegatedFrameData* delegated_frame_data = 1163 output_surface()->last_sent_frame().delegated_frame_data.get(); 1164 if (!delegated_frame_data) 1165 return; 1166 1167 // Return all resources immediately. 1168 TransferableResourceArray resources_to_return = 1169 output_surface()->resources_held_by_parent(); 1170 1171 CompositorFrameAck ack; 1172 for (size_t i = 0; i < resources_to_return.size(); ++i) 1173 output_surface()->ReturnResource(resources_to_return[i].id, &ack); 1174 host_impl->ReclaimResources(&ack); 1175 } 1176 1177 virtual void AfterTest() OVERRIDE {} 1178 1179 private: 1180 scoped_refptr<TextureLayer> texture_layer_; 1181 }; 1182 1183 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest); 1184 1185 // Checks that changing a mailbox in the client for a TextureLayer that's 1186 // invisible correctly works and uses the new mailbox as soon as the layer 1187 // becomes visible (and returns the old one). 1188 class TextureLayerChangeInvisibleMailboxTest 1189 : public LayerTreeTest, 1190 public TextureLayerClient { 1191 public: 1192 TextureLayerChangeInvisibleMailboxTest() 1193 : mailbox_changed_(true), 1194 mailbox_returned_(0), 1195 prepare_called_(0), 1196 commit_count_(0) { 1197 mailbox_ = MakeMailbox('1'); 1198 } 1199 1200 // TextureLayerClient implementation. 1201 virtual bool PrepareTextureMailbox( 1202 TextureMailbox* mailbox, 1203 scoped_ptr<SingleReleaseCallback>* release_callback, 1204 bool use_shared_memory) OVERRIDE { 1205 ++prepare_called_; 1206 if (!mailbox_changed_) 1207 return false; 1208 *mailbox = mailbox_; 1209 *release_callback = SingleReleaseCallback::Create( 1210 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased, 1211 base::Unretained(this))); 1212 return true; 1213 } 1214 1215 TextureMailbox MakeMailbox(char name) { 1216 return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0); 1217 } 1218 1219 void MailboxReleased(uint32 sync_point, bool lost_resource) { 1220 ++mailbox_returned_; 1221 } 1222 1223 virtual void SetupTree() OVERRIDE { 1224 scoped_refptr<Layer> root = Layer::Create(); 1225 root->SetBounds(gfx::Size(10, 10)); 1226 root->SetIsDrawable(true); 1227 1228 solid_layer_ = SolidColorLayer::Create(); 1229 solid_layer_->SetBounds(gfx::Size(10, 10)); 1230 solid_layer_->SetIsDrawable(true); 1231 solid_layer_->SetBackgroundColor(SK_ColorWHITE); 1232 root->AddChild(solid_layer_); 1233 1234 parent_layer_ = Layer::Create(); 1235 parent_layer_->SetBounds(gfx::Size(10, 10)); 1236 parent_layer_->SetIsDrawable(true); 1237 root->AddChild(parent_layer_); 1238 1239 texture_layer_ = TextureLayer::CreateForMailbox(this); 1240 texture_layer_->SetBounds(gfx::Size(10, 10)); 1241 texture_layer_->SetIsDrawable(true); 1242 parent_layer_->AddChild(texture_layer_); 1243 1244 layer_tree_host()->SetRootLayer(root); 1245 LayerTreeTest::SetupTree(); 1246 } 1247 1248 virtual void BeginTest() OVERRIDE { 1249 PostSetNeedsCommitToMainThread(); 1250 } 1251 1252 virtual void DidCommitAndDrawFrame() OVERRIDE { 1253 ++commit_count_; 1254 switch (commit_count_) { 1255 case 1: 1256 // We should have updated the layer, committing the texture. 1257 EXPECT_EQ(1, prepare_called_); 1258 // Make layer invisible. 1259 parent_layer_->SetOpacity(0.f); 1260 break; 1261 case 2: 1262 // Layer shouldn't have been updated. 1263 EXPECT_EQ(1, prepare_called_); 1264 // Change the texture. 1265 mailbox_ = MakeMailbox('2'); 1266 mailbox_changed_ = true; 1267 texture_layer_->SetNeedsDisplay(); 1268 // Force a change to make sure we draw a frame. 1269 solid_layer_->SetBackgroundColor(SK_ColorGRAY); 1270 break; 1271 case 3: 1272 // Layer shouldn't have been updated. 1273 EXPECT_EQ(1, prepare_called_); 1274 // So the old mailbox isn't returned yet. 1275 EXPECT_EQ(0, mailbox_returned_); 1276 // Make layer visible again. 1277 parent_layer_->SetOpacity(1.f); 1278 break; 1279 case 4: 1280 // Layer should have been updated. 1281 EXPECT_EQ(2, prepare_called_); 1282 // So the old mailbox should have been returned already. 1283 EXPECT_EQ(1, mailbox_returned_); 1284 texture_layer_->ClearClient(); 1285 break; 1286 case 5: 1287 EXPECT_EQ(2, mailbox_returned_); 1288 EndTest(); 1289 break; 1290 default: 1291 NOTREACHED(); 1292 break; 1293 } 1294 } 1295 1296 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, 1297 bool result) OVERRIDE { 1298 ASSERT_TRUE(result); 1299 DelegatedFrameData* delegated_frame_data = 1300 output_surface()->last_sent_frame().delegated_frame_data.get(); 1301 if (!delegated_frame_data) 1302 return; 1303 1304 // Return all resources immediately. 1305 TransferableResourceArray resources_to_return = 1306 output_surface()->resources_held_by_parent(); 1307 1308 CompositorFrameAck ack; 1309 for (size_t i = 0; i < resources_to_return.size(); ++i) 1310 output_surface()->ReturnResource(resources_to_return[i].id, &ack); 1311 host_impl->ReclaimResources(&ack); 1312 } 1313 1314 virtual void AfterTest() OVERRIDE {} 1315 1316 private: 1317 scoped_refptr<SolidColorLayer> solid_layer_; 1318 scoped_refptr<Layer> parent_layer_; 1319 scoped_refptr<TextureLayer> texture_layer_; 1320 1321 // Used on the main thread. 1322 bool mailbox_changed_; 1323 TextureMailbox mailbox_; 1324 int mailbox_returned_; 1325 int prepare_called_; 1326 int commit_count_; 1327 }; 1328 1329 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest); 1330 1331 // Test that TextureLayerImpl::ReleaseResources can be called which releases 1332 // the mailbox back to TextureLayerClient. 1333 class TextureLayerReleaseResourcesBase 1334 : public LayerTreeTest, 1335 public TextureLayerClient { 1336 public: 1337 // TextureLayerClient implementation. 1338 virtual bool PrepareTextureMailbox( 1339 TextureMailbox* mailbox, 1340 scoped_ptr<SingleReleaseCallback>* release_callback, 1341 bool use_shared_memory) OVERRIDE { 1342 *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0); 1343 *release_callback = SingleReleaseCallback::Create( 1344 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased, 1345 base::Unretained(this))); 1346 return true; 1347 } 1348 1349 void MailboxReleased(unsigned sync_point, bool lost_resource) { 1350 mailbox_released_ = true; 1351 } 1352 1353 virtual void SetupTree() OVERRIDE { 1354 LayerTreeTest::SetupTree(); 1355 1356 scoped_refptr<TextureLayer> texture_layer = 1357 TextureLayer::CreateForMailbox(this); 1358 texture_layer->SetBounds(gfx::Size(10, 10)); 1359 texture_layer->SetIsDrawable(true); 1360 1361 layer_tree_host()->root_layer()->AddChild(texture_layer); 1362 } 1363 1364 virtual void BeginTest() OVERRIDE { 1365 mailbox_released_ = false; 1366 PostSetNeedsCommitToMainThread(); 1367 } 1368 1369 virtual void DidCommitAndDrawFrame() OVERRIDE { 1370 EndTest(); 1371 } 1372 1373 virtual void AfterTest() OVERRIDE { 1374 EXPECT_TRUE(mailbox_released_); 1375 } 1376 1377 private: 1378 bool mailbox_released_; 1379 }; 1380 1381 class TextureLayerReleaseResourcesAfterCommit 1382 : public TextureLayerReleaseResourcesBase { 1383 public: 1384 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { 1385 LayerTreeImpl* tree = NULL; 1386 if (host_impl->settings().impl_side_painting) 1387 tree = host_impl->pending_tree(); 1388 else 1389 tree = host_impl->active_tree(); 1390 tree->root_layer()->children()[0]->ReleaseResources(); 1391 } 1392 }; 1393 1394 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit); 1395 1396 class TextureLayerReleaseResourcesAfterActivate 1397 : public TextureLayerReleaseResourcesBase { 1398 public: 1399 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { 1400 host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources(); 1401 } 1402 }; 1403 1404 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate); 1405 1406 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest { 1407 public: 1408 void ReleaseCallback(uint32 sync_point, bool lost_resource) { 1409 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); 1410 EXPECT_FALSE(lost_resource); 1411 ++callback_count_; 1412 EndTest(); 1413 } 1414 1415 void SetMailbox(char mailbox_char) { 1416 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); 1417 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( 1418 base::Bind( 1419 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback, 1420 base::Unretained(this))); 1421 layer_->SetTextureMailbox( 1422 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0), 1423 callback.Pass()); 1424 } 1425 1426 virtual void SetupTree() OVERRIDE { 1427 gfx::Size bounds(100, 100); 1428 root_ = Layer::Create(); 1429 root_->SetBounds(bounds); 1430 1431 layer_ = TextureLayer::CreateForMailbox(NULL); 1432 layer_->SetIsDrawable(true); 1433 layer_->SetBounds(bounds); 1434 1435 root_->AddChild(layer_); 1436 layer_tree_host()->SetRootLayer(root_); 1437 layer_tree_host()->SetViewportSize(bounds); 1438 } 1439 1440 virtual void BeginTest() OVERRIDE { 1441 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); 1442 1443 callback_count_ = 0; 1444 1445 // Set the mailbox on the main thread. 1446 SetMailbox('1'); 1447 EXPECT_EQ(0, callback_count_); 1448 1449 PostSetNeedsCommitToMainThread(); 1450 } 1451 1452 virtual void DidCommitAndDrawFrame() OVERRIDE { 1453 switch (layer_tree_host()->source_frame_number()) { 1454 case 1: 1455 // Delete the TextureLayer on the main thread while the mailbox is in 1456 // the impl tree. 1457 layer_->RemoveFromParent(); 1458 layer_ = NULL; 1459 break; 1460 } 1461 } 1462 1463 virtual void AfterTest() OVERRIDE { 1464 EXPECT_EQ(1, callback_count_); 1465 } 1466 1467 private: 1468 base::ThreadChecker main_thread_; 1469 int callback_count_; 1470 scoped_refptr<Layer> root_; 1471 scoped_refptr<TextureLayer> layer_; 1472 }; 1473 1474 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( 1475 TextureLayerWithMailboxMainThreadDeleted); 1476 1477 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest { 1478 public: 1479 void ReleaseCallback(uint32 sync_point, bool lost_resource) { 1480 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); 1481 EXPECT_FALSE(lost_resource); 1482 ++callback_count_; 1483 EndTest(); 1484 } 1485 1486 void SetMailbox(char mailbox_char) { 1487 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); 1488 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( 1489 base::Bind( 1490 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback, 1491 base::Unretained(this))); 1492 layer_->SetTextureMailbox( 1493 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0), 1494 callback.Pass()); 1495 } 1496 1497 virtual void SetupTree() OVERRIDE { 1498 gfx::Size bounds(100, 100); 1499 root_ = Layer::Create(); 1500 root_->SetBounds(bounds); 1501 1502 layer_ = TextureLayer::CreateForMailbox(NULL); 1503 layer_->SetIsDrawable(true); 1504 layer_->SetBounds(bounds); 1505 1506 root_->AddChild(layer_); 1507 layer_tree_host()->SetRootLayer(root_); 1508 layer_tree_host()->SetViewportSize(bounds); 1509 } 1510 1511 virtual void BeginTest() OVERRIDE { 1512 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); 1513 1514 callback_count_ = 0; 1515 1516 // Set the mailbox on the main thread. 1517 SetMailbox('1'); 1518 EXPECT_EQ(0, callback_count_); 1519 1520 PostSetNeedsCommitToMainThread(); 1521 } 1522 1523 virtual void DidCommitAndDrawFrame() OVERRIDE { 1524 switch (layer_tree_host()->source_frame_number()) { 1525 case 1: 1526 // Remove the TextureLayer on the main thread while the mailbox is in 1527 // the impl tree, but don't delete the TextureLayer until after the impl 1528 // tree side is deleted. 1529 layer_->RemoveFromParent(); 1530 break; 1531 case 2: 1532 layer_ = NULL; 1533 break; 1534 } 1535 } 1536 1537 virtual void AfterTest() OVERRIDE { 1538 EXPECT_EQ(1, callback_count_); 1539 } 1540 1541 private: 1542 base::ThreadChecker main_thread_; 1543 int callback_count_; 1544 scoped_refptr<Layer> root_; 1545 scoped_refptr<TextureLayer> layer_; 1546 }; 1547 1548 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( 1549 TextureLayerWithMailboxImplThreadDeleted); 1550 1551 } // namespace 1552 } // namespace cc 1553