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
,
56 base::MessageLoopProxy::current(),
60 MOCK_METHOD0(SetNeedsCommit
, void());
61 MOCK_METHOD0(SetNeedsUpdateLayers
, void());
62 MOCK_METHOD0(StartRateLimiter
, void());
63 MOCK_METHOD0(StopRateLimiter
, void());
66 class FakeTextureLayerClient
: public TextureLayerClient
{
68 FakeTextureLayerClient() : mailbox_changed_(true) {}
70 bool PrepareTextureMailbox(
71 TextureMailbox
* mailbox
,
72 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
73 bool use_shared_memory
) override
{
74 if (!mailbox_changed_
)
78 *release_callback
= release_callback_
.Pass();
79 mailbox_changed_
= false;
83 void set_mailbox(const TextureMailbox
& mailbox
,
84 scoped_ptr
<SingleReleaseCallback
> release_callback
) {
86 release_callback_
= release_callback
.Pass();
87 mailbox_changed_
= true;
91 TextureMailbox mailbox_
;
92 scoped_ptr
<SingleReleaseCallback
> release_callback_
;
93 bool mailbox_changed_
;
94 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient
);
97 class MockMailboxCallback
{
100 void(const gpu::Mailbox
& mailbox
,
102 bool lost_resource
));
103 MOCK_METHOD3(Release2
,
104 void(base::SharedMemory
* shared_memory
,
106 bool lost_resource
));
107 MOCK_METHOD4(ReleaseImpl
,
108 void(const gpu::Mailbox
& mailbox
,
111 BlockingTaskRunner
* main_thread_task_runner
));
112 MOCK_METHOD4(ReleaseImpl2
,
113 void(base::SharedMemory
* shared_memory
,
116 BlockingTaskRunner
* main_thread_task_runner
));
119 struct CommonMailboxObjects
{
120 CommonMailboxObjects()
121 : mailbox_name1_(MailboxFromChar('1')),
122 mailbox_name2_(MailboxFromChar('2')),
125 shared_memory_(new base::SharedMemory
) {
126 release_mailbox1_
= base::Bind(&MockMailboxCallback::Release
,
127 base::Unretained(&mock_callback_
),
129 release_mailbox2_
= base::Bind(&MockMailboxCallback::Release
,
130 base::Unretained(&mock_callback_
),
132 release_mailbox1_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
133 base::Unretained(&mock_callback_
),
135 release_mailbox2_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
136 base::Unretained(&mock_callback_
),
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 EXPECT_TRUE(shared_memory_
->CreateAndMapAnonymous(4 * size
.GetArea()));
144 release_mailbox3_
= base::Bind(&MockMailboxCallback::Release2
,
145 base::Unretained(&mock_callback_
),
146 shared_memory_
.get());
147 release_mailbox3_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl2
,
148 base::Unretained(&mock_callback_
),
149 shared_memory_
.get());
150 mailbox3_
= TextureMailbox(shared_memory_
.get(), size
);
153 gpu::Mailbox mailbox_name1_
;
154 gpu::Mailbox mailbox_name2_
;
155 MockMailboxCallback mock_callback_
;
156 ReleaseCallback release_mailbox1_
;
157 ReleaseCallback release_mailbox2_
;
158 ReleaseCallback release_mailbox3_
;
159 ReleaseCallbackImpl release_mailbox1_impl_
;
160 ReleaseCallbackImpl release_mailbox2_impl_
;
161 ReleaseCallbackImpl release_mailbox3_impl_
;
162 TextureMailbox mailbox1_
;
163 TextureMailbox mailbox2_
;
164 TextureMailbox mailbox3_
;
167 scoped_ptr
<base::SharedMemory
> shared_memory_
;
170 class TextureLayerTest
: public testing::Test
{
174 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)),
175 host_impl_(&proxy_
, &shared_bitmap_manager_
) {}
178 virtual void SetUp() {
179 layer_tree_host_
.reset(new MockLayerTreeHost(&fake_client_
));
180 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
181 layer_tree_host_
->SetViewportSize(gfx::Size(10, 10));
182 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
185 virtual void TearDown() {
186 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
187 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
189 layer_tree_host_
->SetRootLayer(nullptr);
190 layer_tree_host_
= nullptr;
193 scoped_ptr
<MockLayerTreeHost
> layer_tree_host_
;
194 FakeImplProxy proxy_
;
195 FakeLayerTreeHostClient fake_client_
;
196 TestSharedBitmapManager shared_bitmap_manager_
;
197 FakeLayerTreeHostImpl host_impl_
;
200 TEST_F(TextureLayerTest
, CheckPropertyChangeCausesCorrectBehavior
) {
201 scoped_refptr
<TextureLayer
> test_layer
=
202 TextureLayer::CreateForMailbox(nullptr);
203 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_
->SetRootLayer(test_layer
));
205 // Test properties that should call SetNeedsCommit. All properties need to
206 // be set to new values in order for SetNeedsCommit to be called.
207 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetFlipped(false));
208 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetUV(
209 gfx::PointF(0.25f
, 0.25f
), gfx::PointF(0.75f
, 0.75f
)));
210 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetVertexOpacity(
211 0.5f
, 0.5f
, 0.5f
, 0.5f
));
212 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetPremultipliedAlpha(false));
213 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetBlendBackgroundColor(true));
216 TEST_F(TextureLayerTest
, VisibleContentOpaqueRegion
) {
217 const gfx::Size
layer_bounds(100, 100);
218 const gfx::Rect
layer_rect(layer_bounds
);
219 const Region
layer_region(layer_rect
);
221 scoped_refptr
<TextureLayer
> layer
= TextureLayer::CreateForMailbox(nullptr);
222 layer
->SetBounds(layer_bounds
);
223 layer
->draw_properties().visible_content_rect
= layer_rect
;
224 layer
->SetBlendBackgroundColor(true);
226 // Verify initial conditions.
227 EXPECT_FALSE(layer
->contents_opaque());
228 EXPECT_EQ(0u, layer
->background_color());
229 EXPECT_EQ(Region().ToString(),
230 layer
->VisibleContentOpaqueRegion().ToString());
232 // Opaque background.
233 layer
->SetBackgroundColor(SK_ColorWHITE
);
234 EXPECT_EQ(layer_region
.ToString(),
235 layer
->VisibleContentOpaqueRegion().ToString());
237 // Transparent background.
238 layer
->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
239 EXPECT_EQ(Region().ToString(),
240 layer
->VisibleContentOpaqueRegion().ToString());
243 TEST_F(TextureLayerTest
, RateLimiter
) {
244 FakeTextureLayerClient client
;
245 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(
247 test_layer
->SetIsDrawable(true);
248 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
249 layer_tree_host_
->SetRootLayer(test_layer
);
251 // Don't rate limit until we invalidate.
252 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
253 test_layer
->SetRateLimitContext(true);
254 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
256 // Do rate limit after we invalidate.
257 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
258 test_layer
->SetNeedsDisplay();
259 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
261 // Stop rate limiter when we don't want it any more.
262 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
263 test_layer
->SetRateLimitContext(false);
264 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
266 // Or we clear the client.
267 test_layer
->SetRateLimitContext(true);
268 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
269 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
270 test_layer
->ClearClient();
271 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
273 // Reset to a layer with a client, that started the rate limiter.
274 test_layer
= TextureLayer::CreateForMailbox(
276 test_layer
->SetIsDrawable(true);
277 test_layer
->SetRateLimitContext(true);
278 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
279 layer_tree_host_
->SetRootLayer(test_layer
);
280 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
281 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
282 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
283 test_layer
->SetNeedsDisplay();
284 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
286 // Stop rate limiter when we're removed from the tree.
287 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
288 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(1);
289 layer_tree_host_
->SetRootLayer(nullptr);
290 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
293 class TestMailboxHolder
: public TextureLayer::TextureMailboxHolder
{
295 using TextureLayer::TextureMailboxHolder::Create
;
298 ~TestMailboxHolder() override
{}
301 class TextureLayerWithMailboxTest
: public TextureLayerTest
{
303 virtual void TearDown() {
304 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
305 EXPECT_CALL(test_data_
.mock_callback_
,
306 Release(test_data_
.mailbox_name1_
,
307 test_data_
.sync_point1_
,
309 TextureLayerTest::TearDown();
312 CommonMailboxObjects test_data_
;
315 TEST_F(TextureLayerWithMailboxTest
, ReplaceMailboxOnMainThreadBeforeCommit
) {
316 scoped_refptr
<TextureLayer
> test_layer
=
317 TextureLayer::CreateForMailbox(nullptr);
318 ASSERT_TRUE(test_layer
.get());
320 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
321 layer_tree_host_
->SetRootLayer(test_layer
);
322 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
324 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
325 test_layer
->SetTextureMailbox(
326 test_data_
.mailbox1_
,
327 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
328 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
330 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
331 EXPECT_CALL(test_data_
.mock_callback_
,
332 Release(test_data_
.mailbox_name1_
,
333 test_data_
.sync_point1_
,
336 test_layer
->SetTextureMailbox(
337 test_data_
.mailbox2_
,
338 SingleReleaseCallback::Create(test_data_
.release_mailbox2_
));
339 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
340 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
342 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
343 EXPECT_CALL(test_data_
.mock_callback_
,
344 Release(test_data_
.mailbox_name2_
,
345 test_data_
.sync_point2_
,
348 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
349 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
350 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
352 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
353 test_layer
->SetTextureMailbox(
354 test_data_
.mailbox3_
,
355 SingleReleaseCallback::Create(test_data_
.release_mailbox3_
));
356 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
357 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
359 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
360 EXPECT_CALL(test_data_
.mock_callback_
,
361 Release2(test_data_
.shared_memory_
.get(),
364 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
365 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
366 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
369 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
370 test_layer
->SetTextureMailbox(
371 test_data_
.mailbox1_
,
372 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
375 TEST_F(TextureLayerTest
, SetTextureMailboxWithoutReleaseCallback
) {
376 scoped_refptr
<TextureLayer
> test_layer
=
377 TextureLayer::CreateForMailbox(nullptr);
378 ASSERT_TRUE(test_layer
.get());
380 // These use the same gpu::Mailbox, but different sync points.
381 TextureMailbox
mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D
, 1);
382 TextureMailbox
mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D
, 2);
384 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
385 layer_tree_host_
->SetRootLayer(test_layer
);
386 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
388 // Set the mailbox the first time. It should cause a commit.
389 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
390 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox1
);
391 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
393 // Set the mailbox again with a new sync point, as the backing texture has
394 // been updated. It should cause a new commit.
395 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
396 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox2
);
397 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
400 class TextureLayerMailboxHolderTest
: public TextureLayerTest
{
402 TextureLayerMailboxHolderTest()
403 : main_thread_("MAIN") {
404 main_thread_
.Start();
405 main_thread_
.message_loop()->PostTask(
407 base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain
,
408 base::Unretained(this)));
412 void Wait(const base::Thread
& thread
) {
413 bool manual_reset
= false;
414 bool initially_signaled
= false;
415 base::WaitableEvent
event(manual_reset
, initially_signaled
);
416 thread
.message_loop()->PostTask(
418 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
422 void CreateMainRef() {
423 main_ref_
= TestMailboxHolder::Create(
424 test_data_
.mailbox1_
,
425 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
)).Pass();
428 void ReleaseMainRef() { main_ref_
= nullptr; }
430 void CreateImplRef(scoped_ptr
<SingleReleaseCallbackImpl
>* impl_ref
) {
431 *impl_ref
= main_ref_
->holder()->GetCallbackForImplThread();
434 void CapturePostTasksAndWait(base::WaitableEvent
* begin_capture
,
435 base::WaitableEvent
* wait_for_capture
,
436 base::WaitableEvent
* stop_capture
) {
437 begin_capture
->Wait();
438 BlockingTaskRunner::CapturePostTasks
capture(
439 main_thread_task_runner_
.get());
440 wait_for_capture
->Signal();
441 stop_capture
->Wait();
445 void InitializeOnMain() {
446 main_thread_task_runner_
=
447 BlockingTaskRunner::Create(main_thread_
.message_loop_proxy());
450 scoped_ptr
<TestMailboxHolder::MainThreadReference
>
452 base::Thread main_thread_
;
453 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
454 CommonMailboxObjects test_data_
;
457 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_BothReleaseThenMain
) {
458 scoped_refptr
<TextureLayer
> test_layer
=
459 TextureLayer::CreateForMailbox(nullptr);
460 ASSERT_TRUE(test_layer
.get());
462 main_thread_
.message_loop()->PostTask(
464 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
465 base::Unretained(this)));
469 // The texture layer is attached to compositor1, and passes a reference to its
471 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
472 main_thread_
.message_loop()->PostTask(
474 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
475 base::Unretained(this),
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(
483 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
484 base::Unretained(this),
488 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
490 // The compositors both destroy their impl trees before the main thread layer
492 compositor1
->Run(100, false, main_thread_task_runner_
.get());
493 compositor2
->Run(200, false, main_thread_task_runner_
.get());
497 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
498 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
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);
505 main_thread_
.message_loop()->PostTask(
507 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
508 base::Unretained(this)));
510 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
513 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleaseBetween
) {
514 scoped_refptr
<TextureLayer
> test_layer
=
515 TextureLayer::CreateForMailbox(nullptr);
516 ASSERT_TRUE(test_layer
.get());
518 main_thread_
.message_loop()->PostTask(
520 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
521 base::Unretained(this)));
525 // The texture layer is attached to compositor1, and passes a reference to its
527 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
528 main_thread_
.message_loop()->PostTask(
530 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
531 base::Unretained(this),
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(
539 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
540 base::Unretained(this),
544 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
546 // One compositor destroys their impl tree.
547 compositor1
->Run(100, false, main_thread_task_runner_
.get());
549 // Then the main thread reference is destroyed.
550 main_thread_
.message_loop()->PostTask(
552 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
553 base::Unretained(this)));
557 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
558 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
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);
565 compositor2
->Run(200, true, main_thread_task_runner_
.get());
567 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
570 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleasedFirst
) {
571 scoped_refptr
<TextureLayer
> test_layer
=
572 TextureLayer::CreateForMailbox(nullptr);
573 ASSERT_TRUE(test_layer
.get());
575 main_thread_
.message_loop()->PostTask(
577 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
578 base::Unretained(this)));
582 // The texture layer is attached to compositor1, and passes a reference to its
584 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
585 main_thread_
.message_loop()->PostTask(
587 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
588 base::Unretained(this),
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(
596 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
597 base::Unretained(this),
601 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
603 // The main thread reference is destroyed first.
604 main_thread_
.message_loop()->PostTask(
606 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
607 base::Unretained(this)));
609 // One compositor destroys their impl tree.
610 compositor2
->Run(200, false, main_thread_task_runner_
.get());
614 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
615 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
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);
622 compositor1
->Run(100, true, main_thread_task_runner_
.get());
624 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
627 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_SecondImplRefShortcut
) {
628 scoped_refptr
<TextureLayer
> test_layer
=
629 TextureLayer::CreateForMailbox(nullptr);
630 ASSERT_TRUE(test_layer
.get());
632 main_thread_
.message_loop()->PostTask(
634 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
635 base::Unretained(this)));
639 // The texture layer is attached to compositor1, and passes a reference to its
641 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
642 main_thread_
.message_loop()->PostTask(
644 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
645 base::Unretained(this),
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(
653 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
654 base::Unretained(this),
658 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
660 // The main thread reference is destroyed first.
661 main_thread_
.message_loop()->PostTask(
663 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
664 base::Unretained(this)));
666 EXPECT_CALL(test_data_
.mock_callback_
,
667 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
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
);
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(
679 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait
,
680 base::Unretained(this),
685 // Before the main thread capturing starts, one compositor destroys their
686 // impl reference. Since capturing did not start, this gets post-tasked to
688 compositor1
->Run(100, false, main_thread_task_runner_
.get());
690 // Start capturing on the main thread.
691 begin_capture
.Signal();
692 wait_for_capture
.Wait();
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());
701 stop_capture
.Signal();
704 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
707 class TextureLayerImplWithMailboxThreadedCallback
: public LayerTreeTest
{
709 TextureLayerImplWithMailboxThreadedCallback()
710 : callback_count_(0),
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
);
720 void SetMailbox(char mailbox_char
) {
721 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
722 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
724 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback
,
725 base::Unretained(this)));
726 layer_
->SetTextureMailbox(
727 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
731 void BeginTest() override
{
732 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
734 gfx::Size
bounds(100, 100);
735 root_
= Layer::Create();
736 root_
->SetBounds(bounds
);
738 layer_
= TextureLayer::CreateForMailbox(nullptr);
739 layer_
->SetIsDrawable(true);
740 layer_
->SetBounds(bounds
);
742 root_
->AddChild(layer_
);
743 layer_tree_host()->SetRootLayer(root_
);
744 layer_tree_host()->SetViewportSize(bounds
);
746 EXPECT_EQ(0, callback_count_
);
748 // Case #1: change mailbox before the commit. The old mailbox should be
749 // released immediately.
751 EXPECT_EQ(1, callback_count_
);
752 PostSetNeedsCommitToMainThread();
755 void DidCommit() override
{
757 switch (commit_count_
) {
759 // Case #2: change mailbox after the commit (and draw), where the
760 // layer draws. The old mailbox should be released during the next
763 EXPECT_EQ(1, callback_count_
);
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());
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);
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();
791 EXPECT_EQ(4, callback_count_
);
792 // Restore a mailbox for the next step.
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();
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();
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_
);
825 void AfterTest() override
{}
828 base::ThreadChecker main_thread_
;
831 scoped_refptr
<Layer
> root_
;
832 scoped_refptr
<TextureLayer
> layer_
;
835 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
836 TextureLayerImplWithMailboxThreadedCallback
);
839 class TextureLayerMailboxIsActivatedDuringCommit
: public LayerTreeTest
{
841 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
843 static void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {}
845 void SetMailbox(char mailbox_char
) {
846 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
848 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback
));
849 layer_
->SetTextureMailbox(
850 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
854 void BeginTest() override
{
855 gfx::Size
bounds(100, 100);
856 root_
= Layer::Create();
857 root_
->SetBounds(bounds
);
859 layer_
= TextureLayer::CreateForMailbox(nullptr);
860 layer_
->SetIsDrawable(true);
861 layer_
->SetBounds(bounds
);
863 root_
->AddChild(layer_
);
864 layer_tree_host()->SetRootLayer(root_
);
865 layer_tree_host()->SetViewportSize(bounds
);
868 PostSetNeedsCommitToMainThread();
871 void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
875 void DidCommit() override
{
876 switch (layer_tree_host()->source_frame_number()) {
878 // The first mailbox has been activated. Set a new mailbox, and
879 // expect the next commit to finish *after* it is activated.
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();
894 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
895 switch (host_impl
->active_tree()->source_frame_number()) {
897 // The activate for the 1st mailbox should have happened before now.
898 EXPECT_EQ(1, activate_count_
);
902 // The activate for the 2nd mailbox should have happened before now.
903 EXPECT_EQ(2, activate_count_
);
907 // The activate to remove the layer should have happened before now.
908 EXPECT_EQ(3, activate_count_
);
918 void AfterTest() override
{}
921 scoped_refptr
<Layer
> root_
;
922 scoped_refptr
<TextureLayer
> layer_
;
925 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
926 TextureLayerMailboxIsActivatedDuringCommit
);
928 class TextureLayerImplWithMailboxTest
: public TextureLayerTest
{
930 TextureLayerImplWithMailboxTest()
932 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)) {}
934 virtual void SetUp() {
935 TextureLayerTest::SetUp();
936 layer_tree_host_
.reset(new MockLayerTreeHost(&fake_client_
));
937 EXPECT_TRUE(host_impl_
.InitializeRenderer(FakeOutputSurface::Create3d()));
940 bool WillDraw(TextureLayerImpl
* layer
, DrawMode mode
) {
941 bool will_draw
= layer
->WillDraw(
942 mode
, host_impl_
.active_tree()->resource_provider());
944 layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
948 CommonMailboxObjects test_data_
;
949 FakeLayerTreeHostClient fake_client_
;
952 // Test conditions for results of TextureLayerImpl::WillDraw under
953 // different configurations of different mailbox, texture_id, and draw_mode.
954 TEST_F(TextureLayerImplWithMailboxTest
, TestWillDraw
) {
956 test_data_
.mock_callback_
,
957 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
959 EXPECT_CALL(test_data_
.mock_callback_
,
960 ReleaseImpl2(test_data_
.shared_memory_
.get(), 0, false, _
))
964 scoped_ptr
<TextureLayerImpl
> impl_layer
=
965 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
966 impl_layer
->SetTextureMailbox(
967 test_data_
.mailbox1_
,
968 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
969 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
973 scoped_ptr
<TextureLayerImpl
> impl_layer
=
974 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
975 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
976 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
980 // Software resource.
981 scoped_ptr
<TextureLayerImpl
> impl_layer
=
982 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
983 impl_layer
->SetTextureMailbox(
984 test_data_
.mailbox3_
,
985 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
986 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
991 scoped_ptr
<TextureLayerImpl
> impl_layer
=
992 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
993 impl_layer
->SetTextureMailbox(
994 test_data_
.mailbox1_
,
995 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
996 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
1000 scoped_ptr
<TextureLayerImpl
> impl_layer
=
1001 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1002 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1003 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
1007 // Software resource.
1008 scoped_ptr
<TextureLayerImpl
> impl_layer
=
1009 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1010 impl_layer
->SetTextureMailbox(
1011 test_data_
.mailbox3_
,
1012 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
1013 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
1016 // Resourceless software mode.
1018 scoped_ptr
<TextureLayerImpl
> impl_layer
=
1019 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1020 impl_layer
->SetTextureMailbox(
1021 test_data_
.mailbox1_
,
1022 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1023 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_RESOURCELESS_SOFTWARE
));
1027 TEST_F(TextureLayerImplWithMailboxTest
, TestImplLayerCallbacks
) {
1028 host_impl_
.CreatePendingTree();
1029 scoped_ptr
<TextureLayerImpl
> pending_layer
;
1030 pending_layer
= TextureLayerImpl::Create(host_impl_
.pending_tree(), 1);
1031 ASSERT_TRUE(pending_layer
);
1033 scoped_ptr
<LayerImpl
> active_layer(
1034 pending_layer
->CreateLayerImpl(host_impl_
.active_tree()));
1035 ASSERT_TRUE(active_layer
);
1037 pending_layer
->SetTextureMailbox(
1038 test_data_
.mailbox1_
,
1039 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1041 // Test multiple commits without an activation.
1043 test_data_
.mock_callback_
,
1044 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1046 pending_layer
->SetTextureMailbox(
1047 test_data_
.mailbox2_
,
1048 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox2_impl_
));
1049 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1051 // Test callback after activation.
1052 pending_layer
->PushPropertiesTo(active_layer
.get());
1053 active_layer
->DidBecomeActive();
1055 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1056 pending_layer
->SetTextureMailbox(
1057 test_data_
.mailbox1_
,
1058 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1059 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1061 EXPECT_CALL(test_data_
.mock_callback_
,
1062 ReleaseImpl(test_data_
.mailbox_name2_
, _
, false, _
)).Times(1);
1063 pending_layer
->PushPropertiesTo(active_layer
.get());
1064 active_layer
->DidBecomeActive();
1065 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1067 // Test resetting the mailbox.
1068 EXPECT_CALL(test_data_
.mock_callback_
,
1069 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1070 pending_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1071 pending_layer
->PushPropertiesTo(active_layer
.get());
1072 active_layer
->DidBecomeActive();
1073 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1077 test_data_
.mock_callback_
,
1078 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1080 pending_layer
->SetTextureMailbox(
1081 test_data_
.mailbox1_
,
1082 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1085 TEST_F(TextureLayerImplWithMailboxTest
,
1086 TestDestructorCallbackOnCreatedResource
) {
1087 scoped_ptr
<TextureLayerImpl
> impl_layer
;
1088 impl_layer
= TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1089 ASSERT_TRUE(impl_layer
);
1091 EXPECT_CALL(test_data_
.mock_callback_
,
1092 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1093 impl_layer
->SetTextureMailbox(
1094 test_data_
.mailbox1_
,
1095 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1096 impl_layer
->DidBecomeActive();
1097 EXPECT_TRUE(impl_layer
->WillDraw(
1098 DRAW_MODE_HARDWARE
, host_impl_
.active_tree()->resource_provider()));
1099 impl_layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
1100 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1103 TEST_F(TextureLayerImplWithMailboxTest
, TestCallbackOnInUseResource
) {
1104 ResourceProvider
* provider
= host_impl_
.active_tree()->resource_provider();
1105 ResourceProvider::ResourceId id
= provider
->CreateResourceFromTextureMailbox(
1106 test_data_
.mailbox1_
,
1107 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1108 provider
->AllocateForTesting(id
);
1110 // Transfer some resources to the parent.
1111 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1112 resource_ids_to_transfer
.push_back(id
);
1113 TransferableResourceArray list
;
1114 provider
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1115 EXPECT_TRUE(provider
->InUseByConsumer(id
));
1116 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1117 provider
->DeleteResource(id
);
1118 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1119 EXPECT_CALL(test_data_
.mock_callback_
,
1120 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1121 ReturnedResourceArray returned
;
1122 TransferableResource::ReturnResources(list
, &returned
);
1123 provider
->ReceiveReturnsFromParent(returned
);
1126 // Checks that TextureLayer::Update does not cause an extra commit when setting
1127 // the texture mailbox.
1128 class TextureLayerNoExtraCommitForMailboxTest
1129 : public LayerTreeTest
,
1130 public TextureLayerClient
{
1132 // TextureLayerClient implementation.
1133 bool PrepareTextureMailbox(
1134 TextureMailbox
* texture_mailbox
,
1135 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1136 bool use_shared_memory
) override
{
1137 if (layer_tree_host()->source_frame_number() == 1) {
1138 // Once this has been committed, the mailbox will be released.
1139 *texture_mailbox
= TextureMailbox();
1143 *texture_mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1144 *release_callback
= SingleReleaseCallback::Create(
1145 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased
,
1146 base::Unretained(this)));
1150 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1151 // Source frame number during callback is the same as the source frame
1152 // on which it was released.
1153 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1157 void SetupTree() override
{
1158 scoped_refptr
<Layer
> root
= Layer::Create();
1159 root
->SetBounds(gfx::Size(10, 10));
1160 root
->SetIsDrawable(true);
1162 texture_layer_
= TextureLayer::CreateForMailbox(this);
1163 texture_layer_
->SetBounds(gfx::Size(10, 10));
1164 texture_layer_
->SetIsDrawable(true);
1165 root
->AddChild(texture_layer_
);
1167 layer_tree_host()->SetRootLayer(root
);
1168 LayerTreeTest::SetupTree();
1171 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1173 void DidCommitAndDrawFrame() override
{
1174 switch (layer_tree_host()->source_frame_number()) {
1176 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1177 // Invalidate the texture layer to clear the mailbox before
1179 texture_layer_
->SetNeedsDisplay();
1189 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1190 ASSERT_TRUE(result
);
1191 DelegatedFrameData
* delegated_frame_data
=
1192 output_surface()->last_sent_frame().delegated_frame_data
.get();
1193 if (!delegated_frame_data
)
1196 // Return all resources immediately.
1197 TransferableResourceArray resources_to_return
=
1198 output_surface()->resources_held_by_parent();
1200 CompositorFrameAck ack
;
1201 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1202 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1203 host_impl
->ReclaimResources(&ack
);
1206 void AfterTest() override
{}
1209 scoped_refptr
<TextureLayer
> texture_layer_
;
1212 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest
);
1214 // Checks that changing a mailbox in the client for a TextureLayer that's
1215 // invisible correctly works and uses the new mailbox as soon as the layer
1216 // becomes visible (and returns the old one).
1217 class TextureLayerChangeInvisibleMailboxTest
1218 : public LayerTreeTest
,
1219 public TextureLayerClient
{
1221 TextureLayerChangeInvisibleMailboxTest()
1222 : mailbox_changed_(true),
1223 mailbox_returned_(0),
1226 mailbox_
= MakeMailbox('1');
1229 // TextureLayerClient implementation.
1230 bool PrepareTextureMailbox(
1231 TextureMailbox
* mailbox
,
1232 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1233 bool use_shared_memory
) override
{
1235 if (!mailbox_changed_
)
1237 *mailbox
= mailbox_
;
1238 *release_callback
= SingleReleaseCallback::Create(
1239 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased
,
1240 base::Unretained(this)));
1244 TextureMailbox
MakeMailbox(char name
) {
1245 return TextureMailbox(MailboxFromChar(name
), GL_TEXTURE_2D
, 0);
1248 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1249 ++mailbox_returned_
;
1252 void SetupTree() override
{
1253 scoped_refptr
<Layer
> root
= Layer::Create();
1254 root
->SetBounds(gfx::Size(10, 10));
1255 root
->SetIsDrawable(true);
1257 solid_layer_
= SolidColorLayer::Create();
1258 solid_layer_
->SetBounds(gfx::Size(10, 10));
1259 solid_layer_
->SetIsDrawable(true);
1260 solid_layer_
->SetBackgroundColor(SK_ColorWHITE
);
1261 root
->AddChild(solid_layer_
);
1263 parent_layer_
= Layer::Create();
1264 parent_layer_
->SetBounds(gfx::Size(10, 10));
1265 parent_layer_
->SetIsDrawable(true);
1266 root
->AddChild(parent_layer_
);
1268 texture_layer_
= TextureLayer::CreateForMailbox(this);
1269 texture_layer_
->SetBounds(gfx::Size(10, 10));
1270 texture_layer_
->SetIsDrawable(true);
1271 parent_layer_
->AddChild(texture_layer_
);
1273 layer_tree_host()->SetRootLayer(root
);
1274 LayerTreeTest::SetupTree();
1277 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1279 void DidCommitAndDrawFrame() override
{
1281 switch (commit_count_
) {
1283 // We should have updated the layer, committing the texture.
1284 EXPECT_EQ(1, prepare_called_
);
1285 // Make layer invisible.
1286 parent_layer_
->SetOpacity(0.f
);
1289 // Layer shouldn't have been updated.
1290 EXPECT_EQ(1, prepare_called_
);
1291 // Change the texture.
1292 mailbox_
= MakeMailbox('2');
1293 mailbox_changed_
= true;
1294 texture_layer_
->SetNeedsDisplay();
1295 // Force a change to make sure we draw a frame.
1296 solid_layer_
->SetBackgroundColor(SK_ColorGRAY
);
1299 // Layer shouldn't have been updated.
1300 EXPECT_EQ(1, prepare_called_
);
1301 // So the old mailbox isn't returned yet.
1302 EXPECT_EQ(0, mailbox_returned_
);
1303 // Make layer visible again.
1304 parent_layer_
->SetOpacity(1.f
);
1307 // Layer should have been updated.
1308 EXPECT_EQ(2, prepare_called_
);
1309 // So the old mailbox should have been returned already.
1310 EXPECT_EQ(1, mailbox_returned_
);
1311 texture_layer_
->ClearClient();
1314 EXPECT_EQ(2, mailbox_returned_
);
1323 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1324 ASSERT_TRUE(result
);
1325 DelegatedFrameData
* delegated_frame_data
=
1326 output_surface()->last_sent_frame().delegated_frame_data
.get();
1327 if (!delegated_frame_data
)
1330 // Return all resources immediately.
1331 TransferableResourceArray resources_to_return
=
1332 output_surface()->resources_held_by_parent();
1334 CompositorFrameAck ack
;
1335 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1336 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1337 host_impl
->ReclaimResources(&ack
);
1340 void AfterTest() override
{}
1343 scoped_refptr
<SolidColorLayer
> solid_layer_
;
1344 scoped_refptr
<Layer
> parent_layer_
;
1345 scoped_refptr
<TextureLayer
> texture_layer_
;
1347 // Used on the main thread.
1348 bool mailbox_changed_
;
1349 TextureMailbox mailbox_
;
1350 int mailbox_returned_
;
1351 int prepare_called_
;
1355 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest
);
1357 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1358 // the mailbox back to TextureLayerClient.
1359 class TextureLayerReleaseResourcesBase
1360 : public LayerTreeTest
,
1361 public TextureLayerClient
{
1363 // TextureLayerClient implementation.
1364 bool PrepareTextureMailbox(
1365 TextureMailbox
* mailbox
,
1366 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1367 bool use_shared_memory
) override
{
1368 *mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1369 *release_callback
= SingleReleaseCallback::Create(
1370 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased
,
1371 base::Unretained(this)));
1375 void MailboxReleased(unsigned sync_point
, bool lost_resource
) {
1376 mailbox_released_
= true;
1379 void SetupTree() override
{
1380 LayerTreeTest::SetupTree();
1382 scoped_refptr
<TextureLayer
> texture_layer
=
1383 TextureLayer::CreateForMailbox(this);
1384 texture_layer
->SetBounds(gfx::Size(10, 10));
1385 texture_layer
->SetIsDrawable(true);
1387 layer_tree_host()->root_layer()->AddChild(texture_layer
);
1390 void BeginTest() override
{
1391 mailbox_released_
= false;
1392 PostSetNeedsCommitToMainThread();
1395 void DidCommitAndDrawFrame() override
{ EndTest(); }
1397 void AfterTest() override
{ EXPECT_TRUE(mailbox_released_
); }
1400 bool mailbox_released_
;
1403 class TextureLayerReleaseResourcesAfterCommit
1404 : public TextureLayerReleaseResourcesBase
{
1406 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
1407 LayerTreeImpl
* tree
= nullptr;
1408 if (host_impl
->settings().impl_side_painting
)
1409 tree
= host_impl
->pending_tree();
1411 tree
= host_impl
->active_tree();
1412 tree
->root_layer()->children()[0]->ReleaseResources();
1416 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit
);
1418 class TextureLayerReleaseResourcesAfterActivate
1419 : public TextureLayerReleaseResourcesBase
{
1421 void DidActivateTreeOnThread(LayerTreeHostImpl
* host_impl
) override
{
1422 host_impl
->active_tree()->root_layer()->children()[0]->ReleaseResources();
1426 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate
);
1428 class TextureLayerWithMailboxMainThreadDeleted
: public LayerTreeTest
{
1430 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1431 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1432 EXPECT_FALSE(lost_resource
);
1437 void SetMailbox(char mailbox_char
) {
1438 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1439 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1441 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback
,
1442 base::Unretained(this)));
1443 layer_
->SetTextureMailbox(
1444 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1448 void SetupTree() override
{
1449 gfx::Size
bounds(100, 100);
1450 root_
= Layer::Create();
1451 root_
->SetBounds(bounds
);
1453 layer_
= TextureLayer::CreateForMailbox(nullptr);
1454 layer_
->SetIsDrawable(true);
1455 layer_
->SetBounds(bounds
);
1457 root_
->AddChild(layer_
);
1458 layer_tree_host()->SetRootLayer(root_
);
1459 layer_tree_host()->SetViewportSize(bounds
);
1462 void BeginTest() override
{
1463 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1465 callback_count_
= 0;
1467 // Set the mailbox on the main thread.
1469 EXPECT_EQ(0, callback_count_
);
1471 PostSetNeedsCommitToMainThread();
1474 void DidCommitAndDrawFrame() override
{
1475 switch (layer_tree_host()->source_frame_number()) {
1477 // Delete the TextureLayer on the main thread while the mailbox is in
1479 layer_
->RemoveFromParent();
1485 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1488 base::ThreadChecker main_thread_
;
1489 int callback_count_
;
1490 scoped_refptr
<Layer
> root_
;
1491 scoped_refptr
<TextureLayer
> layer_
;
1494 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1495 TextureLayerWithMailboxMainThreadDeleted
);
1497 class TextureLayerWithMailboxImplThreadDeleted
: public LayerTreeTest
{
1499 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1500 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1501 EXPECT_FALSE(lost_resource
);
1506 void SetMailbox(char mailbox_char
) {
1507 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1508 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1510 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback
,
1511 base::Unretained(this)));
1512 layer_
->SetTextureMailbox(
1513 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1517 void SetupTree() override
{
1518 gfx::Size
bounds(100, 100);
1519 root_
= Layer::Create();
1520 root_
->SetBounds(bounds
);
1522 layer_
= TextureLayer::CreateForMailbox(nullptr);
1523 layer_
->SetIsDrawable(true);
1524 layer_
->SetBounds(bounds
);
1526 root_
->AddChild(layer_
);
1527 layer_tree_host()->SetRootLayer(root_
);
1528 layer_tree_host()->SetViewportSize(bounds
);
1531 void BeginTest() override
{
1532 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1534 callback_count_
= 0;
1536 // Set the mailbox on the main thread.
1538 EXPECT_EQ(0, callback_count_
);
1540 PostSetNeedsCommitToMainThread();
1543 void DidCommitAndDrawFrame() override
{
1544 switch (layer_tree_host()->source_frame_number()) {
1546 // Remove the TextureLayer on the main thread while the mailbox is in
1547 // the impl tree, but don't delete the TextureLayer until after the impl
1548 // tree side is deleted.
1549 layer_
->RemoveFromParent();
1557 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1560 base::ThreadChecker main_thread_
;
1561 int callback_count_
;
1562 scoped_refptr
<Layer
> root_
;
1563 scoped_refptr
<TextureLayer
> layer_
;
1566 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1567 TextureLayerWithMailboxImplThreadDeleted
);