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