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