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.
5 #include "cc/layers/texture_layer.h"
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"
36 using ::testing::Mock;
38 using ::testing::AtLeast;
39 using ::testing::AnyNumber;
40 using ::testing::InvokeWithoutArgs;
45 gpu::Mailbox MailboxFromChar(char value) {
47 memset(mailbox.name, value, sizeof(mailbox.name));
51 class MockLayerTreeHost : public LayerTreeHost {
53 explicit MockLayerTreeHost(FakeLayerTreeHostClient* client)
54 : LayerTreeHost(client, nullptr, nullptr, LayerTreeSettings()) {
55 InitializeSingleThreaded(client, base::MessageLoopProxy::current());
58 MOCK_METHOD0(SetNeedsCommit, void());
59 MOCK_METHOD0(SetNeedsUpdateLayers, void());
60 MOCK_METHOD0(StartRateLimiter, void());
61 MOCK_METHOD0(StopRateLimiter, void());
64 class FakeTextureLayerClient : public TextureLayerClient {
66 FakeTextureLayerClient() : mailbox_changed_(true) {}
68 bool PrepareTextureMailbox(
69 TextureMailbox* mailbox,
70 scoped_ptr<SingleReleaseCallback>* release_callback,
71 bool use_shared_memory) override {
72 if (!mailbox_changed_)
76 *release_callback = release_callback_.Pass();
77 mailbox_changed_ = false;
81 void set_mailbox(const TextureMailbox& mailbox,
82 scoped_ptr<SingleReleaseCallback> release_callback) {
84 release_callback_ = release_callback.Pass();
85 mailbox_changed_ = true;
89 TextureMailbox mailbox_;
90 scoped_ptr<SingleReleaseCallback> release_callback_;
91 bool mailbox_changed_;
92 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient);
95 class MockMailboxCallback {
98 void(const gpu::Mailbox& mailbox,
100 bool lost_resource));
101 MOCK_METHOD3(Release2,
102 void(base::SharedMemory* shared_memory,
104 bool lost_resource));
105 MOCK_METHOD4(ReleaseImpl,
106 void(const gpu::Mailbox& mailbox,
109 BlockingTaskRunner* main_thread_task_runner));
110 MOCK_METHOD4(ReleaseImpl2,
111 void(base::SharedMemory* shared_memory,
114 BlockingTaskRunner* main_thread_task_runner));
117 struct CommonMailboxObjects {
118 CommonMailboxObjects()
119 : mailbox_name1_(MailboxFromChar('1')),
120 mailbox_name2_(MailboxFromChar('2')),
123 shared_memory_(new base::SharedMemory) {
124 release_mailbox1_ = base::Bind(&MockMailboxCallback::Release,
125 base::Unretained(&mock_callback_),
127 release_mailbox2_ = base::Bind(&MockMailboxCallback::Release,
128 base::Unretained(&mock_callback_),
130 release_mailbox1_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl,
131 base::Unretained(&mock_callback_),
133 release_mailbox2_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl,
134 base::Unretained(&mock_callback_),
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);
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_;
165 scoped_ptr<base::SharedMemory> shared_memory_;
168 class TextureLayerTest : public testing::Test {
172 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
173 host_impl_(&proxy_, &shared_bitmap_manager_) {}
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());
183 virtual void TearDown() {
184 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
185 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
187 layer_tree_host_->SetRootLayer(nullptr);
188 layer_tree_host_ = nullptr;
191 scoped_ptr<MockLayerTreeHost> layer_tree_host_;
192 FakeImplProxy proxy_;
193 FakeLayerTreeHostClient fake_client_;
194 TestSharedBitmapManager shared_bitmap_manager_;
195 FakeLayerTreeHostImpl host_impl_;
198 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) {
199 scoped_refptr<TextureLayer> test_layer =
200 TextureLayer::CreateForMailbox(nullptr);
201 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer));
203 // Test properties that should call SetNeedsCommit. All properties need to
204 // be set to new values in order for SetNeedsCommit to be called.
205 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false));
206 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV(
207 gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f)));
208 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity(
209 0.5f, 0.5f, 0.5f, 0.5f));
210 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false));
211 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true));
214 TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) {
215 const gfx::Size layer_bounds(100, 100);
216 const gfx::Rect layer_rect(layer_bounds);
217 const Region layer_region(layer_rect);
219 scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(nullptr);
220 layer->SetBounds(layer_bounds);
221 layer->draw_properties().visible_content_rect = layer_rect;
222 layer->SetBlendBackgroundColor(true);
224 // Verify initial conditions.
225 EXPECT_FALSE(layer->contents_opaque());
226 EXPECT_EQ(0u, layer->background_color());
227 EXPECT_EQ(Region().ToString(),
228 layer->VisibleContentOpaqueRegion().ToString());
230 // Opaque background.
231 layer->SetBackgroundColor(SK_ColorWHITE);
232 EXPECT_EQ(layer_region.ToString(),
233 layer->VisibleContentOpaqueRegion().ToString());
235 // Transparent background.
236 layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
237 EXPECT_EQ(Region().ToString(),
238 layer->VisibleContentOpaqueRegion().ToString());
241 TEST_F(TextureLayerTest, RateLimiter) {
242 FakeTextureLayerClient client;
243 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(
245 test_layer->SetIsDrawable(true);
246 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
247 layer_tree_host_->SetRootLayer(test_layer);
249 // Don't rate limit until we invalidate.
250 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
251 test_layer->SetRateLimitContext(true);
252 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
254 // Do rate limit after we invalidate.
255 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
256 test_layer->SetNeedsDisplay();
257 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
259 // Stop rate limiter when we don't want it any more.
260 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
261 test_layer->SetRateLimitContext(false);
262 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
264 // Or we clear the client.
265 test_layer->SetRateLimitContext(true);
266 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
267 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
268 test_layer->ClearClient();
269 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
271 // Reset to a layer with a client, that started the rate limiter.
272 test_layer = TextureLayer::CreateForMailbox(
274 test_layer->SetIsDrawable(true);
275 test_layer->SetRateLimitContext(true);
276 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
277 layer_tree_host_->SetRootLayer(test_layer);
278 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
279 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
280 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
281 test_layer->SetNeedsDisplay();
282 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
284 // Stop rate limiter when we're removed from the tree.
285 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
286 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
287 layer_tree_host_->SetRootLayer(nullptr);
288 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
291 class TestMailboxHolder : public TextureLayer::TextureMailboxHolder {
293 using TextureLayer::TextureMailboxHolder::Create;
296 ~TestMailboxHolder() override {}
299 class TextureLayerWithMailboxTest : public TextureLayerTest {
301 virtual void TearDown() {
302 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
303 EXPECT_CALL(test_data_.mock_callback_,
304 Release(test_data_.mailbox_name1_,
305 test_data_.sync_point1_,
307 TextureLayerTest::TearDown();
310 CommonMailboxObjects test_data_;
313 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
314 scoped_refptr<TextureLayer> test_layer =
315 TextureLayer::CreateForMailbox(nullptr);
316 ASSERT_TRUE(test_layer.get());
318 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
319 layer_tree_host_->SetRootLayer(test_layer);
320 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
322 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
323 test_layer->SetTextureMailbox(
324 test_data_.mailbox1_,
325 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
326 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
328 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
329 EXPECT_CALL(test_data_.mock_callback_,
330 Release(test_data_.mailbox_name1_,
331 test_data_.sync_point1_,
334 test_layer->SetTextureMailbox(
335 test_data_.mailbox2_,
336 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
337 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
338 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
340 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
341 EXPECT_CALL(test_data_.mock_callback_,
342 Release(test_data_.mailbox_name2_,
343 test_data_.sync_point2_,
346 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
347 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
348 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
350 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
351 test_layer->SetTextureMailbox(
352 test_data_.mailbox3_,
353 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
354 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
355 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
357 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
358 EXPECT_CALL(test_data_.mock_callback_,
359 Release2(test_data_.shared_memory_.get(),
362 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
363 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
364 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
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_));
373 TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) {
374 scoped_refptr<TextureLayer> test_layer =
375 TextureLayer::CreateForMailbox(nullptr);
376 ASSERT_TRUE(test_layer.get());
378 // These use the same gpu::Mailbox, but different sync points.
379 TextureMailbox mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D, 1);
380 TextureMailbox mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D, 2);
382 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
383 layer_tree_host_->SetRootLayer(test_layer);
384 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
386 // Set the mailbox the first time. It should cause a commit.
387 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
388 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox1);
389 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
391 // Set the mailbox again with a new sync point, as the backing texture has
392 // been updated. It should cause a new commit.
393 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
394 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox2);
395 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
398 class TextureLayerMailboxHolderTest : public TextureLayerTest {
400 TextureLayerMailboxHolderTest()
401 : main_thread_("MAIN") {
402 main_thread_.Start();
403 main_thread_.message_loop()->PostTask(
405 base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain,
406 base::Unretained(this)));
410 void Wait(const base::Thread& thread) {
411 bool manual_reset = false;
412 bool initially_signaled = false;
413 base::WaitableEvent event(manual_reset, initially_signaled);
414 thread.message_loop()->PostTask(
416 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
420 void CreateMainRef() {
421 main_ref_ = TestMailboxHolder::Create(
422 test_data_.mailbox1_,
423 SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass();
426 void ReleaseMainRef() { main_ref_ = nullptr; }
428 void CreateImplRef(scoped_ptr<SingleReleaseCallbackImpl>* impl_ref) {
429 *impl_ref = main_ref_->holder()->GetCallbackForImplThread();
432 void CapturePostTasksAndWait(base::WaitableEvent* begin_capture,
433 base::WaitableEvent* wait_for_capture,
434 base::WaitableEvent* stop_capture) {
435 begin_capture->Wait();
436 BlockingTaskRunner::CapturePostTasks capture(
437 main_thread_task_runner_.get());
438 wait_for_capture->Signal();
439 stop_capture->Wait();
443 void InitializeOnMain() {
444 main_thread_task_runner_ =
445 BlockingTaskRunner::Create(main_thread_.message_loop_proxy());
448 scoped_ptr<TestMailboxHolder::MainThreadReference>
450 base::Thread main_thread_;
451 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
452 CommonMailboxObjects test_data_;
455 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) {
456 scoped_refptr<TextureLayer> test_layer =
457 TextureLayer::CreateForMailbox(nullptr);
458 ASSERT_TRUE(test_layer.get());
460 main_thread_.message_loop()->PostTask(
462 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
463 base::Unretained(this)));
467 // The texture layer is attached to compositor1, and passes a reference to its
469 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
470 main_thread_.message_loop()->PostTask(
472 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
473 base::Unretained(this),
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(
481 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
482 base::Unretained(this),
486 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
488 // The compositors both destroy their impl trees before the main thread layer
490 compositor1->Run(100, false, main_thread_task_runner_.get());
491 compositor2->Run(200, false, main_thread_task_runner_.get());
495 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
496 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
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);
503 main_thread_.message_loop()->PostTask(
505 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
506 base::Unretained(this)));
508 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
511 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) {
512 scoped_refptr<TextureLayer> test_layer =
513 TextureLayer::CreateForMailbox(nullptr);
514 ASSERT_TRUE(test_layer.get());
516 main_thread_.message_loop()->PostTask(
518 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
519 base::Unretained(this)));
523 // The texture layer is attached to compositor1, and passes a reference to its
525 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
526 main_thread_.message_loop()->PostTask(
528 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
529 base::Unretained(this),
532 // Then the texture layer is removed and attached to compositor2, and passes a
533 // reference to its impl tree.
534 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
535 main_thread_.message_loop()->PostTask(
537 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
538 base::Unretained(this),
542 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
544 // One compositor destroys their impl tree.
545 compositor1->Run(100, false, main_thread_task_runner_.get());
547 // Then the main thread reference is destroyed.
548 main_thread_.message_loop()->PostTask(
550 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
551 base::Unretained(this)));
555 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
556 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
558 // The second impl reference is destroyed last, causing the mailbox to be
559 // released back to the embedder with the last sync point from the impl tree.
560 EXPECT_CALL(test_data_.mock_callback_,
561 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
563 compositor2->Run(200, true, main_thread_task_runner_.get());
565 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
568 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) {
569 scoped_refptr<TextureLayer> test_layer =
570 TextureLayer::CreateForMailbox(nullptr);
571 ASSERT_TRUE(test_layer.get());
573 main_thread_.message_loop()->PostTask(
575 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
576 base::Unretained(this)));
580 // The texture layer is attached to compositor1, and passes a reference to its
582 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
583 main_thread_.message_loop()->PostTask(
585 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
586 base::Unretained(this),
589 // Then the texture layer is removed and attached to compositor2, and passes a
590 // reference to its impl tree.
591 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
592 main_thread_.message_loop()->PostTask(
594 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
595 base::Unretained(this),
599 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
601 // The main thread reference is destroyed first.
602 main_thread_.message_loop()->PostTask(
604 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
605 base::Unretained(this)));
607 // One compositor destroys their impl tree.
608 compositor2->Run(200, false, main_thread_task_runner_.get());
612 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
613 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
615 // The second impl reference is destroyed last, causing the mailbox to be
616 // released back to the embedder with the last sync point from the impl tree.
617 EXPECT_CALL(test_data_.mock_callback_,
618 Release(test_data_.mailbox_name1_, 100, true)).Times(1);
620 compositor1->Run(100, true, main_thread_task_runner_.get());
622 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
625 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) {
626 scoped_refptr<TextureLayer> test_layer =
627 TextureLayer::CreateForMailbox(nullptr);
628 ASSERT_TRUE(test_layer.get());
630 main_thread_.message_loop()->PostTask(
632 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
633 base::Unretained(this)));
637 // The texture layer is attached to compositor1, and passes a reference to its
639 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
640 main_thread_.message_loop()->PostTask(
642 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
643 base::Unretained(this),
646 // Then the texture layer is removed and attached to compositor2, and passes a
647 // reference to its impl tree.
648 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
649 main_thread_.message_loop()->PostTask(
651 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
652 base::Unretained(this),
656 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
658 // The main thread reference is destroyed first.
659 main_thread_.message_loop()->PostTask(
661 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
662 base::Unretained(this)));
664 EXPECT_CALL(test_data_.mock_callback_,
665 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
667 bool manual_reset = false;
668 bool initially_signaled = false;
669 base::WaitableEvent begin_capture(manual_reset, initially_signaled);
670 base::WaitableEvent wait_for_capture(manual_reset, initially_signaled);
671 base::WaitableEvent stop_capture(manual_reset, initially_signaled);
673 // Post a task to start capturing tasks on the main thread. This will block
674 // the main thread until we signal the |stop_capture| event.
675 main_thread_.message_loop()->PostTask(
677 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait,
678 base::Unretained(this),
683 // Before the main thread capturing starts, one compositor destroys their
684 // impl reference. Since capturing did not start, this gets post-tasked to
686 compositor1->Run(100, false, main_thread_task_runner_.get());
688 // Start capturing on the main thread.
689 begin_capture.Signal();
690 wait_for_capture.Wait();
692 // Meanwhile, the second compositor released its impl reference, but this task
693 // gets shortcutted directly to the main thread. This means the reference is
694 // released before compositor1, whose reference will be released later when
695 // the post-task is serviced. But since it was destroyed _on the impl thread_
696 // last, its sync point values should be used.
697 compositor2->Run(200, true, main_thread_task_runner_.get());
699 stop_capture.Signal();
702 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
705 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest {
707 TextureLayerImplWithMailboxThreadedCallback()
708 : callback_count_(0),
711 // Make sure callback is received on main and doesn't block the impl thread.
712 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
713 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
714 EXPECT_FALSE(lost_resource);
718 void SetMailbox(char mailbox_char) {
719 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
720 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
722 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback,
723 base::Unretained(this)));
724 layer_->SetTextureMailbox(
725 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
729 void BeginTest() override {
730 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
732 gfx::Size bounds(100, 100);
733 root_ = Layer::Create();
734 root_->SetBounds(bounds);
736 layer_ = TextureLayer::CreateForMailbox(nullptr);
737 layer_->SetIsDrawable(true);
738 layer_->SetBounds(bounds);
740 root_->AddChild(layer_);
741 layer_tree_host()->SetRootLayer(root_);
742 layer_tree_host()->SetViewportSize(bounds);
744 EXPECT_EQ(0, callback_count_);
746 // Case #1: change mailbox before the commit. The old mailbox should be
747 // released immediately.
749 EXPECT_EQ(1, callback_count_);
750 PostSetNeedsCommitToMainThread();
753 void DidCommit() override {
755 switch (commit_count_) {
757 // Case #2: change mailbox after the commit (and draw), where the
758 // layer draws. The old mailbox should be released during the next
761 EXPECT_EQ(1, callback_count_);
764 EXPECT_EQ(2, callback_count_);
765 // Case #3: change mailbox when the layer doesn't draw. The old
766 // mailbox should be released during the next commit.
767 layer_->SetBounds(gfx::Size());
771 EXPECT_EQ(3, callback_count_);
772 // Case #4: release mailbox that was committed but never drawn. The
773 // old mailbox should be released during the next commit.
774 layer_->SetTextureMailbox(TextureMailbox(), nullptr);
777 if (layer_tree_host()->settings().impl_side_painting) {
778 // With impl painting, the texture mailbox will still be on the impl
779 // thread when the commit finishes, because the layer is not drawble
780 // when it has no texture mailbox, and thus does not block the commit
781 // on activation. So, we wait for activation.
782 // TODO(danakj): fix this. crbug.com/277953
783 layer_tree_host()->SetNeedsCommit();
789 EXPECT_EQ(4, callback_count_);
790 // Restore a mailbox for the next step.
794 // Case #5: remove layer from tree. Callback should *not* be called, the
795 // mailbox is returned to the main thread.
796 EXPECT_EQ(4, callback_count_);
797 layer_->RemoveFromParent();
800 if (layer_tree_host()->settings().impl_side_painting) {
801 // With impl painting, the texture mailbox will still be on the impl
802 // thread when the commit finishes, because the layer is not around to
803 // block the commit on activation anymore. So, we wait for activation.
804 // TODO(danakj): fix this. crbug.com/277953
805 layer_tree_host()->SetNeedsCommit();
811 EXPECT_EQ(4, callback_count_);
812 // Resetting the mailbox will call the callback now.
813 layer_->SetTextureMailbox(TextureMailbox(), nullptr);
814 EXPECT_EQ(5, callback_count_);
823 void AfterTest() override {}
826 base::ThreadChecker main_thread_;
829 scoped_refptr<Layer> root_;
830 scoped_refptr<TextureLayer> layer_;
833 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
834 TextureLayerImplWithMailboxThreadedCallback);
837 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
839 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
841 static void ReleaseCallback(uint32 sync_point, bool lost_resource) {}
843 void SetMailbox(char mailbox_char) {
844 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
846 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
847 layer_->SetTextureMailbox(
848 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
852 void BeginTest() override {
853 gfx::Size bounds(100, 100);
854 root_ = Layer::Create();
855 root_->SetBounds(bounds);
857 layer_ = TextureLayer::CreateForMailbox(nullptr);
858 layer_->SetIsDrawable(true);
859 layer_->SetBounds(bounds);
861 root_->AddChild(layer_);
862 layer_tree_host()->SetRootLayer(root_);
863 layer_tree_host()->SetViewportSize(bounds);
866 PostSetNeedsCommitToMainThread();
869 void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
873 void DidCommit() override {
874 switch (layer_tree_host()->source_frame_number()) {
876 // The first mailbox has been activated. Set a new mailbox, and
877 // expect the next commit to finish *after* it is activated.
881 // The second mailbox has been activated. Remove the layer from
882 // the tree to cause another commit/activation. The commit should
883 // finish *after* the layer is removed from the active tree.
884 layer_->RemoveFromParent();
892 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
893 switch (host_impl->active_tree()->source_frame_number()) {
895 // The activate for the 1st mailbox should have happened before now.
896 EXPECT_EQ(1, activate_count_);
900 // The activate for the 2nd mailbox should have happened before now.
901 EXPECT_EQ(2, activate_count_);
905 // The activate to remove the layer should have happened before now.
906 EXPECT_EQ(3, activate_count_);
916 void AfterTest() override {}
919 scoped_refptr<Layer> root_;
920 scoped_refptr<TextureLayer> layer_;
923 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
924 TextureLayerMailboxIsActivatedDuringCommit);
926 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
928 TextureLayerImplWithMailboxTest()
930 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
932 virtual void SetUp() {
933 TextureLayerTest::SetUp();
934 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
935 EXPECT_TRUE(host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()));
938 bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
939 bool will_draw = layer->WillDraw(
940 mode, host_impl_.active_tree()->resource_provider());
942 layer->DidDraw(host_impl_.active_tree()->resource_provider());
946 CommonMailboxObjects test_data_;
947 FakeLayerTreeHostClient fake_client_;
950 // Test conditions for results of TextureLayerImpl::WillDraw under
951 // different configurations of different mailbox, texture_id, and draw_mode.
952 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
954 test_data_.mock_callback_,
955 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
957 EXPECT_CALL(test_data_.mock_callback_,
958 ReleaseImpl2(test_data_.shared_memory_.get(), 0, false, _))
962 scoped_ptr<TextureLayerImpl> impl_layer =
963 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
964 impl_layer->SetTextureMailbox(
965 test_data_.mailbox1_,
966 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
967 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
971 scoped_ptr<TextureLayerImpl> impl_layer =
972 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
973 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
974 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
978 // Software resource.
979 scoped_ptr<TextureLayerImpl> impl_layer =
980 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
981 impl_layer->SetTextureMailbox(
982 test_data_.mailbox3_,
983 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
984 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
989 scoped_ptr<TextureLayerImpl> impl_layer =
990 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
991 impl_layer->SetTextureMailbox(
992 test_data_.mailbox1_,
993 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
994 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
998 scoped_ptr<TextureLayerImpl> impl_layer =
999 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1000 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1001 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1005 // Software resource.
1006 scoped_ptr<TextureLayerImpl> impl_layer =
1007 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1008 impl_layer->SetTextureMailbox(
1009 test_data_.mailbox3_,
1010 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
1011 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1014 // Resourceless software mode.
1016 scoped_ptr<TextureLayerImpl> impl_layer =
1017 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1018 impl_layer->SetTextureMailbox(
1019 test_data_.mailbox1_,
1020 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1021 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
1025 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
1026 host_impl_.CreatePendingTree();
1027 scoped_ptr<TextureLayerImpl> pending_layer;
1028 pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1);
1029 ASSERT_TRUE(pending_layer);
1031 scoped_ptr<LayerImpl> active_layer(
1032 pending_layer->CreateLayerImpl(host_impl_.active_tree()));
1033 ASSERT_TRUE(active_layer);
1035 pending_layer->SetTextureMailbox(
1036 test_data_.mailbox1_,
1037 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1039 // Test multiple commits without an activation.
1041 test_data_.mock_callback_,
1042 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
1044 pending_layer->SetTextureMailbox(
1045 test_data_.mailbox2_,
1046 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox2_impl_));
1047 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1049 // Test callback after activation.
1050 pending_layer->PushPropertiesTo(active_layer.get());
1051 active_layer->DidBecomeActive();
1053 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1054 pending_layer->SetTextureMailbox(
1055 test_data_.mailbox1_,
1056 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1057 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1059 EXPECT_CALL(test_data_.mock_callback_,
1060 ReleaseImpl(test_data_.mailbox_name2_, _, false, _)).Times(1);
1061 pending_layer->PushPropertiesTo(active_layer.get());
1062 active_layer->DidBecomeActive();
1063 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1065 // Test resetting the mailbox.
1066 EXPECT_CALL(test_data_.mock_callback_,
1067 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1068 pending_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1069 pending_layer->PushPropertiesTo(active_layer.get());
1070 active_layer->DidBecomeActive();
1071 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1075 test_data_.mock_callback_,
1076 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
1078 pending_layer->SetTextureMailbox(
1079 test_data_.mailbox1_,
1080 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1083 TEST_F(TextureLayerImplWithMailboxTest,
1084 TestDestructorCallbackOnCreatedResource) {
1085 scoped_ptr<TextureLayerImpl> impl_layer;
1086 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1087 ASSERT_TRUE(impl_layer);
1089 EXPECT_CALL(test_data_.mock_callback_,
1090 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1091 impl_layer->SetTextureMailbox(
1092 test_data_.mailbox1_,
1093 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1094 impl_layer->DidBecomeActive();
1095 EXPECT_TRUE(impl_layer->WillDraw(
1096 DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1097 impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1098 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1101 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1102 ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1103 ResourceProvider::ResourceId id = provider->CreateResourceFromTextureMailbox(
1104 test_data_.mailbox1_,
1105 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1106 provider->AllocateForTesting(id);
1108 // Transfer some resources to the parent.
1109 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1110 resource_ids_to_transfer.push_back(id);
1111 TransferableResourceArray list;
1112 provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1113 EXPECT_TRUE(provider->InUseByConsumer(id));
1114 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1115 provider->DeleteResource(id);
1116 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1117 EXPECT_CALL(test_data_.mock_callback_,
1118 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1119 ReturnedResourceArray returned;
1120 TransferableResource::ReturnResources(list, &returned);
1121 provider->ReceiveReturnsFromParent(returned);
1124 // Checks that TextureLayer::Update does not cause an extra commit when setting
1125 // the texture mailbox.
1126 class TextureLayerNoExtraCommitForMailboxTest
1127 : public LayerTreeTest,
1128 public TextureLayerClient {
1130 // TextureLayerClient implementation.
1131 bool PrepareTextureMailbox(
1132 TextureMailbox* texture_mailbox,
1133 scoped_ptr<SingleReleaseCallback>* release_callback,
1134 bool use_shared_memory) override {
1135 if (layer_tree_host()->source_frame_number() == 1) {
1136 // Once this has been committed, the mailbox will be released.
1137 *texture_mailbox = TextureMailbox();
1141 *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1142 *release_callback = SingleReleaseCallback::Create(
1143 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1144 base::Unretained(this)));
1148 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1149 // Source frame number during callback is the same as the source frame
1150 // on which it was released.
1151 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1155 void SetupTree() override {
1156 scoped_refptr<Layer> root = Layer::Create();
1157 root->SetBounds(gfx::Size(10, 10));
1158 root->SetIsDrawable(true);
1160 texture_layer_ = TextureLayer::CreateForMailbox(this);
1161 texture_layer_->SetBounds(gfx::Size(10, 10));
1162 texture_layer_->SetIsDrawable(true);
1163 root->AddChild(texture_layer_);
1165 layer_tree_host()->SetRootLayer(root);
1166 LayerTreeTest::SetupTree();
1169 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1171 void DidCommitAndDrawFrame() override {
1172 switch (layer_tree_host()->source_frame_number()) {
1174 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1175 // Invalidate the texture layer to clear the mailbox before
1177 texture_layer_->SetNeedsDisplay();
1187 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1188 ASSERT_TRUE(result);
1189 DelegatedFrameData* delegated_frame_data =
1190 output_surface()->last_sent_frame().delegated_frame_data.get();
1191 if (!delegated_frame_data)
1194 // Return all resources immediately.
1195 TransferableResourceArray resources_to_return =
1196 output_surface()->resources_held_by_parent();
1198 CompositorFrameAck ack;
1199 for (size_t i = 0; i < resources_to_return.size(); ++i)
1200 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1201 host_impl->ReclaimResources(&ack);
1204 void AfterTest() override {}
1207 scoped_refptr<TextureLayer> texture_layer_;
1210 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1212 // Checks that changing a mailbox in the client for a TextureLayer that's
1213 // invisible correctly works and uses the new mailbox as soon as the layer
1214 // becomes visible (and returns the old one).
1215 class TextureLayerChangeInvisibleMailboxTest
1216 : public LayerTreeTest,
1217 public TextureLayerClient {
1219 TextureLayerChangeInvisibleMailboxTest()
1220 : mailbox_changed_(true),
1221 mailbox_returned_(0),
1224 mailbox_ = MakeMailbox('1');
1227 // TextureLayerClient implementation.
1228 bool PrepareTextureMailbox(
1229 TextureMailbox* mailbox,
1230 scoped_ptr<SingleReleaseCallback>* release_callback,
1231 bool use_shared_memory) override {
1233 if (!mailbox_changed_)
1235 *mailbox = mailbox_;
1236 *release_callback = SingleReleaseCallback::Create(
1237 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1238 base::Unretained(this)));
1242 TextureMailbox MakeMailbox(char name) {
1243 return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0);
1246 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1247 ++mailbox_returned_;
1250 void SetupTree() override {
1251 scoped_refptr<Layer> root = Layer::Create();
1252 root->SetBounds(gfx::Size(10, 10));
1253 root->SetIsDrawable(true);
1255 solid_layer_ = SolidColorLayer::Create();
1256 solid_layer_->SetBounds(gfx::Size(10, 10));
1257 solid_layer_->SetIsDrawable(true);
1258 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1259 root->AddChild(solid_layer_);
1261 parent_layer_ = Layer::Create();
1262 parent_layer_->SetBounds(gfx::Size(10, 10));
1263 parent_layer_->SetIsDrawable(true);
1264 root->AddChild(parent_layer_);
1266 texture_layer_ = TextureLayer::CreateForMailbox(this);
1267 texture_layer_->SetBounds(gfx::Size(10, 10));
1268 texture_layer_->SetIsDrawable(true);
1269 parent_layer_->AddChild(texture_layer_);
1271 layer_tree_host()->SetRootLayer(root);
1272 LayerTreeTest::SetupTree();
1275 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1277 void DidCommitAndDrawFrame() override {
1279 switch (commit_count_) {
1281 // We should have updated the layer, committing the texture.
1282 EXPECT_EQ(1, prepare_called_);
1283 // Make layer invisible.
1284 parent_layer_->SetOpacity(0.f);
1287 // Layer shouldn't have been updated.
1288 EXPECT_EQ(1, prepare_called_);
1289 // Change the texture.
1290 mailbox_ = MakeMailbox('2');
1291 mailbox_changed_ = true;
1292 texture_layer_->SetNeedsDisplay();
1293 // Force a change to make sure we draw a frame.
1294 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1297 // Layer shouldn't have been updated.
1298 EXPECT_EQ(1, prepare_called_);
1299 // So the old mailbox isn't returned yet.
1300 EXPECT_EQ(0, mailbox_returned_);
1301 // Make layer visible again.
1302 parent_layer_->SetOpacity(1.f);
1305 // Layer should have been updated.
1306 EXPECT_EQ(2, prepare_called_);
1307 // So the old mailbox should have been returned already.
1308 EXPECT_EQ(1, mailbox_returned_);
1309 texture_layer_->ClearClient();
1312 EXPECT_EQ(2, mailbox_returned_);
1321 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1322 ASSERT_TRUE(result);
1323 DelegatedFrameData* delegated_frame_data =
1324 output_surface()->last_sent_frame().delegated_frame_data.get();
1325 if (!delegated_frame_data)
1328 // Return all resources immediately.
1329 TransferableResourceArray resources_to_return =
1330 output_surface()->resources_held_by_parent();
1332 CompositorFrameAck ack;
1333 for (size_t i = 0; i < resources_to_return.size(); ++i)
1334 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1335 host_impl->ReclaimResources(&ack);
1338 void AfterTest() override {}
1341 scoped_refptr<SolidColorLayer> solid_layer_;
1342 scoped_refptr<Layer> parent_layer_;
1343 scoped_refptr<TextureLayer> texture_layer_;
1345 // Used on the main thread.
1346 bool mailbox_changed_;
1347 TextureMailbox mailbox_;
1348 int mailbox_returned_;
1349 int prepare_called_;
1353 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1355 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1356 // the mailbox back to TextureLayerClient.
1357 class TextureLayerReleaseResourcesBase
1358 : public LayerTreeTest,
1359 public TextureLayerClient {
1361 // TextureLayerClient implementation.
1362 bool PrepareTextureMailbox(
1363 TextureMailbox* mailbox,
1364 scoped_ptr<SingleReleaseCallback>* release_callback,
1365 bool use_shared_memory) override {
1366 *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1367 *release_callback = SingleReleaseCallback::Create(
1368 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1369 base::Unretained(this)));
1373 void MailboxReleased(unsigned sync_point, bool lost_resource) {
1374 mailbox_released_ = true;
1377 void SetupTree() override {
1378 LayerTreeTest::SetupTree();
1380 scoped_refptr<TextureLayer> texture_layer =
1381 TextureLayer::CreateForMailbox(this);
1382 texture_layer->SetBounds(gfx::Size(10, 10));
1383 texture_layer->SetIsDrawable(true);
1385 layer_tree_host()->root_layer()->AddChild(texture_layer);
1388 void BeginTest() override {
1389 mailbox_released_ = false;
1390 PostSetNeedsCommitToMainThread();
1393 void DidCommitAndDrawFrame() override { EndTest(); }
1395 void AfterTest() override { EXPECT_TRUE(mailbox_released_); }
1398 bool mailbox_released_;
1401 class TextureLayerReleaseResourcesAfterCommit
1402 : public TextureLayerReleaseResourcesBase {
1404 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
1405 LayerTreeImpl* tree = nullptr;
1406 if (host_impl->settings().impl_side_painting)
1407 tree = host_impl->pending_tree();
1409 tree = host_impl->active_tree();
1410 tree->root_layer()->children()[0]->ReleaseResources();
1414 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1416 class TextureLayerReleaseResourcesAfterActivate
1417 : public TextureLayerReleaseResourcesBase {
1419 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
1420 host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
1424 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
1426 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
1428 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1429 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1430 EXPECT_FALSE(lost_resource);
1435 void SetMailbox(char mailbox_char) {
1436 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1437 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1439 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
1440 base::Unretained(this)));
1441 layer_->SetTextureMailbox(
1442 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1446 void SetupTree() override {
1447 gfx::Size bounds(100, 100);
1448 root_ = Layer::Create();
1449 root_->SetBounds(bounds);
1451 layer_ = TextureLayer::CreateForMailbox(nullptr);
1452 layer_->SetIsDrawable(true);
1453 layer_->SetBounds(bounds);
1455 root_->AddChild(layer_);
1456 layer_tree_host()->SetRootLayer(root_);
1457 layer_tree_host()->SetViewportSize(bounds);
1460 void BeginTest() override {
1461 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1463 callback_count_ = 0;
1465 // Set the mailbox on the main thread.
1467 EXPECT_EQ(0, callback_count_);
1469 PostSetNeedsCommitToMainThread();
1472 void DidCommitAndDrawFrame() override {
1473 switch (layer_tree_host()->source_frame_number()) {
1475 // Delete the TextureLayer on the main thread while the mailbox is in
1477 layer_->RemoveFromParent();
1483 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1486 base::ThreadChecker main_thread_;
1487 int callback_count_;
1488 scoped_refptr<Layer> root_;
1489 scoped_refptr<TextureLayer> layer_;
1492 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1493 TextureLayerWithMailboxMainThreadDeleted);
1495 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
1497 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1498 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1499 EXPECT_FALSE(lost_resource);
1504 void SetMailbox(char mailbox_char) {
1505 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1506 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1508 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
1509 base::Unretained(this)));
1510 layer_->SetTextureMailbox(
1511 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1515 void SetupTree() override {
1516 gfx::Size bounds(100, 100);
1517 root_ = Layer::Create();
1518 root_->SetBounds(bounds);
1520 layer_ = TextureLayer::CreateForMailbox(nullptr);
1521 layer_->SetIsDrawable(true);
1522 layer_->SetBounds(bounds);
1524 root_->AddChild(layer_);
1525 layer_tree_host()->SetRootLayer(root_);
1526 layer_tree_host()->SetViewportSize(bounds);
1529 void BeginTest() override {
1530 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1532 callback_count_ = 0;
1534 // Set the mailbox on the main thread.
1536 EXPECT_EQ(0, callback_count_);
1538 PostSetNeedsCommitToMainThread();
1541 void DidCommitAndDrawFrame() override {
1542 switch (layer_tree_host()->source_frame_number()) {
1544 // Remove the TextureLayer on the main thread while the mailbox is in
1545 // the impl tree, but don't delete the TextureLayer until after the impl
1546 // tree side is deleted.
1547 layer_->RemoveFromParent();
1555 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1558 base::ThreadChecker main_thread_;
1559 int callback_count_;
1560 scoped_refptr<Layer> root_;
1561 scoped_refptr<TextureLayer> layer_;
1564 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1565 TextureLayerWithMailboxImplThreadDeleted);