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
->SetNearestNeighbor(true));
209 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetUV(
210 gfx::PointF(0.25f
, 0.25f
), gfx::PointF(0.75f
, 0.75f
)));
211 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetVertexOpacity(
212 0.5f
, 0.5f
, 0.5f
, 0.5f
));
213 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetPremultipliedAlpha(false));
214 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetBlendBackgroundColor(true));
217 TEST_F(TextureLayerTest
, VisibleContentOpaqueRegion
) {
218 const gfx::Size
layer_bounds(100, 100);
219 const gfx::Rect
layer_rect(layer_bounds
);
220 const Region
layer_region(layer_rect
);
222 scoped_refptr
<TextureLayer
> layer
= TextureLayer::CreateForMailbox(nullptr);
223 layer
->SetBounds(layer_bounds
);
224 layer
->draw_properties().visible_content_rect
= layer_rect
;
225 layer
->SetBlendBackgroundColor(true);
227 // Verify initial conditions.
228 EXPECT_FALSE(layer
->contents_opaque());
229 EXPECT_EQ(0u, layer
->background_color());
230 EXPECT_EQ(Region().ToString(),
231 layer
->VisibleContentOpaqueRegion().ToString());
233 // Opaque background.
234 layer
->SetBackgroundColor(SK_ColorWHITE
);
235 EXPECT_EQ(layer_region
.ToString(),
236 layer
->VisibleContentOpaqueRegion().ToString());
238 // Transparent background.
239 layer
->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
240 EXPECT_EQ(Region().ToString(),
241 layer
->VisibleContentOpaqueRegion().ToString());
244 TEST_F(TextureLayerTest
, RateLimiter
) {
245 FakeTextureLayerClient client
;
246 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(
248 test_layer
->SetIsDrawable(true);
249 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
250 layer_tree_host_
->SetRootLayer(test_layer
);
252 // Don't rate limit until we invalidate.
253 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
254 test_layer
->SetRateLimitContext(true);
255 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
257 // Do rate limit after we invalidate.
258 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
259 test_layer
->SetNeedsDisplay();
260 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
262 // Stop rate limiter when we don't want it any more.
263 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
264 test_layer
->SetRateLimitContext(false);
265 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
267 // Or we clear the client.
268 test_layer
->SetRateLimitContext(true);
269 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
270 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
271 test_layer
->ClearClient();
272 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
274 // Reset to a layer with a client, that started the rate limiter.
275 test_layer
= TextureLayer::CreateForMailbox(
277 test_layer
->SetIsDrawable(true);
278 test_layer
->SetRateLimitContext(true);
279 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
280 layer_tree_host_
->SetRootLayer(test_layer
);
281 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
282 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
283 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
284 test_layer
->SetNeedsDisplay();
285 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
287 // Stop rate limiter when we're removed from the tree.
288 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
289 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(1);
290 layer_tree_host_
->SetRootLayer(nullptr);
291 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
294 class TestMailboxHolder
: public TextureLayer::TextureMailboxHolder
{
296 using TextureLayer::TextureMailboxHolder::Create
;
299 ~TestMailboxHolder() override
{}
302 class TextureLayerWithMailboxTest
: public TextureLayerTest
{
304 virtual void TearDown() {
305 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
306 EXPECT_CALL(test_data_
.mock_callback_
,
307 Release(test_data_
.mailbox_name1_
,
308 test_data_
.sync_point1_
,
310 TextureLayerTest::TearDown();
313 CommonMailboxObjects test_data_
;
316 TEST_F(TextureLayerWithMailboxTest
, ReplaceMailboxOnMainThreadBeforeCommit
) {
317 scoped_refptr
<TextureLayer
> test_layer
=
318 TextureLayer::CreateForMailbox(nullptr);
319 ASSERT_TRUE(test_layer
.get());
321 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
322 layer_tree_host_
->SetRootLayer(test_layer
);
323 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
325 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
326 test_layer
->SetTextureMailbox(
327 test_data_
.mailbox1_
,
328 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
329 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
331 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
332 EXPECT_CALL(test_data_
.mock_callback_
,
333 Release(test_data_
.mailbox_name1_
,
334 test_data_
.sync_point1_
,
337 test_layer
->SetTextureMailbox(
338 test_data_
.mailbox2_
,
339 SingleReleaseCallback::Create(test_data_
.release_mailbox2_
));
340 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
341 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
343 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
344 EXPECT_CALL(test_data_
.mock_callback_
,
345 Release(test_data_
.mailbox_name2_
,
346 test_data_
.sync_point2_
,
349 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
350 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
351 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
353 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
354 test_layer
->SetTextureMailbox(
355 test_data_
.mailbox3_
,
356 SingleReleaseCallback::Create(test_data_
.release_mailbox3_
));
357 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
358 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
360 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
361 EXPECT_CALL(test_data_
.mock_callback_
,
362 Release2(test_data_
.shared_memory_
.get(),
365 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
366 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
367 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
370 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
371 test_layer
->SetTextureMailbox(
372 test_data_
.mailbox1_
,
373 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
376 TEST_F(TextureLayerTest
, SetTextureMailboxWithoutReleaseCallback
) {
377 scoped_refptr
<TextureLayer
> test_layer
=
378 TextureLayer::CreateForMailbox(nullptr);
379 ASSERT_TRUE(test_layer
.get());
381 // These use the same gpu::Mailbox, but different sync points.
382 TextureMailbox
mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D
, 1);
383 TextureMailbox
mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D
, 2);
385 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
386 layer_tree_host_
->SetRootLayer(test_layer
);
387 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
389 // Set the mailbox the first time. It should cause a commit.
390 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
391 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox1
);
392 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
394 // Set the mailbox again with a new sync point, as the backing texture has
395 // been updated. It should cause a new commit.
396 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
397 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox2
);
398 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
401 class TextureLayerMailboxHolderTest
: public TextureLayerTest
{
403 TextureLayerMailboxHolderTest()
404 : main_thread_("MAIN") {
405 main_thread_
.Start();
406 main_thread_
.message_loop()->PostTask(
408 base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain
,
409 base::Unretained(this)));
413 void Wait(const base::Thread
& thread
) {
414 bool manual_reset
= false;
415 bool initially_signaled
= false;
416 base::WaitableEvent
event(manual_reset
, initially_signaled
);
417 thread
.message_loop()->PostTask(
419 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
423 void CreateMainRef() {
424 main_ref_
= TestMailboxHolder::Create(
425 test_data_
.mailbox1_
,
426 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
)).Pass();
429 void ReleaseMainRef() { main_ref_
= nullptr; }
431 void CreateImplRef(scoped_ptr
<SingleReleaseCallbackImpl
>* impl_ref
) {
432 *impl_ref
= main_ref_
->holder()->GetCallbackForImplThread();
435 void CapturePostTasksAndWait(base::WaitableEvent
* begin_capture
,
436 base::WaitableEvent
* wait_for_capture
,
437 base::WaitableEvent
* stop_capture
) {
438 begin_capture
->Wait();
439 BlockingTaskRunner::CapturePostTasks
capture(
440 main_thread_task_runner_
.get());
441 wait_for_capture
->Signal();
442 stop_capture
->Wait();
446 void InitializeOnMain() {
447 main_thread_task_runner_
=
448 BlockingTaskRunner::Create(main_thread_
.message_loop_proxy());
451 scoped_ptr
<TestMailboxHolder::MainThreadReference
>
453 base::Thread main_thread_
;
454 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
455 CommonMailboxObjects test_data_
;
458 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_BothReleaseThenMain
) {
459 scoped_refptr
<TextureLayer
> test_layer
=
460 TextureLayer::CreateForMailbox(nullptr);
461 ASSERT_TRUE(test_layer
.get());
463 main_thread_
.message_loop()->PostTask(
465 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
466 base::Unretained(this)));
470 // The texture layer is attached to compositor1, and passes a reference to its
472 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
473 main_thread_
.message_loop()->PostTask(
475 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
476 base::Unretained(this),
479 // Then the texture layer is removed and attached to compositor2, and passes a
480 // reference to its impl tree.
481 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
482 main_thread_
.message_loop()->PostTask(
484 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
485 base::Unretained(this),
489 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
491 // The compositors both destroy their impl trees before the main thread layer
493 compositor1
->Run(100, false, main_thread_task_runner_
.get());
494 compositor2
->Run(200, false, main_thread_task_runner_
.get());
498 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
499 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
501 // The main thread ref is the last one, so the mailbox is released back to the
502 // embedder, with the last sync point provided by the impl trees.
503 EXPECT_CALL(test_data_
.mock_callback_
,
504 Release(test_data_
.mailbox_name1_
, 200, false)).Times(1);
506 main_thread_
.message_loop()->PostTask(
508 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
509 base::Unretained(this)));
511 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
514 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleaseBetween
) {
515 scoped_refptr
<TextureLayer
> test_layer
=
516 TextureLayer::CreateForMailbox(nullptr);
517 ASSERT_TRUE(test_layer
.get());
519 main_thread_
.message_loop()->PostTask(
521 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
522 base::Unretained(this)));
526 // The texture layer is attached to compositor1, and passes a reference to its
528 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
529 main_thread_
.message_loop()->PostTask(
531 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
532 base::Unretained(this),
535 // Then the texture layer is removed and attached to compositor2, and passes a
536 // reference to its impl tree.
537 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
538 main_thread_
.message_loop()->PostTask(
540 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
541 base::Unretained(this),
545 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
547 // One compositor destroys their impl tree.
548 compositor1
->Run(100, false, main_thread_task_runner_
.get());
550 // Then the main thread reference is destroyed.
551 main_thread_
.message_loop()->PostTask(
553 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
554 base::Unretained(this)));
558 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
559 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
561 // The second impl reference is destroyed last, causing the mailbox to be
562 // released back to the embedder with the last sync point from the impl tree.
563 EXPECT_CALL(test_data_
.mock_callback_
,
564 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
566 compositor2
->Run(200, true, main_thread_task_runner_
.get());
568 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
571 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleasedFirst
) {
572 scoped_refptr
<TextureLayer
> test_layer
=
573 TextureLayer::CreateForMailbox(nullptr);
574 ASSERT_TRUE(test_layer
.get());
576 main_thread_
.message_loop()->PostTask(
578 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
579 base::Unretained(this)));
583 // The texture layer is attached to compositor1, and passes a reference to its
585 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
586 main_thread_
.message_loop()->PostTask(
588 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
589 base::Unretained(this),
592 // Then the texture layer is removed and attached to compositor2, and passes a
593 // reference to its impl tree.
594 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
595 main_thread_
.message_loop()->PostTask(
597 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
598 base::Unretained(this),
602 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
604 // The main thread reference is destroyed first.
605 main_thread_
.message_loop()->PostTask(
607 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
608 base::Unretained(this)));
610 // One compositor destroys their impl tree.
611 compositor2
->Run(200, false, main_thread_task_runner_
.get());
615 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
616 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
618 // The second impl reference is destroyed last, causing the mailbox to be
619 // released back to the embedder with the last sync point from the impl tree.
620 EXPECT_CALL(test_data_
.mock_callback_
,
621 Release(test_data_
.mailbox_name1_
, 100, true)).Times(1);
623 compositor1
->Run(100, true, main_thread_task_runner_
.get());
625 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
628 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_SecondImplRefShortcut
) {
629 scoped_refptr
<TextureLayer
> test_layer
=
630 TextureLayer::CreateForMailbox(nullptr);
631 ASSERT_TRUE(test_layer
.get());
633 main_thread_
.message_loop()->PostTask(
635 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
636 base::Unretained(this)));
640 // The texture layer is attached to compositor1, and passes a reference to its
642 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
643 main_thread_
.message_loop()->PostTask(
645 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
646 base::Unretained(this),
649 // Then the texture layer is removed and attached to compositor2, and passes a
650 // reference to its impl tree.
651 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
652 main_thread_
.message_loop()->PostTask(
654 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
655 base::Unretained(this),
659 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
661 // The main thread reference is destroyed first.
662 main_thread_
.message_loop()->PostTask(
664 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
665 base::Unretained(this)));
667 EXPECT_CALL(test_data_
.mock_callback_
,
668 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
670 bool manual_reset
= false;
671 bool initially_signaled
= false;
672 base::WaitableEvent
begin_capture(manual_reset
, initially_signaled
);
673 base::WaitableEvent
wait_for_capture(manual_reset
, initially_signaled
);
674 base::WaitableEvent
stop_capture(manual_reset
, initially_signaled
);
676 // Post a task to start capturing tasks on the main thread. This will block
677 // the main thread until we signal the |stop_capture| event.
678 main_thread_
.message_loop()->PostTask(
680 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait
,
681 base::Unretained(this),
686 // Before the main thread capturing starts, one compositor destroys their
687 // impl reference. Since capturing did not start, this gets post-tasked to
689 compositor1
->Run(100, false, main_thread_task_runner_
.get());
691 // Start capturing on the main thread.
692 begin_capture
.Signal();
693 wait_for_capture
.Wait();
695 // Meanwhile, the second compositor released its impl reference, but this task
696 // gets shortcutted directly to the main thread. This means the reference is
697 // released before compositor1, whose reference will be released later when
698 // the post-task is serviced. But since it was destroyed _on the impl thread_
699 // last, its sync point values should be used.
700 compositor2
->Run(200, true, main_thread_task_runner_
.get());
702 stop_capture
.Signal();
705 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
708 class TextureLayerImplWithMailboxThreadedCallback
: public LayerTreeTest
{
710 TextureLayerImplWithMailboxThreadedCallback()
711 : callback_count_(0),
714 // Make sure callback is received on main and doesn't block the impl thread.
715 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
716 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
717 EXPECT_FALSE(lost_resource
);
721 void SetMailbox(char mailbox_char
) {
722 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
723 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
725 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback
,
726 base::Unretained(this)));
727 layer_
->SetTextureMailbox(
728 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
732 void BeginTest() override
{
733 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
735 gfx::Size
bounds(100, 100);
736 root_
= Layer::Create();
737 root_
->SetBounds(bounds
);
739 layer_
= TextureLayer::CreateForMailbox(nullptr);
740 layer_
->SetIsDrawable(true);
741 layer_
->SetBounds(bounds
);
743 root_
->AddChild(layer_
);
744 layer_tree_host()->SetRootLayer(root_
);
745 layer_tree_host()->SetViewportSize(bounds
);
747 EXPECT_EQ(0, callback_count_
);
749 // Case #1: change mailbox before the commit. The old mailbox should be
750 // released immediately.
752 EXPECT_EQ(1, callback_count_
);
753 PostSetNeedsCommitToMainThread();
756 void DidCommit() override
{
758 switch (commit_count_
) {
760 // Case #2: change mailbox after the commit (and draw), where the
761 // layer draws. The old mailbox should be released during the next
764 EXPECT_EQ(1, callback_count_
);
767 EXPECT_EQ(2, callback_count_
);
768 // Case #3: change mailbox when the layer doesn't draw. The old
769 // mailbox should be released during the next commit.
770 layer_
->SetBounds(gfx::Size());
774 EXPECT_EQ(3, callback_count_
);
775 // Case #4: release mailbox that was committed but never drawn. The
776 // old mailbox should be released during the next commit.
777 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
780 if (layer_tree_host()->settings().impl_side_painting
) {
781 // With impl painting, the texture mailbox will still be on the impl
782 // thread when the commit finishes, because the layer is not drawble
783 // when it has no texture mailbox, and thus does not block the commit
784 // on activation. So, we wait for activation.
785 // TODO(danakj): fix this. crbug.com/277953
786 layer_tree_host()->SetNeedsCommit();
792 EXPECT_EQ(4, callback_count_
);
793 // Restore a mailbox for the next step.
797 // Case #5: remove layer from tree. Callback should *not* be called, the
798 // mailbox is returned to the main thread.
799 EXPECT_EQ(4, callback_count_
);
800 layer_
->RemoveFromParent();
803 if (layer_tree_host()->settings().impl_side_painting
) {
804 // With impl painting, the texture mailbox will still be on the impl
805 // thread when the commit finishes, because the layer is not around to
806 // block the commit on activation anymore. So, we wait for activation.
807 // TODO(danakj): fix this. crbug.com/277953
808 layer_tree_host()->SetNeedsCommit();
814 EXPECT_EQ(4, callback_count_
);
815 // Resetting the mailbox will call the callback now.
816 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
817 EXPECT_EQ(5, callback_count_
);
826 void AfterTest() override
{}
829 base::ThreadChecker main_thread_
;
832 scoped_refptr
<Layer
> root_
;
833 scoped_refptr
<TextureLayer
> layer_
;
836 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
837 TextureLayerImplWithMailboxThreadedCallback
);
840 class TextureLayerMailboxIsActivatedDuringCommit
: public LayerTreeTest
{
842 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
844 static void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {}
846 void SetMailbox(char mailbox_char
) {
847 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
849 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback
));
850 layer_
->SetTextureMailbox(
851 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
855 void BeginTest() override
{
856 gfx::Size
bounds(100, 100);
857 root_
= Layer::Create();
858 root_
->SetBounds(bounds
);
860 layer_
= TextureLayer::CreateForMailbox(nullptr);
861 layer_
->SetIsDrawable(true);
862 layer_
->SetBounds(bounds
);
864 root_
->AddChild(layer_
);
865 layer_tree_host()->SetRootLayer(root_
);
866 layer_tree_host()->SetViewportSize(bounds
);
869 PostSetNeedsCommitToMainThread();
872 void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
876 void DidCommit() override
{
877 switch (layer_tree_host()->source_frame_number()) {
879 // The first mailbox has been activated. Set a new mailbox, and
880 // expect the next commit to finish *after* it is activated.
884 // The second mailbox has been activated. Remove the layer from
885 // the tree to cause another commit/activation. The commit should
886 // finish *after* the layer is removed from the active tree.
887 layer_
->RemoveFromParent();
895 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
896 switch (host_impl
->active_tree()->source_frame_number()) {
898 // The activate for the 1st mailbox should have happened before now.
899 EXPECT_EQ(1, activate_count_
);
903 // The activate for the 2nd mailbox should have happened before now.
904 EXPECT_EQ(2, activate_count_
);
908 // The activate to remove the layer should have happened before now.
909 EXPECT_EQ(3, activate_count_
);
919 void AfterTest() override
{}
922 scoped_refptr
<Layer
> root_
;
923 scoped_refptr
<TextureLayer
> layer_
;
926 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
927 TextureLayerMailboxIsActivatedDuringCommit
);
929 class TextureLayerImplWithMailboxTest
: public TextureLayerTest
{
931 TextureLayerImplWithMailboxTest()
933 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)) {}
935 virtual void SetUp() {
936 TextureLayerTest::SetUp();
937 layer_tree_host_
.reset(new MockLayerTreeHost(&fake_client_
));
938 EXPECT_TRUE(host_impl_
.InitializeRenderer(FakeOutputSurface::Create3d()));
941 bool WillDraw(TextureLayerImpl
* layer
, DrawMode mode
) {
942 bool will_draw
= layer
->WillDraw(
943 mode
, host_impl_
.active_tree()->resource_provider());
945 layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
949 CommonMailboxObjects test_data_
;
950 FakeLayerTreeHostClient fake_client_
;
953 // Test conditions for results of TextureLayerImpl::WillDraw under
954 // different configurations of different mailbox, texture_id, and draw_mode.
955 TEST_F(TextureLayerImplWithMailboxTest
, TestWillDraw
) {
957 test_data_
.mock_callback_
,
958 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
960 EXPECT_CALL(test_data_
.mock_callback_
,
961 ReleaseImpl2(test_data_
.shared_memory_
.get(), 0, false, _
))
965 scoped_ptr
<TextureLayerImpl
> impl_layer
=
966 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
967 impl_layer
->SetTextureMailbox(
968 test_data_
.mailbox1_
,
969 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
970 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
974 scoped_ptr
<TextureLayerImpl
> impl_layer
=
975 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
976 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
977 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
981 // Software resource.
982 scoped_ptr
<TextureLayerImpl
> impl_layer
=
983 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
984 impl_layer
->SetTextureMailbox(
985 test_data_
.mailbox3_
,
986 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
987 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
992 scoped_ptr
<TextureLayerImpl
> impl_layer
=
993 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
994 impl_layer
->SetTextureMailbox(
995 test_data_
.mailbox1_
,
996 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
997 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
1001 scoped_ptr
<TextureLayerImpl
> impl_layer
=
1002 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1003 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1004 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
1008 // Software resource.
1009 scoped_ptr
<TextureLayerImpl
> impl_layer
=
1010 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1011 impl_layer
->SetTextureMailbox(
1012 test_data_
.mailbox3_
,
1013 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
1014 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
1017 // Resourceless software mode.
1019 scoped_ptr
<TextureLayerImpl
> impl_layer
=
1020 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1021 impl_layer
->SetTextureMailbox(
1022 test_data_
.mailbox1_
,
1023 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1024 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_RESOURCELESS_SOFTWARE
));
1028 TEST_F(TextureLayerImplWithMailboxTest
, TestImplLayerCallbacks
) {
1029 host_impl_
.CreatePendingTree();
1030 scoped_ptr
<TextureLayerImpl
> pending_layer
;
1031 pending_layer
= TextureLayerImpl::Create(host_impl_
.pending_tree(), 1);
1032 ASSERT_TRUE(pending_layer
);
1034 scoped_ptr
<LayerImpl
> active_layer(
1035 pending_layer
->CreateLayerImpl(host_impl_
.active_tree()));
1036 ASSERT_TRUE(active_layer
);
1038 pending_layer
->SetTextureMailbox(
1039 test_data_
.mailbox1_
,
1040 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1042 // Test multiple commits without an activation.
1044 test_data_
.mock_callback_
,
1045 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1047 pending_layer
->SetTextureMailbox(
1048 test_data_
.mailbox2_
,
1049 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox2_impl_
));
1050 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1052 // Test callback after activation.
1053 pending_layer
->PushPropertiesTo(active_layer
.get());
1054 active_layer
->DidBecomeActive();
1056 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1057 pending_layer
->SetTextureMailbox(
1058 test_data_
.mailbox1_
,
1059 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1060 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1062 EXPECT_CALL(test_data_
.mock_callback_
,
1063 ReleaseImpl(test_data_
.mailbox_name2_
, _
, false, _
)).Times(1);
1064 pending_layer
->PushPropertiesTo(active_layer
.get());
1065 active_layer
->DidBecomeActive();
1066 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1068 // Test resetting the mailbox.
1069 EXPECT_CALL(test_data_
.mock_callback_
,
1070 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1071 pending_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1072 pending_layer
->PushPropertiesTo(active_layer
.get());
1073 active_layer
->DidBecomeActive();
1074 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1078 test_data_
.mock_callback_
,
1079 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1081 pending_layer
->SetTextureMailbox(
1082 test_data_
.mailbox1_
,
1083 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1086 TEST_F(TextureLayerImplWithMailboxTest
,
1087 TestDestructorCallbackOnCreatedResource
) {
1088 scoped_ptr
<TextureLayerImpl
> impl_layer
;
1089 impl_layer
= TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1090 ASSERT_TRUE(impl_layer
);
1092 EXPECT_CALL(test_data_
.mock_callback_
,
1093 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1094 impl_layer
->SetTextureMailbox(
1095 test_data_
.mailbox1_
,
1096 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1097 impl_layer
->DidBecomeActive();
1098 EXPECT_TRUE(impl_layer
->WillDraw(
1099 DRAW_MODE_HARDWARE
, host_impl_
.active_tree()->resource_provider()));
1100 impl_layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
1101 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1104 TEST_F(TextureLayerImplWithMailboxTest
, TestCallbackOnInUseResource
) {
1105 ResourceProvider
* provider
= host_impl_
.active_tree()->resource_provider();
1106 ResourceProvider::ResourceId id
= provider
->CreateResourceFromTextureMailbox(
1107 test_data_
.mailbox1_
,
1108 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1109 provider
->AllocateForTesting(id
);
1111 // Transfer some resources to the parent.
1112 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1113 resource_ids_to_transfer
.push_back(id
);
1114 TransferableResourceArray list
;
1115 provider
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1116 EXPECT_TRUE(provider
->InUseByConsumer(id
));
1117 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1118 provider
->DeleteResource(id
);
1119 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1120 EXPECT_CALL(test_data_
.mock_callback_
,
1121 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1122 ReturnedResourceArray returned
;
1123 TransferableResource::ReturnResources(list
, &returned
);
1124 provider
->ReceiveReturnsFromParent(returned
);
1127 // Checks that TextureLayer::Update does not cause an extra commit when setting
1128 // the texture mailbox.
1129 class TextureLayerNoExtraCommitForMailboxTest
1130 : public LayerTreeTest
,
1131 public TextureLayerClient
{
1133 // TextureLayerClient implementation.
1134 bool PrepareTextureMailbox(
1135 TextureMailbox
* texture_mailbox
,
1136 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1137 bool use_shared_memory
) override
{
1138 if (layer_tree_host()->source_frame_number() == 1) {
1139 // Once this has been committed, the mailbox will be released.
1140 *texture_mailbox
= TextureMailbox();
1144 *texture_mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1145 *release_callback
= SingleReleaseCallback::Create(
1146 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased
,
1147 base::Unretained(this)));
1151 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1152 // Source frame number during callback is the same as the source frame
1153 // on which it was released.
1154 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1158 void SetupTree() override
{
1159 scoped_refptr
<Layer
> root
= Layer::Create();
1160 root
->SetBounds(gfx::Size(10, 10));
1161 root
->SetIsDrawable(true);
1163 texture_layer_
= TextureLayer::CreateForMailbox(this);
1164 texture_layer_
->SetBounds(gfx::Size(10, 10));
1165 texture_layer_
->SetIsDrawable(true);
1166 root
->AddChild(texture_layer_
);
1168 layer_tree_host()->SetRootLayer(root
);
1169 LayerTreeTest::SetupTree();
1172 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1174 void DidCommitAndDrawFrame() override
{
1175 switch (layer_tree_host()->source_frame_number()) {
1177 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1178 // Invalidate the texture layer to clear the mailbox before
1180 texture_layer_
->SetNeedsDisplay();
1190 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1191 ASSERT_TRUE(result
);
1192 DelegatedFrameData
* delegated_frame_data
=
1193 output_surface()->last_sent_frame().delegated_frame_data
.get();
1194 if (!delegated_frame_data
)
1197 // Return all resources immediately.
1198 TransferableResourceArray resources_to_return
=
1199 output_surface()->resources_held_by_parent();
1201 CompositorFrameAck ack
;
1202 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1203 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1204 host_impl
->ReclaimResources(&ack
);
1207 void AfterTest() override
{}
1210 scoped_refptr
<TextureLayer
> texture_layer_
;
1213 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest
);
1215 // Checks that changing a mailbox in the client for a TextureLayer that's
1216 // invisible correctly works and uses the new mailbox as soon as the layer
1217 // becomes visible (and returns the old one).
1218 class TextureLayerChangeInvisibleMailboxTest
1219 : public LayerTreeTest
,
1220 public TextureLayerClient
{
1222 TextureLayerChangeInvisibleMailboxTest()
1223 : mailbox_changed_(true),
1224 mailbox_returned_(0),
1227 mailbox_
= MakeMailbox('1');
1230 // TextureLayerClient implementation.
1231 bool PrepareTextureMailbox(
1232 TextureMailbox
* mailbox
,
1233 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1234 bool use_shared_memory
) override
{
1236 if (!mailbox_changed_
)
1238 *mailbox
= mailbox_
;
1239 *release_callback
= SingleReleaseCallback::Create(
1240 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased
,
1241 base::Unretained(this)));
1245 TextureMailbox
MakeMailbox(char name
) {
1246 return TextureMailbox(MailboxFromChar(name
), GL_TEXTURE_2D
, 0);
1249 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1250 ++mailbox_returned_
;
1253 void SetupTree() override
{
1254 scoped_refptr
<Layer
> root
= Layer::Create();
1255 root
->SetBounds(gfx::Size(10, 10));
1256 root
->SetIsDrawable(true);
1258 solid_layer_
= SolidColorLayer::Create();
1259 solid_layer_
->SetBounds(gfx::Size(10, 10));
1260 solid_layer_
->SetIsDrawable(true);
1261 solid_layer_
->SetBackgroundColor(SK_ColorWHITE
);
1262 root
->AddChild(solid_layer_
);
1264 parent_layer_
= Layer::Create();
1265 parent_layer_
->SetBounds(gfx::Size(10, 10));
1266 parent_layer_
->SetIsDrawable(true);
1267 root
->AddChild(parent_layer_
);
1269 texture_layer_
= TextureLayer::CreateForMailbox(this);
1270 texture_layer_
->SetBounds(gfx::Size(10, 10));
1271 texture_layer_
->SetIsDrawable(true);
1272 parent_layer_
->AddChild(texture_layer_
);
1274 layer_tree_host()->SetRootLayer(root
);
1275 LayerTreeTest::SetupTree();
1278 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1280 void DidCommitAndDrawFrame() override
{
1282 switch (commit_count_
) {
1284 // We should have updated the layer, committing the texture.
1285 EXPECT_EQ(1, prepare_called_
);
1286 // Make layer invisible.
1287 parent_layer_
->SetOpacity(0.f
);
1290 // Layer shouldn't have been updated.
1291 EXPECT_EQ(1, prepare_called_
);
1292 // Change the texture.
1293 mailbox_
= MakeMailbox('2');
1294 mailbox_changed_
= true;
1295 texture_layer_
->SetNeedsDisplay();
1296 // Force a change to make sure we draw a frame.
1297 solid_layer_
->SetBackgroundColor(SK_ColorGRAY
);
1300 // Layer shouldn't have been updated.
1301 EXPECT_EQ(1, prepare_called_
);
1302 // So the old mailbox isn't returned yet.
1303 EXPECT_EQ(0, mailbox_returned_
);
1304 // Make layer visible again.
1305 parent_layer_
->SetOpacity(1.f
);
1308 // Layer should have been updated.
1309 EXPECT_EQ(2, prepare_called_
);
1310 // So the old mailbox should have been returned already.
1311 EXPECT_EQ(1, mailbox_returned_
);
1312 texture_layer_
->ClearClient();
1315 EXPECT_EQ(2, mailbox_returned_
);
1324 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1325 ASSERT_TRUE(result
);
1326 DelegatedFrameData
* delegated_frame_data
=
1327 output_surface()->last_sent_frame().delegated_frame_data
.get();
1328 if (!delegated_frame_data
)
1331 // Return all resources immediately.
1332 TransferableResourceArray resources_to_return
=
1333 output_surface()->resources_held_by_parent();
1335 CompositorFrameAck ack
;
1336 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1337 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1338 host_impl
->ReclaimResources(&ack
);
1341 void AfterTest() override
{}
1344 scoped_refptr
<SolidColorLayer
> solid_layer_
;
1345 scoped_refptr
<Layer
> parent_layer_
;
1346 scoped_refptr
<TextureLayer
> texture_layer_
;
1348 // Used on the main thread.
1349 bool mailbox_changed_
;
1350 TextureMailbox mailbox_
;
1351 int mailbox_returned_
;
1352 int prepare_called_
;
1356 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest
);
1358 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1359 // the mailbox back to TextureLayerClient.
1360 class TextureLayerReleaseResourcesBase
1361 : public LayerTreeTest
,
1362 public TextureLayerClient
{
1364 // TextureLayerClient implementation.
1365 bool PrepareTextureMailbox(
1366 TextureMailbox
* mailbox
,
1367 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1368 bool use_shared_memory
) override
{
1369 *mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1370 *release_callback
= SingleReleaseCallback::Create(
1371 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased
,
1372 base::Unretained(this)));
1376 void MailboxReleased(unsigned sync_point
, bool lost_resource
) {
1377 mailbox_released_
= true;
1380 void SetupTree() override
{
1381 LayerTreeTest::SetupTree();
1383 scoped_refptr
<TextureLayer
> texture_layer
=
1384 TextureLayer::CreateForMailbox(this);
1385 texture_layer
->SetBounds(gfx::Size(10, 10));
1386 texture_layer
->SetIsDrawable(true);
1388 layer_tree_host()->root_layer()->AddChild(texture_layer
);
1391 void BeginTest() override
{
1392 mailbox_released_
= false;
1393 PostSetNeedsCommitToMainThread();
1396 void DidCommitAndDrawFrame() override
{ EndTest(); }
1398 void AfterTest() override
{ EXPECT_TRUE(mailbox_released_
); }
1401 bool mailbox_released_
;
1404 class TextureLayerReleaseResourcesAfterCommit
1405 : public TextureLayerReleaseResourcesBase
{
1407 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
1408 LayerTreeImpl
* tree
= nullptr;
1409 if (host_impl
->settings().impl_side_painting
)
1410 tree
= host_impl
->pending_tree();
1412 tree
= host_impl
->active_tree();
1413 tree
->root_layer()->children()[0]->ReleaseResources();
1417 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit
);
1419 class TextureLayerReleaseResourcesAfterActivate
1420 : public TextureLayerReleaseResourcesBase
{
1422 void DidActivateTreeOnThread(LayerTreeHostImpl
* host_impl
) override
{
1423 host_impl
->active_tree()->root_layer()->children()[0]->ReleaseResources();
1427 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate
);
1429 class TextureLayerWithMailboxMainThreadDeleted
: public LayerTreeTest
{
1431 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1432 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1433 EXPECT_FALSE(lost_resource
);
1438 void SetMailbox(char mailbox_char
) {
1439 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1440 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1442 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback
,
1443 base::Unretained(this)));
1444 layer_
->SetTextureMailbox(
1445 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1449 void SetupTree() override
{
1450 gfx::Size
bounds(100, 100);
1451 root_
= Layer::Create();
1452 root_
->SetBounds(bounds
);
1454 layer_
= TextureLayer::CreateForMailbox(nullptr);
1455 layer_
->SetIsDrawable(true);
1456 layer_
->SetBounds(bounds
);
1458 root_
->AddChild(layer_
);
1459 layer_tree_host()->SetRootLayer(root_
);
1460 layer_tree_host()->SetViewportSize(bounds
);
1463 void BeginTest() override
{
1464 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1466 callback_count_
= 0;
1468 // Set the mailbox on the main thread.
1470 EXPECT_EQ(0, callback_count_
);
1472 PostSetNeedsCommitToMainThread();
1475 void DidCommitAndDrawFrame() override
{
1476 switch (layer_tree_host()->source_frame_number()) {
1478 // Delete the TextureLayer on the main thread while the mailbox is in
1480 layer_
->RemoveFromParent();
1486 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1489 base::ThreadChecker main_thread_
;
1490 int callback_count_
;
1491 scoped_refptr
<Layer
> root_
;
1492 scoped_refptr
<TextureLayer
> layer_
;
1495 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1496 TextureLayerWithMailboxMainThreadDeleted
);
1498 class TextureLayerWithMailboxImplThreadDeleted
: public LayerTreeTest
{
1500 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1501 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1502 EXPECT_FALSE(lost_resource
);
1507 void SetMailbox(char mailbox_char
) {
1508 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1509 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1511 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback
,
1512 base::Unretained(this)));
1513 layer_
->SetTextureMailbox(
1514 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1518 void SetupTree() override
{
1519 gfx::Size
bounds(100, 100);
1520 root_
= Layer::Create();
1521 root_
->SetBounds(bounds
);
1523 layer_
= TextureLayer::CreateForMailbox(nullptr);
1524 layer_
->SetIsDrawable(true);
1525 layer_
->SetBounds(bounds
);
1527 root_
->AddChild(layer_
);
1528 layer_tree_host()->SetRootLayer(root_
);
1529 layer_tree_host()->SetViewportSize(bounds
);
1532 void BeginTest() override
{
1533 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1535 callback_count_
= 0;
1537 // Set the mailbox on the main thread.
1539 EXPECT_EQ(0, callback_count_
);
1541 PostSetNeedsCommitToMainThread();
1544 void DidCommitAndDrawFrame() override
{
1545 switch (layer_tree_host()->source_frame_number()) {
1547 // Remove the TextureLayer on the main thread while the mailbox is in
1548 // the impl tree, but don't delete the TextureLayer until after the impl
1549 // tree side is deleted.
1550 layer_
->RemoveFromParent();
1558 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1561 base::ThreadChecker main_thread_
;
1562 int callback_count_
;
1563 scoped_refptr
<Layer
> root_
;
1564 scoped_refptr
<TextureLayer
> layer_
;
1567 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1568 TextureLayerWithMailboxImplThreadDeleted
);