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/location.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/threading/thread.h"
17 #include "base/time/time.h"
18 #include "cc/layers/solid_color_layer.h"
19 #include "cc/layers/texture_layer_client.h"
20 #include "cc/layers/texture_layer_impl.h"
21 #include "cc/output/compositor_frame_ack.h"
22 #include "cc/output/context_provider.h"
23 #include "cc/resources/returned_resource.h"
24 #include "cc/test/fake_impl_proxy.h"
25 #include "cc/test/fake_layer_tree_host_client.h"
26 #include "cc/test/fake_layer_tree_host_impl.h"
27 #include "cc/test/fake_output_surface.h"
28 #include "cc/test/layer_test_common.h"
29 #include "cc/test/layer_tree_test.h"
30 #include "cc/test/test_task_graph_runner.h"
31 #include "cc/test/test_web_graphics_context_3d.h"
32 #include "cc/trees/blocking_task_runner.h"
33 #include "cc/trees/layer_tree_host.h"
34 #include "cc/trees/layer_tree_impl.h"
35 #include "cc/trees/single_thread_proxy.h"
36 #include "gpu/GLES2/gl2extchromium.h"
37 #include "testing/gmock/include/gmock/gmock.h"
38 #include "testing/gtest/include/gtest/gtest.h"
40 using ::testing::Mock
;
42 using ::testing::AtLeast
;
43 using ::testing::AnyNumber
;
44 using ::testing::InvokeWithoutArgs
;
49 gpu::Mailbox
MailboxFromChar(char value
) {
51 memset(mailbox
.name
, value
, sizeof(mailbox
.name
));
55 class MockLayerTreeHost
: public LayerTreeHost
{
57 static scoped_ptr
<MockLayerTreeHost
> Create(
58 FakeLayerTreeHostClient
* client
,
59 TaskGraphRunner
* task_graph_runner
) {
60 LayerTreeHost::InitParams params
;
61 params
.client
= client
;
62 params
.task_graph_runner
= task_graph_runner
;
63 LayerTreeSettings settings
;
64 params
.settings
= &settings
;
65 return make_scoped_ptr(new MockLayerTreeHost(client
, ¶ms
));
68 MOCK_METHOD0(SetNeedsCommit
, void());
69 MOCK_METHOD0(SetNeedsUpdateLayers
, void());
70 MOCK_METHOD0(StartRateLimiter
, void());
71 MOCK_METHOD0(StopRateLimiter
, void());
74 MockLayerTreeHost(FakeLayerTreeHostClient
* client
,
75 LayerTreeHost::InitParams
* params
)
76 : LayerTreeHost(params
) {
77 InitializeSingleThreaded(client
, base::ThreadTaskRunnerHandle::Get(),
82 class FakeTextureLayerClient
: public TextureLayerClient
{
84 FakeTextureLayerClient() : mailbox_changed_(true) {}
86 bool PrepareTextureMailbox(
87 TextureMailbox
* mailbox
,
88 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
89 bool use_shared_memory
) override
{
90 if (!mailbox_changed_
)
94 *release_callback
= release_callback_
.Pass();
95 mailbox_changed_
= false;
99 void set_mailbox(const TextureMailbox
& mailbox
,
100 scoped_ptr
<SingleReleaseCallback
> release_callback
) {
102 release_callback_
= release_callback
.Pass();
103 mailbox_changed_
= true;
107 TextureMailbox mailbox_
;
108 scoped_ptr
<SingleReleaseCallback
> release_callback_
;
109 bool mailbox_changed_
;
110 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient
);
113 class MockMailboxCallback
{
115 MOCK_METHOD3(Release
,
116 void(const gpu::Mailbox
& mailbox
,
118 bool lost_resource
));
119 MOCK_METHOD3(Release2
,
120 void(SharedBitmap
* shared_bitmap
,
122 bool lost_resource
));
123 MOCK_METHOD4(ReleaseImpl
,
124 void(const gpu::Mailbox
& mailbox
,
127 BlockingTaskRunner
* main_thread_task_runner
));
128 MOCK_METHOD4(ReleaseImpl2
,
129 void(SharedBitmap
* shared_bitmap
,
132 BlockingTaskRunner
* main_thread_task_runner
));
135 struct CommonMailboxObjects
{
136 explicit CommonMailboxObjects(SharedBitmapManager
* manager
)
137 : mailbox_name1_(MailboxFromChar('1')),
138 mailbox_name2_(MailboxFromChar('2')),
141 release_mailbox1_
= base::Bind(&MockMailboxCallback::Release
,
142 base::Unretained(&mock_callback_
),
144 release_mailbox2_
= base::Bind(&MockMailboxCallback::Release
,
145 base::Unretained(&mock_callback_
),
147 release_mailbox1_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
148 base::Unretained(&mock_callback_
),
150 release_mailbox2_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
151 base::Unretained(&mock_callback_
),
153 const uint32 arbitrary_target1
= GL_TEXTURE_2D
;
154 const uint32 arbitrary_target2
= GL_TEXTURE_EXTERNAL_OES
;
155 mailbox1_
= TextureMailbox(mailbox_name1_
, arbitrary_target1
, sync_point1_
);
156 mailbox2_
= TextureMailbox(mailbox_name2_
, arbitrary_target2
, sync_point2_
);
157 gfx::Size
size(128, 128);
158 shared_bitmap_
= manager
->AllocateSharedBitmap(size
);
159 DCHECK(shared_bitmap_
);
161 base::Bind(&MockMailboxCallback::Release2
,
162 base::Unretained(&mock_callback_
), shared_bitmap_
.get());
163 release_mailbox3_impl_
=
164 base::Bind(&MockMailboxCallback::ReleaseImpl2
,
165 base::Unretained(&mock_callback_
), shared_bitmap_
.get());
166 mailbox3_
= TextureMailbox(shared_bitmap_
.get(), size
);
169 gpu::Mailbox mailbox_name1_
;
170 gpu::Mailbox mailbox_name2_
;
171 MockMailboxCallback mock_callback_
;
172 ReleaseCallback release_mailbox1_
;
173 ReleaseCallback release_mailbox2_
;
174 ReleaseCallback release_mailbox3_
;
175 ReleaseCallbackImpl release_mailbox1_impl_
;
176 ReleaseCallbackImpl release_mailbox2_impl_
;
177 ReleaseCallbackImpl release_mailbox3_impl_
;
178 TextureMailbox mailbox1_
;
179 TextureMailbox mailbox2_
;
180 TextureMailbox mailbox3_
;
183 scoped_ptr
<SharedBitmap
> shared_bitmap_
;
186 class TextureLayerTest
: public testing::Test
{
190 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)),
191 host_impl_(&proxy_
, &shared_bitmap_manager_
, &task_graph_runner_
),
192 test_data_(&shared_bitmap_manager_
) {}
195 void SetUp() override
{
197 MockLayerTreeHost::Create(&fake_client_
, &task_graph_runner_
);
198 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
199 layer_tree_host_
->SetViewportSize(gfx::Size(10, 10));
200 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
203 void TearDown() override
{
204 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
205 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
207 layer_tree_host_
->SetRootLayer(nullptr);
208 layer_tree_host_
= nullptr;
211 scoped_ptr
<MockLayerTreeHost
> layer_tree_host_
;
212 FakeImplProxy proxy_
;
213 FakeLayerTreeHostClient fake_client_
;
214 TestSharedBitmapManager shared_bitmap_manager_
;
215 TestTaskGraphRunner task_graph_runner_
;
216 FakeLayerTreeHostImpl host_impl_
;
217 CommonMailboxObjects test_data_
;
218 LayerSettings layer_settings_
;
221 TEST_F(TextureLayerTest
, CheckPropertyChangeCausesCorrectBehavior
) {
222 scoped_refptr
<TextureLayer
> test_layer
=
223 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
224 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_
->SetRootLayer(test_layer
));
226 // Test properties that should call SetNeedsCommit. All properties need to
227 // be set to new values in order for SetNeedsCommit to be called.
228 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetFlipped(false));
229 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetNearestNeighbor(true));
230 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetUV(
231 gfx::PointF(0.25f
, 0.25f
), gfx::PointF(0.75f
, 0.75f
)));
232 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetVertexOpacity(
233 0.5f
, 0.5f
, 0.5f
, 0.5f
));
234 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetPremultipliedAlpha(false));
235 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetBlendBackgroundColor(true));
238 TEST_F(TextureLayerTest
, RateLimiter
) {
239 FakeTextureLayerClient client
;
240 scoped_refptr
<TextureLayer
> test_layer
=
241 TextureLayer::CreateForMailbox(layer_settings_
, &client
);
242 test_layer
->SetIsDrawable(true);
243 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
244 layer_tree_host_
->SetRootLayer(test_layer
);
246 // Don't rate limit until we invalidate.
247 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
248 test_layer
->SetRateLimitContext(true);
249 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
251 // Do rate limit after we invalidate.
252 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
253 test_layer
->SetNeedsDisplay();
254 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
256 // Stop rate limiter when we don't want it any more.
257 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
258 test_layer
->SetRateLimitContext(false);
259 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
261 // Or we clear the client.
262 test_layer
->SetRateLimitContext(true);
263 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
264 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
265 test_layer
->ClearClient();
266 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
268 // Reset to a layer with a client, that started the rate limiter.
269 test_layer
= TextureLayer::CreateForMailbox(layer_settings_
, &client
);
270 test_layer
->SetIsDrawable(true);
271 test_layer
->SetRateLimitContext(true);
272 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
273 layer_tree_host_
->SetRootLayer(test_layer
);
274 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
275 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
276 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
277 test_layer
->SetNeedsDisplay();
278 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
280 // Stop rate limiter when we're removed from the tree.
281 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
282 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(1);
283 layer_tree_host_
->SetRootLayer(nullptr);
284 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
287 class TestMailboxHolder
: public TextureLayer::TextureMailboxHolder
{
289 using TextureLayer::TextureMailboxHolder::Create
;
292 ~TestMailboxHolder() override
{}
295 class TextureLayerWithMailboxTest
: public TextureLayerTest
{
297 void TearDown() override
{
298 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
299 EXPECT_CALL(test_data_
.mock_callback_
,
300 Release(test_data_
.mailbox_name1_
,
301 test_data_
.sync_point1_
,
303 TextureLayerTest::TearDown();
307 TEST_F(TextureLayerWithMailboxTest
, ReplaceMailboxOnMainThreadBeforeCommit
) {
308 scoped_refptr
<TextureLayer
> test_layer
=
309 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
310 ASSERT_TRUE(test_layer
.get());
312 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
313 layer_tree_host_
->SetRootLayer(test_layer
);
314 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
316 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
317 test_layer
->SetTextureMailbox(
318 test_data_
.mailbox1_
,
319 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
320 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
322 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
323 EXPECT_CALL(test_data_
.mock_callback_
,
324 Release(test_data_
.mailbox_name1_
,
325 test_data_
.sync_point1_
,
328 test_layer
->SetTextureMailbox(
329 test_data_
.mailbox2_
,
330 SingleReleaseCallback::Create(test_data_
.release_mailbox2_
));
331 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
332 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
334 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
335 EXPECT_CALL(test_data_
.mock_callback_
,
336 Release(test_data_
.mailbox_name2_
,
337 test_data_
.sync_point2_
,
340 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
341 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
342 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
344 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
345 test_layer
->SetTextureMailbox(
346 test_data_
.mailbox3_
,
347 SingleReleaseCallback::Create(test_data_
.release_mailbox3_
));
348 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
349 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
351 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
352 EXPECT_CALL(test_data_
.mock_callback_
,
353 Release2(test_data_
.shared_bitmap_
.get(), 0, false)).Times(1);
354 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
355 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
356 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
359 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
360 test_layer
->SetTextureMailbox(
361 test_data_
.mailbox1_
,
362 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
365 TEST_F(TextureLayerTest
, SetTextureMailboxWithoutReleaseCallback
) {
366 scoped_refptr
<TextureLayer
> test_layer
=
367 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
368 ASSERT_TRUE(test_layer
.get());
370 // These use the same gpu::Mailbox, but different sync points.
371 TextureMailbox
mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D
, 1);
372 TextureMailbox
mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D
, 2);
374 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
375 layer_tree_host_
->SetRootLayer(test_layer
);
376 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
378 // Set the mailbox the first time. It should cause a commit.
379 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
380 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox1
);
381 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
383 // Set the mailbox again with a new sync point, as the backing texture has
384 // been updated. It should cause a new commit.
385 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
386 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox2
);
387 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
390 class TextureLayerMailboxHolderTest
: public TextureLayerTest
{
392 TextureLayerMailboxHolderTest()
393 : main_thread_("MAIN") {
394 main_thread_
.Start();
395 main_thread_
.message_loop()->task_runner()->PostTask(
396 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain
,
397 base::Unretained(this)));
401 void Wait(const base::Thread
& thread
) {
402 bool manual_reset
= false;
403 bool initially_signaled
= false;
404 base::WaitableEvent
event(manual_reset
, initially_signaled
);
405 thread
.message_loop()->task_runner()->PostTask(
407 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
411 void CreateMainRef() {
412 main_ref_
= TestMailboxHolder::Create(
413 test_data_
.mailbox1_
,
414 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
)).Pass();
417 void ReleaseMainRef() { main_ref_
= nullptr; }
419 void CreateImplRef(scoped_ptr
<SingleReleaseCallbackImpl
>* impl_ref
) {
420 *impl_ref
= main_ref_
->holder()->GetCallbackForImplThread();
423 void CapturePostTasksAndWait(base::WaitableEvent
* begin_capture
,
424 base::WaitableEvent
* wait_for_capture
,
425 base::WaitableEvent
* stop_capture
) {
426 begin_capture
->Wait();
427 BlockingTaskRunner::CapturePostTasks
capture(
428 main_thread_task_runner_
.get());
429 wait_for_capture
->Signal();
430 stop_capture
->Wait();
434 void InitializeOnMain() {
435 main_thread_task_runner_
=
436 BlockingTaskRunner::Create(main_thread_
.task_runner());
439 scoped_ptr
<TestMailboxHolder::MainThreadReference
>
441 base::Thread main_thread_
;
442 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
445 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_BothReleaseThenMain
) {
446 scoped_refptr
<TextureLayer
> test_layer
=
447 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
448 ASSERT_TRUE(test_layer
.get());
450 main_thread_
.message_loop()->task_runner()->PostTask(
451 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
452 base::Unretained(this)));
456 // The texture layer is attached to compositor1, and passes a reference to its
458 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
459 main_thread_
.message_loop()->task_runner()->PostTask(
460 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
461 base::Unretained(this), &compositor1
));
463 // Then the texture layer is removed and attached to compositor2, and passes a
464 // reference to its impl tree.
465 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
466 main_thread_
.message_loop()->task_runner()->PostTask(
467 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
468 base::Unretained(this), &compositor2
));
471 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
473 // The compositors both destroy their impl trees before the main thread layer
475 compositor1
->Run(100, false, main_thread_task_runner_
.get());
476 compositor2
->Run(200, false, main_thread_task_runner_
.get());
480 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
481 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
483 // The main thread ref is the last one, so the mailbox is released back to the
484 // embedder, with the last sync point provided by the impl trees.
485 EXPECT_CALL(test_data_
.mock_callback_
,
486 Release(test_data_
.mailbox_name1_
, 200, false)).Times(1);
488 main_thread_
.message_loop()->task_runner()->PostTask(
489 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
490 base::Unretained(this)));
492 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
495 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleaseBetween
) {
496 scoped_refptr
<TextureLayer
> test_layer
=
497 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
498 ASSERT_TRUE(test_layer
.get());
500 main_thread_
.message_loop()->task_runner()->PostTask(
501 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
502 base::Unretained(this)));
506 // The texture layer is attached to compositor1, and passes a reference to its
508 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
509 main_thread_
.message_loop()->task_runner()->PostTask(
510 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
511 base::Unretained(this), &compositor1
));
513 // Then the texture layer is removed and attached to compositor2, and passes a
514 // reference to its impl tree.
515 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
516 main_thread_
.message_loop()->task_runner()->PostTask(
517 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
518 base::Unretained(this), &compositor2
));
521 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
523 // One compositor destroys their impl tree.
524 compositor1
->Run(100, false, main_thread_task_runner_
.get());
526 // Then the main thread reference is destroyed.
527 main_thread_
.message_loop()->task_runner()->PostTask(
528 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
529 base::Unretained(this)));
533 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
534 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
536 // The second impl reference is destroyed last, causing the mailbox to be
537 // released back to the embedder with the last sync point from the impl tree.
538 EXPECT_CALL(test_data_
.mock_callback_
,
539 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
541 compositor2
->Run(200, true, main_thread_task_runner_
.get());
543 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
546 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleasedFirst
) {
547 scoped_refptr
<TextureLayer
> test_layer
=
548 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
549 ASSERT_TRUE(test_layer
.get());
551 main_thread_
.message_loop()->task_runner()->PostTask(
552 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
553 base::Unretained(this)));
557 // The texture layer is attached to compositor1, and passes a reference to its
559 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
560 main_thread_
.message_loop()->task_runner()->PostTask(
561 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
562 base::Unretained(this), &compositor1
));
564 // Then the texture layer is removed and attached to compositor2, and passes a
565 // reference to its impl tree.
566 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
567 main_thread_
.message_loop()->task_runner()->PostTask(
568 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
569 base::Unretained(this), &compositor2
));
572 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
574 // The main thread reference is destroyed first.
575 main_thread_
.message_loop()->task_runner()->PostTask(
576 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
577 base::Unretained(this)));
579 // One compositor destroys their impl tree.
580 compositor2
->Run(200, false, main_thread_task_runner_
.get());
584 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
585 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
587 // The second impl reference is destroyed last, causing the mailbox to be
588 // released back to the embedder with the last sync point from the impl tree.
589 EXPECT_CALL(test_data_
.mock_callback_
,
590 Release(test_data_
.mailbox_name1_
, 100, true)).Times(1);
592 compositor1
->Run(100, true, main_thread_task_runner_
.get());
594 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
597 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_SecondImplRefShortcut
) {
598 scoped_refptr
<TextureLayer
> test_layer
=
599 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
600 ASSERT_TRUE(test_layer
.get());
602 main_thread_
.message_loop()->task_runner()->PostTask(
603 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
604 base::Unretained(this)));
608 // The texture layer is attached to compositor1, and passes a reference to its
610 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
611 main_thread_
.message_loop()->task_runner()->PostTask(
612 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
613 base::Unretained(this), &compositor1
));
615 // Then the texture layer is removed and attached to compositor2, and passes a
616 // reference to its impl tree.
617 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
618 main_thread_
.message_loop()->task_runner()->PostTask(
619 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
620 base::Unretained(this), &compositor2
));
623 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
625 // The main thread reference is destroyed first.
626 main_thread_
.message_loop()->task_runner()->PostTask(
627 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
628 base::Unretained(this)));
630 EXPECT_CALL(test_data_
.mock_callback_
,
631 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
633 bool manual_reset
= false;
634 bool initially_signaled
= false;
635 base::WaitableEvent
begin_capture(manual_reset
, initially_signaled
);
636 base::WaitableEvent
wait_for_capture(manual_reset
, initially_signaled
);
637 base::WaitableEvent
stop_capture(manual_reset
, initially_signaled
);
639 // Post a task to start capturing tasks on the main thread. This will block
640 // the main thread until we signal the |stop_capture| event.
641 main_thread_
.message_loop()->task_runner()->PostTask(
643 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait
,
644 base::Unretained(this), &begin_capture
, &wait_for_capture
,
647 // Before the main thread capturing starts, one compositor destroys their
648 // impl reference. Since capturing did not start, this gets post-tasked to
650 compositor1
->Run(100, false, main_thread_task_runner_
.get());
652 // Start capturing on the main thread.
653 begin_capture
.Signal();
654 wait_for_capture
.Wait();
656 // Meanwhile, the second compositor released its impl reference, but this task
657 // gets shortcutted directly to the main thread. This means the reference is
658 // released before compositor1, whose reference will be released later when
659 // the post-task is serviced. But since it was destroyed _on the impl thread_
660 // last, its sync point values should be used.
661 compositor2
->Run(200, true, main_thread_task_runner_
.get());
663 stop_capture
.Signal();
666 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
669 class TextureLayerImplWithMailboxThreadedCallback
: public LayerTreeTest
{
671 TextureLayerImplWithMailboxThreadedCallback()
672 : callback_count_(0),
675 // Make sure callback is received on main and doesn't block the impl thread.
676 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
677 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
678 EXPECT_FALSE(lost_resource
);
682 void SetMailbox(char mailbox_char
) {
683 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
684 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
686 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback
,
687 base::Unretained(this)));
688 layer_
->SetTextureMailbox(
689 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
693 void BeginTest() override
{
694 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
696 gfx::Size
bounds(100, 100);
697 root_
= Layer::Create(layer_settings());
698 root_
->SetBounds(bounds
);
700 layer_
= TextureLayer::CreateForMailbox(layer_settings(), nullptr);
701 layer_
->SetIsDrawable(true);
702 layer_
->SetBounds(bounds
);
704 root_
->AddChild(layer_
);
705 layer_tree_host()->SetRootLayer(root_
);
706 layer_tree_host()->SetViewportSize(bounds
);
708 EXPECT_EQ(0, callback_count_
);
710 // Case #1: change mailbox before the commit. The old mailbox should be
711 // released immediately.
713 EXPECT_EQ(1, callback_count_
);
714 PostSetNeedsCommitToMainThread();
717 void DidCommit() override
{
719 switch (commit_count_
) {
721 // Case #2: change mailbox after the commit (and draw), where the
722 // layer draws. The old mailbox should be released during the next
725 EXPECT_EQ(1, callback_count_
);
728 EXPECT_EQ(2, callback_count_
);
729 // Case #3: change mailbox when the layer doesn't draw. The old
730 // mailbox should be released during the next commit.
731 layer_
->SetBounds(gfx::Size());
735 EXPECT_EQ(3, callback_count_
);
736 // Case #4: release mailbox that was committed but never drawn. The
737 // old mailbox should be released during the next commit.
738 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
741 // With impl painting, the texture mailbox will still be on the impl
742 // thread when the commit finishes, because the layer is not drawble
743 // when it has no texture mailbox, and thus does not block the commit
744 // on activation. So, we wait for activation.
745 // TODO(danakj): fix this. crbug.com/277953
746 layer_tree_host()->SetNeedsCommit();
749 EXPECT_EQ(4, callback_count_
);
750 // Restore a mailbox for the next step.
754 // Case #5: remove layer from tree. Callback should *not* be called, the
755 // mailbox is returned to the main thread.
756 EXPECT_EQ(4, callback_count_
);
757 layer_
->RemoveFromParent();
760 // With impl painting, the texture mailbox will still be on the impl
761 // thread when the commit finishes, because the layer is not around to
762 // block the commit on activation anymore. So, we wait for activation.
763 // TODO(danakj): fix this. crbug.com/277953
764 layer_tree_host()->SetNeedsCommit();
767 EXPECT_EQ(4, callback_count_
);
768 // Resetting the mailbox will call the callback now.
769 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
770 EXPECT_EQ(5, callback_count_
);
779 void AfterTest() override
{}
782 base::ThreadChecker main_thread_
;
785 scoped_refptr
<Layer
> root_
;
786 scoped_refptr
<TextureLayer
> layer_
;
789 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
790 TextureLayerImplWithMailboxThreadedCallback
);
793 class TextureLayerMailboxIsActivatedDuringCommit
: public LayerTreeTest
{
795 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
797 static void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {}
799 void SetMailbox(char mailbox_char
) {
800 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
802 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback
));
803 layer_
->SetTextureMailbox(
804 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
808 void BeginTest() override
{
809 gfx::Size
bounds(100, 100);
810 root_
= Layer::Create(layer_settings());
811 root_
->SetBounds(bounds
);
813 layer_
= TextureLayer::CreateForMailbox(layer_settings(), nullptr);
814 layer_
->SetIsDrawable(true);
815 layer_
->SetBounds(bounds
);
817 root_
->AddChild(layer_
);
818 layer_tree_host()->SetRootLayer(root_
);
819 layer_tree_host()->SetViewportSize(bounds
);
822 PostSetNeedsCommitToMainThread();
825 void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
829 void DidCommit() override
{
830 switch (layer_tree_host()->source_frame_number()) {
832 // The first mailbox has been activated. Set a new mailbox, and
833 // expect the next commit to finish *after* it is activated.
837 // The second mailbox has been activated. Remove the layer from
838 // the tree to cause another commit/activation. The commit should
839 // finish *after* the layer is removed from the active tree.
840 layer_
->RemoveFromParent();
848 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
849 switch (host_impl
->active_tree()->source_frame_number()) {
851 // The activate for the 1st mailbox should have happened before now.
852 EXPECT_EQ(1, activate_count_
);
856 // The activate for the 2nd mailbox should have happened before now.
857 EXPECT_EQ(2, activate_count_
);
861 // The activate to remove the layer should have happened before now.
862 EXPECT_EQ(3, activate_count_
);
872 void AfterTest() override
{}
875 scoped_refptr
<Layer
> root_
;
876 scoped_refptr
<TextureLayer
> layer_
;
879 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
880 TextureLayerMailboxIsActivatedDuringCommit
);
882 class TextureLayerImplWithMailboxTest
: public TextureLayerTest
{
884 TextureLayerImplWithMailboxTest()
886 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)) {}
888 void SetUp() override
{
889 TextureLayerTest::SetUp();
891 MockLayerTreeHost::Create(&fake_client_
, &task_graph_runner_
);
892 EXPECT_TRUE(host_impl_
.InitializeRenderer(FakeOutputSurface::Create3d()));
895 bool WillDraw(TextureLayerImpl
* layer
, DrawMode mode
) {
896 bool will_draw
= layer
->WillDraw(
897 mode
, host_impl_
.active_tree()->resource_provider());
899 layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
903 FakeLayerTreeHostClient fake_client_
;
906 // Test conditions for results of TextureLayerImpl::WillDraw under
907 // different configurations of different mailbox, texture_id, and draw_mode.
908 TEST_F(TextureLayerImplWithMailboxTest
, TestWillDraw
) {
910 test_data_
.mock_callback_
,
911 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
913 EXPECT_CALL(test_data_
.mock_callback_
,
914 ReleaseImpl2(test_data_
.shared_bitmap_
.get(), 0, false, _
))
918 scoped_ptr
<TextureLayerImpl
> impl_layer
=
919 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
920 impl_layer
->SetTextureMailbox(
921 test_data_
.mailbox1_
,
922 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
923 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
927 scoped_ptr
<TextureLayerImpl
> impl_layer
=
928 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
929 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
930 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
934 // Software resource.
935 scoped_ptr
<TextureLayerImpl
> impl_layer
=
936 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
937 impl_layer
->SetTextureMailbox(
938 test_data_
.mailbox3_
,
939 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
940 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
945 scoped_ptr
<TextureLayerImpl
> impl_layer
=
946 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
947 impl_layer
->SetTextureMailbox(
948 test_data_
.mailbox1_
,
949 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
950 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
954 scoped_ptr
<TextureLayerImpl
> impl_layer
=
955 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
956 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
957 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
961 // Software resource.
962 scoped_ptr
<TextureLayerImpl
> impl_layer
=
963 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
964 impl_layer
->SetTextureMailbox(
965 test_data_
.mailbox3_
,
966 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
967 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
970 // Resourceless software mode.
972 scoped_ptr
<TextureLayerImpl
> impl_layer
=
973 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
974 impl_layer
->SetTextureMailbox(
975 test_data_
.mailbox1_
,
976 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
977 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_RESOURCELESS_SOFTWARE
));
981 TEST_F(TextureLayerImplWithMailboxTest
, TestImplLayerCallbacks
) {
982 host_impl_
.CreatePendingTree();
983 scoped_ptr
<TextureLayerImpl
> pending_layer
;
984 pending_layer
= TextureLayerImpl::Create(host_impl_
.pending_tree(), 1);
985 ASSERT_TRUE(pending_layer
);
987 scoped_ptr
<LayerImpl
> active_layer(
988 pending_layer
->CreateLayerImpl(host_impl_
.active_tree()));
989 ASSERT_TRUE(active_layer
);
991 pending_layer
->SetTextureMailbox(
992 test_data_
.mailbox1_
,
993 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
995 // Test multiple commits without an activation.
997 test_data_
.mock_callback_
,
998 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1000 pending_layer
->SetTextureMailbox(
1001 test_data_
.mailbox2_
,
1002 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox2_impl_
));
1003 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1005 // Test callback after activation.
1006 pending_layer
->PushPropertiesTo(active_layer
.get());
1007 active_layer
->DidBecomeActive();
1009 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1010 pending_layer
->SetTextureMailbox(
1011 test_data_
.mailbox1_
,
1012 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1013 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1015 EXPECT_CALL(test_data_
.mock_callback_
,
1016 ReleaseImpl(test_data_
.mailbox_name2_
, _
, false, _
)).Times(1);
1017 pending_layer
->PushPropertiesTo(active_layer
.get());
1018 active_layer
->DidBecomeActive();
1019 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1021 // Test resetting the mailbox.
1022 EXPECT_CALL(test_data_
.mock_callback_
,
1023 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1024 pending_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1025 pending_layer
->PushPropertiesTo(active_layer
.get());
1026 active_layer
->DidBecomeActive();
1027 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1031 test_data_
.mock_callback_
,
1032 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1034 pending_layer
->SetTextureMailbox(
1035 test_data_
.mailbox1_
,
1036 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1039 TEST_F(TextureLayerImplWithMailboxTest
,
1040 TestDestructorCallbackOnCreatedResource
) {
1041 scoped_ptr
<TextureLayerImpl
> impl_layer
;
1042 impl_layer
= TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1043 ASSERT_TRUE(impl_layer
);
1045 EXPECT_CALL(test_data_
.mock_callback_
,
1046 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1047 impl_layer
->SetTextureMailbox(
1048 test_data_
.mailbox1_
,
1049 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1050 impl_layer
->DidBecomeActive();
1051 EXPECT_TRUE(impl_layer
->WillDraw(
1052 DRAW_MODE_HARDWARE
, host_impl_
.active_tree()->resource_provider()));
1053 impl_layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
1054 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1057 TEST_F(TextureLayerImplWithMailboxTest
, TestCallbackOnInUseResource
) {
1058 ResourceProvider
* provider
= host_impl_
.active_tree()->resource_provider();
1059 ResourceId id
= provider
->CreateResourceFromTextureMailbox(
1060 test_data_
.mailbox1_
,
1061 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1062 provider
->AllocateForTesting(id
);
1064 // Transfer some resources to the parent.
1065 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1066 resource_ids_to_transfer
.push_back(id
);
1067 TransferableResourceArray list
;
1068 provider
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1069 EXPECT_TRUE(provider
->InUseByConsumer(id
));
1070 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1071 provider
->DeleteResource(id
);
1072 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1073 EXPECT_CALL(test_data_
.mock_callback_
,
1074 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1075 ReturnedResourceArray returned
;
1076 TransferableResource::ReturnResources(list
, &returned
);
1077 provider
->ReceiveReturnsFromParent(returned
);
1080 // Checks that TextureLayer::Update does not cause an extra commit when setting
1081 // the texture mailbox.
1082 class TextureLayerNoExtraCommitForMailboxTest
1083 : public LayerTreeTest
,
1084 public TextureLayerClient
{
1086 // TextureLayerClient implementation.
1087 bool PrepareTextureMailbox(
1088 TextureMailbox
* texture_mailbox
,
1089 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1090 bool use_shared_memory
) override
{
1091 if (layer_tree_host()->source_frame_number() == 1) {
1092 // Once this has been committed, the mailbox will be released.
1093 *texture_mailbox
= TextureMailbox();
1097 *texture_mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1098 *release_callback
= SingleReleaseCallback::Create(
1099 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased
,
1100 base::Unretained(this)));
1104 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1105 // Source frame number during callback is the same as the source frame
1106 // on which it was released.
1107 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1111 void SetupTree() override
{
1112 scoped_refptr
<Layer
> root
= Layer::Create(layer_settings());
1113 root
->SetBounds(gfx::Size(10, 10));
1114 root
->SetIsDrawable(true);
1116 texture_layer_
= TextureLayer::CreateForMailbox(layer_settings(), this);
1117 texture_layer_
->SetBounds(gfx::Size(10, 10));
1118 texture_layer_
->SetIsDrawable(true);
1119 root
->AddChild(texture_layer_
);
1121 layer_tree_host()->SetRootLayer(root
);
1122 LayerTreeTest::SetupTree();
1125 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1127 void DidCommitAndDrawFrame() override
{
1128 switch (layer_tree_host()->source_frame_number()) {
1130 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1131 // Invalidate the texture layer to clear the mailbox before
1133 texture_layer_
->SetNeedsDisplay();
1143 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1144 ASSERT_TRUE(result
);
1145 DelegatedFrameData
* delegated_frame_data
=
1146 output_surface()->last_sent_frame().delegated_frame_data
.get();
1147 if (!delegated_frame_data
)
1150 // Return all resources immediately.
1151 TransferableResourceArray resources_to_return
=
1152 output_surface()->resources_held_by_parent();
1154 CompositorFrameAck ack
;
1155 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1156 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1157 host_impl
->ReclaimResources(&ack
);
1160 void AfterTest() override
{}
1163 scoped_refptr
<TextureLayer
> texture_layer_
;
1166 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest
);
1168 // Checks that changing a mailbox in the client for a TextureLayer that's
1169 // invisible correctly works and uses the new mailbox as soon as the layer
1170 // becomes visible (and returns the old one).
1171 class TextureLayerChangeInvisibleMailboxTest
1172 : public LayerTreeTest
,
1173 public TextureLayerClient
{
1175 TextureLayerChangeInvisibleMailboxTest()
1176 : mailbox_changed_(true),
1177 mailbox_returned_(0),
1180 mailbox_
= MakeMailbox('1');
1183 // TextureLayerClient implementation.
1184 bool PrepareTextureMailbox(
1185 TextureMailbox
* mailbox
,
1186 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1187 bool use_shared_memory
) override
{
1189 if (!mailbox_changed_
)
1191 *mailbox
= mailbox_
;
1192 *release_callback
= SingleReleaseCallback::Create(
1193 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased
,
1194 base::Unretained(this)));
1198 TextureMailbox
MakeMailbox(char name
) {
1199 return TextureMailbox(MailboxFromChar(name
), GL_TEXTURE_2D
, 0);
1202 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1203 ++mailbox_returned_
;
1206 void SetupTree() override
{
1207 scoped_refptr
<Layer
> root
= Layer::Create(layer_settings());
1208 root
->SetBounds(gfx::Size(10, 10));
1209 root
->SetIsDrawable(true);
1211 solid_layer_
= SolidColorLayer::Create(layer_settings());
1212 solid_layer_
->SetBounds(gfx::Size(10, 10));
1213 solid_layer_
->SetIsDrawable(true);
1214 solid_layer_
->SetBackgroundColor(SK_ColorWHITE
);
1215 root
->AddChild(solid_layer_
);
1217 parent_layer_
= Layer::Create(layer_settings());
1218 parent_layer_
->SetBounds(gfx::Size(10, 10));
1219 parent_layer_
->SetIsDrawable(true);
1220 root
->AddChild(parent_layer_
);
1222 texture_layer_
= TextureLayer::CreateForMailbox(layer_settings(), this);
1223 texture_layer_
->SetBounds(gfx::Size(10, 10));
1224 texture_layer_
->SetIsDrawable(true);
1225 parent_layer_
->AddChild(texture_layer_
);
1227 layer_tree_host()->SetRootLayer(root
);
1228 LayerTreeTest::SetupTree();
1231 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1233 void DidCommitAndDrawFrame() override
{
1235 switch (commit_count_
) {
1237 // We should have updated the layer, committing the texture.
1238 EXPECT_EQ(1, prepare_called_
);
1239 // Make layer invisible.
1240 parent_layer_
->SetOpacity(0.f
);
1243 // Layer shouldn't have been updated.
1244 EXPECT_EQ(1, prepare_called_
);
1245 // Change the texture.
1246 mailbox_
= MakeMailbox('2');
1247 mailbox_changed_
= true;
1248 texture_layer_
->SetNeedsDisplay();
1249 // Force a change to make sure we draw a frame.
1250 solid_layer_
->SetBackgroundColor(SK_ColorGRAY
);
1253 // Layer shouldn't have been updated.
1254 EXPECT_EQ(1, prepare_called_
);
1255 // So the old mailbox isn't returned yet.
1256 EXPECT_EQ(0, mailbox_returned_
);
1257 // Make layer visible again.
1258 parent_layer_
->SetOpacity(1.f
);
1261 // Layer should have been updated.
1262 EXPECT_EQ(2, prepare_called_
);
1263 // So the old mailbox should have been returned already.
1264 EXPECT_EQ(1, mailbox_returned_
);
1265 texture_layer_
->ClearClient();
1268 EXPECT_EQ(2, mailbox_returned_
);
1277 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1278 ASSERT_TRUE(result
);
1279 DelegatedFrameData
* delegated_frame_data
=
1280 output_surface()->last_sent_frame().delegated_frame_data
.get();
1281 if (!delegated_frame_data
)
1284 // Return all resources immediately.
1285 TransferableResourceArray resources_to_return
=
1286 output_surface()->resources_held_by_parent();
1288 CompositorFrameAck ack
;
1289 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1290 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1291 host_impl
->ReclaimResources(&ack
);
1294 void AfterTest() override
{}
1297 scoped_refptr
<SolidColorLayer
> solid_layer_
;
1298 scoped_refptr
<Layer
> parent_layer_
;
1299 scoped_refptr
<TextureLayer
> texture_layer_
;
1301 // Used on the main thread.
1302 bool mailbox_changed_
;
1303 TextureMailbox mailbox_
;
1304 int mailbox_returned_
;
1305 int prepare_called_
;
1309 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest
);
1311 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1312 // the mailbox back to TextureLayerClient.
1313 class TextureLayerReleaseResourcesBase
1314 : public LayerTreeTest
,
1315 public TextureLayerClient
{
1317 // TextureLayerClient implementation.
1318 bool PrepareTextureMailbox(
1319 TextureMailbox
* mailbox
,
1320 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1321 bool use_shared_memory
) override
{
1322 *mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1323 *release_callback
= SingleReleaseCallback::Create(
1324 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased
,
1325 base::Unretained(this)));
1329 void MailboxReleased(unsigned sync_point
, bool lost_resource
) {
1330 mailbox_released_
= true;
1333 void SetupTree() override
{
1334 LayerTreeTest::SetupTree();
1336 scoped_refptr
<TextureLayer
> texture_layer
=
1337 TextureLayer::CreateForMailbox(layer_settings(), this);
1338 texture_layer
->SetBounds(gfx::Size(10, 10));
1339 texture_layer
->SetIsDrawable(true);
1341 layer_tree_host()->root_layer()->AddChild(texture_layer
);
1344 void BeginTest() override
{
1345 mailbox_released_
= false;
1346 PostSetNeedsCommitToMainThread();
1349 void DidCommitAndDrawFrame() override
{ EndTest(); }
1351 void AfterTest() override
{ EXPECT_TRUE(mailbox_released_
); }
1354 bool mailbox_released_
;
1357 class TextureLayerReleaseResourcesAfterCommit
1358 : public TextureLayerReleaseResourcesBase
{
1360 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
1361 LayerTreeImpl
* tree
= nullptr;
1362 tree
= host_impl
->sync_tree();
1363 tree
->root_layer()->children()[0]->ReleaseResources();
1367 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit
);
1369 class TextureLayerReleaseResourcesAfterActivate
1370 : public TextureLayerReleaseResourcesBase
{
1372 void DidActivateTreeOnThread(LayerTreeHostImpl
* host_impl
) override
{
1373 host_impl
->active_tree()->root_layer()->children()[0]->ReleaseResources();
1377 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate
);
1379 class TextureLayerWithMailboxMainThreadDeleted
: public LayerTreeTest
{
1381 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1382 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1383 EXPECT_FALSE(lost_resource
);
1388 void SetMailbox(char mailbox_char
) {
1389 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1390 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1392 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback
,
1393 base::Unretained(this)));
1394 layer_
->SetTextureMailbox(
1395 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1399 void SetupTree() override
{
1400 gfx::Size
bounds(100, 100);
1401 root_
= Layer::Create(layer_settings());
1402 root_
->SetBounds(bounds
);
1404 layer_
= TextureLayer::CreateForMailbox(layer_settings(), nullptr);
1405 layer_
->SetIsDrawable(true);
1406 layer_
->SetBounds(bounds
);
1408 root_
->AddChild(layer_
);
1409 layer_tree_host()->SetRootLayer(root_
);
1410 layer_tree_host()->SetViewportSize(bounds
);
1413 void BeginTest() override
{
1414 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1416 callback_count_
= 0;
1418 // Set the mailbox on the main thread.
1420 EXPECT_EQ(0, callback_count_
);
1422 PostSetNeedsCommitToMainThread();
1425 void DidCommitAndDrawFrame() override
{
1426 switch (layer_tree_host()->source_frame_number()) {
1428 // Delete the TextureLayer on the main thread while the mailbox is in
1430 layer_
->RemoveFromParent();
1436 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1439 base::ThreadChecker main_thread_
;
1440 int callback_count_
;
1441 scoped_refptr
<Layer
> root_
;
1442 scoped_refptr
<TextureLayer
> layer_
;
1445 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1446 TextureLayerWithMailboxMainThreadDeleted
);
1448 class TextureLayerWithMailboxImplThreadDeleted
: public LayerTreeTest
{
1450 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1451 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1452 EXPECT_FALSE(lost_resource
);
1457 void SetMailbox(char mailbox_char
) {
1458 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1459 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1461 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback
,
1462 base::Unretained(this)));
1463 layer_
->SetTextureMailbox(
1464 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1468 void SetupTree() override
{
1469 gfx::Size
bounds(100, 100);
1470 root_
= Layer::Create(layer_settings());
1471 root_
->SetBounds(bounds
);
1473 layer_
= TextureLayer::CreateForMailbox(layer_settings(), nullptr);
1474 layer_
->SetIsDrawable(true);
1475 layer_
->SetBounds(bounds
);
1477 root_
->AddChild(layer_
);
1478 layer_tree_host()->SetRootLayer(root_
);
1479 layer_tree_host()->SetViewportSize(bounds
);
1482 void BeginTest() override
{
1483 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1485 callback_count_
= 0;
1487 // Set the mailbox on the main thread.
1489 EXPECT_EQ(0, callback_count_
);
1491 PostSetNeedsCommitToMainThread();
1494 void DidCommitAndDrawFrame() override
{
1495 switch (layer_tree_host()->source_frame_number()) {
1497 // Remove the TextureLayer on the main thread while the mailbox is in
1498 // the impl tree, but don't delete the TextureLayer until after the impl
1499 // tree side is deleted.
1500 layer_
->RemoveFromParent();
1508 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1511 base::ThreadChecker main_thread_
;
1512 int callback_count_
;
1513 scoped_refptr
<Layer
> root_
;
1514 scoped_refptr
<TextureLayer
> layer_
;
1517 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1518 TextureLayerWithMailboxImplThreadDeleted
);