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/lock.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "base/threading/thread.h"
18 #include "base/time/time.h"
19 #include "cc/layers/solid_color_layer.h"
20 #include "cc/layers/texture_layer_client.h"
21 #include "cc/layers/texture_layer_impl.h"
22 #include "cc/output/compositor_frame_ack.h"
23 #include "cc/output/context_provider.h"
24 #include "cc/resources/returned_resource.h"
25 #include "cc/test/fake_impl_proxy.h"
26 #include "cc/test/fake_layer_tree_host_client.h"
27 #include "cc/test/fake_layer_tree_host_impl.h"
28 #include "cc/test/fake_output_surface.h"
29 #include "cc/test/layer_test_common.h"
30 #include "cc/test/layer_tree_test.h"
31 #include "cc/test/test_task_graph_runner.h"
32 #include "cc/test/test_web_graphics_context_3d.h"
33 #include "cc/trees/blocking_task_runner.h"
34 #include "cc/trees/layer_tree_host.h"
35 #include "cc/trees/layer_tree_impl.h"
36 #include "cc/trees/single_thread_proxy.h"
37 #include "gpu/GLES2/gl2extchromium.h"
38 #include "testing/gmock/include/gmock/gmock.h"
39 #include "testing/gtest/include/gtest/gtest.h"
41 using ::testing::Mock
;
43 using ::testing::AtLeast
;
44 using ::testing::AnyNumber
;
45 using ::testing::InvokeWithoutArgs
;
50 gpu::Mailbox
MailboxFromChar(char value
) {
52 memset(mailbox
.name
, value
, sizeof(mailbox
.name
));
56 class MockLayerTreeHost
: public LayerTreeHost
{
58 static scoped_ptr
<MockLayerTreeHost
> Create(
59 FakeLayerTreeHostClient
* client
,
60 TaskGraphRunner
* task_graph_runner
) {
61 LayerTreeHost::InitParams params
;
62 params
.client
= client
;
63 params
.task_graph_runner
= task_graph_runner
;
64 LayerTreeSettings settings
;
65 params
.settings
= &settings
;
66 return make_scoped_ptr(new MockLayerTreeHost(client
, ¶ms
));
69 MOCK_METHOD0(SetNeedsCommit
, void());
70 MOCK_METHOD0(SetNeedsUpdateLayers
, void());
71 MOCK_METHOD0(StartRateLimiter
, void());
72 MOCK_METHOD0(StopRateLimiter
, void());
75 MockLayerTreeHost(FakeLayerTreeHostClient
* client
,
76 LayerTreeHost::InitParams
* params
)
77 : LayerTreeHost(params
) {
78 InitializeSingleThreaded(client
, base::ThreadTaskRunnerHandle::Get(),
83 class FakeTextureLayerClient
: public TextureLayerClient
{
85 FakeTextureLayerClient() : mailbox_changed_(true) {}
87 bool PrepareTextureMailbox(
88 TextureMailbox
* mailbox
,
89 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
90 bool use_shared_memory
) override
{
91 if (!mailbox_changed_
)
95 *release_callback
= release_callback_
.Pass();
96 mailbox_changed_
= false;
100 void set_mailbox(const TextureMailbox
& mailbox
,
101 scoped_ptr
<SingleReleaseCallback
> release_callback
) {
103 release_callback_
= release_callback
.Pass();
104 mailbox_changed_
= true;
108 TextureMailbox mailbox_
;
109 scoped_ptr
<SingleReleaseCallback
> release_callback_
;
110 bool mailbox_changed_
;
111 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient
);
114 class MockMailboxCallback
{
116 MOCK_METHOD3(Release
,
117 void(const gpu::Mailbox
& mailbox
,
119 bool lost_resource
));
120 MOCK_METHOD3(Release2
,
121 void(SharedBitmap
* shared_bitmap
,
123 bool lost_resource
));
124 MOCK_METHOD4(ReleaseImpl
,
125 void(const gpu::Mailbox
& mailbox
,
128 BlockingTaskRunner
* main_thread_task_runner
));
129 MOCK_METHOD4(ReleaseImpl2
,
130 void(SharedBitmap
* shared_bitmap
,
133 BlockingTaskRunner
* main_thread_task_runner
));
136 struct CommonMailboxObjects
{
137 explicit CommonMailboxObjects(SharedBitmapManager
* manager
)
138 : mailbox_name1_(MailboxFromChar('1')),
139 mailbox_name2_(MailboxFromChar('2')),
142 release_mailbox1_
= base::Bind(&MockMailboxCallback::Release
,
143 base::Unretained(&mock_callback_
),
145 release_mailbox2_
= base::Bind(&MockMailboxCallback::Release
,
146 base::Unretained(&mock_callback_
),
148 release_mailbox1_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
149 base::Unretained(&mock_callback_
),
151 release_mailbox2_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
152 base::Unretained(&mock_callback_
),
154 const uint32 arbitrary_target1
= GL_TEXTURE_2D
;
155 const uint32 arbitrary_target2
= GL_TEXTURE_EXTERNAL_OES
;
156 mailbox1_
= TextureMailbox(mailbox_name1_
, arbitrary_target1
, sync_point1_
);
157 mailbox2_
= TextureMailbox(mailbox_name2_
, arbitrary_target2
, sync_point2_
);
158 gfx::Size
size(128, 128);
159 shared_bitmap_
= manager
->AllocateSharedBitmap(size
);
160 DCHECK(shared_bitmap_
);
162 base::Bind(&MockMailboxCallback::Release2
,
163 base::Unretained(&mock_callback_
), shared_bitmap_
.get());
164 release_mailbox3_impl_
=
165 base::Bind(&MockMailboxCallback::ReleaseImpl2
,
166 base::Unretained(&mock_callback_
), shared_bitmap_
.get());
167 mailbox3_
= TextureMailbox(shared_bitmap_
.get(), size
);
170 gpu::Mailbox mailbox_name1_
;
171 gpu::Mailbox mailbox_name2_
;
172 MockMailboxCallback mock_callback_
;
173 ReleaseCallback release_mailbox1_
;
174 ReleaseCallback release_mailbox2_
;
175 ReleaseCallback release_mailbox3_
;
176 ReleaseCallbackImpl release_mailbox1_impl_
;
177 ReleaseCallbackImpl release_mailbox2_impl_
;
178 ReleaseCallbackImpl release_mailbox3_impl_
;
179 TextureMailbox mailbox1_
;
180 TextureMailbox mailbox2_
;
181 TextureMailbox mailbox3_
;
184 scoped_ptr
<SharedBitmap
> shared_bitmap_
;
187 class TextureLayerTest
: public testing::Test
{
191 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)),
192 host_impl_(&proxy_
, &shared_bitmap_manager_
, &task_graph_runner_
),
193 test_data_(&shared_bitmap_manager_
) {}
196 void SetUp() override
{
198 MockLayerTreeHost::Create(&fake_client_
, &task_graph_runner_
);
199 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
200 layer_tree_host_
->SetViewportSize(gfx::Size(10, 10));
201 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
204 void TearDown() override
{
205 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
206 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
208 layer_tree_host_
->SetRootLayer(nullptr);
209 layer_tree_host_
= nullptr;
212 scoped_ptr
<MockLayerTreeHost
> layer_tree_host_
;
213 FakeImplProxy proxy_
;
214 FakeLayerTreeHostClient fake_client_
;
215 TestSharedBitmapManager shared_bitmap_manager_
;
216 TestTaskGraphRunner task_graph_runner_
;
217 FakeLayerTreeHostImpl host_impl_
;
218 CommonMailboxObjects test_data_
;
219 LayerSettings layer_settings_
;
222 TEST_F(TextureLayerTest
, CheckPropertyChangeCausesCorrectBehavior
) {
223 scoped_refptr
<TextureLayer
> test_layer
=
224 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
225 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_
->SetRootLayer(test_layer
));
227 // Test properties that should call SetNeedsCommit. All properties need to
228 // be set to new values in order for SetNeedsCommit to be called.
229 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetFlipped(false));
230 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetNearestNeighbor(true));
231 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetUV(
232 gfx::PointF(0.25f
, 0.25f
), gfx::PointF(0.75f
, 0.75f
)));
233 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetVertexOpacity(
234 0.5f
, 0.5f
, 0.5f
, 0.5f
));
235 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetPremultipliedAlpha(false));
236 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetBlendBackgroundColor(true));
239 TEST_F(TextureLayerTest
, RateLimiter
) {
240 FakeTextureLayerClient client
;
241 scoped_refptr
<TextureLayer
> test_layer
=
242 TextureLayer::CreateForMailbox(layer_settings_
, &client
);
243 test_layer
->SetIsDrawable(true);
244 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
245 layer_tree_host_
->SetRootLayer(test_layer
);
247 // Don't rate limit until we invalidate.
248 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
249 test_layer
->SetRateLimitContext(true);
250 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
252 // Do rate limit after we invalidate.
253 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
254 test_layer
->SetNeedsDisplay();
255 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
257 // Stop rate limiter when we don't want it any more.
258 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
259 test_layer
->SetRateLimitContext(false);
260 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
262 // Or we clear the client.
263 test_layer
->SetRateLimitContext(true);
264 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
265 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
266 test_layer
->ClearClient();
267 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
269 // Reset to a layer with a client, that started the rate limiter.
270 test_layer
= TextureLayer::CreateForMailbox(layer_settings_
, &client
);
271 test_layer
->SetIsDrawable(true);
272 test_layer
->SetRateLimitContext(true);
273 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
274 layer_tree_host_
->SetRootLayer(test_layer
);
275 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
276 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
277 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
278 test_layer
->SetNeedsDisplay();
279 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
281 // Stop rate limiter when we're removed from the tree.
282 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
283 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(1);
284 layer_tree_host_
->SetRootLayer(nullptr);
285 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
288 class TestMailboxHolder
: public TextureLayer::TextureMailboxHolder
{
290 using TextureLayer::TextureMailboxHolder::Create
;
293 ~TestMailboxHolder() override
{}
296 class TextureLayerWithMailboxTest
: public TextureLayerTest
{
298 void TearDown() override
{
299 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
300 EXPECT_CALL(test_data_
.mock_callback_
,
301 Release(test_data_
.mailbox_name1_
,
302 test_data_
.sync_point1_
,
304 TextureLayerTest::TearDown();
308 TEST_F(TextureLayerWithMailboxTest
, ReplaceMailboxOnMainThreadBeforeCommit
) {
309 scoped_refptr
<TextureLayer
> test_layer
=
310 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
311 ASSERT_TRUE(test_layer
.get());
313 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
314 layer_tree_host_
->SetRootLayer(test_layer
);
315 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
317 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
318 test_layer
->SetTextureMailbox(
319 test_data_
.mailbox1_
,
320 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
321 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
323 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
324 EXPECT_CALL(test_data_
.mock_callback_
,
325 Release(test_data_
.mailbox_name1_
,
326 test_data_
.sync_point1_
,
329 test_layer
->SetTextureMailbox(
330 test_data_
.mailbox2_
,
331 SingleReleaseCallback::Create(test_data_
.release_mailbox2_
));
332 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
333 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
335 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
336 EXPECT_CALL(test_data_
.mock_callback_
,
337 Release(test_data_
.mailbox_name2_
,
338 test_data_
.sync_point2_
,
341 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
342 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
343 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
345 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
346 test_layer
->SetTextureMailbox(
347 test_data_
.mailbox3_
,
348 SingleReleaseCallback::Create(test_data_
.release_mailbox3_
));
349 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
350 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
352 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
353 EXPECT_CALL(test_data_
.mock_callback_
,
354 Release2(test_data_
.shared_bitmap_
.get(), 0, false)).Times(1);
355 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
356 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
357 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
360 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
361 test_layer
->SetTextureMailbox(
362 test_data_
.mailbox1_
,
363 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
366 TEST_F(TextureLayerTest
, SetTextureMailboxWithoutReleaseCallback
) {
367 scoped_refptr
<TextureLayer
> test_layer
=
368 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
369 ASSERT_TRUE(test_layer
.get());
371 // These use the same gpu::Mailbox, but different sync points.
372 TextureMailbox
mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D
, 1);
373 TextureMailbox
mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D
, 2);
375 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
376 layer_tree_host_
->SetRootLayer(test_layer
);
377 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
379 // Set the mailbox the first time. It should cause a commit.
380 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
381 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox1
);
382 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
384 // Set the mailbox again with a new sync point, as the backing texture has
385 // been updated. It should cause a new commit.
386 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
387 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox2
);
388 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
391 class TextureLayerMailboxHolderTest
: public TextureLayerTest
{
393 TextureLayerMailboxHolderTest()
394 : main_thread_("MAIN") {
395 main_thread_
.Start();
396 main_thread_
.message_loop()->task_runner()->PostTask(
397 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain
,
398 base::Unretained(this)));
402 void Wait(const base::Thread
& thread
) {
403 bool manual_reset
= false;
404 bool initially_signaled
= false;
405 base::WaitableEvent
event(manual_reset
, initially_signaled
);
406 thread
.message_loop()->task_runner()->PostTask(
408 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
412 void CreateMainRef() {
413 main_ref_
= TestMailboxHolder::Create(
414 test_data_
.mailbox1_
,
415 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
)).Pass();
418 void ReleaseMainRef() { main_ref_
= nullptr; }
420 void CreateImplRef(scoped_ptr
<SingleReleaseCallbackImpl
>* impl_ref
) {
421 *impl_ref
= main_ref_
->holder()->GetCallbackForImplThread();
424 void CapturePostTasksAndWait(base::WaitableEvent
* begin_capture
,
425 base::WaitableEvent
* wait_for_capture
,
426 base::WaitableEvent
* stop_capture
) {
427 begin_capture
->Wait();
428 BlockingTaskRunner::CapturePostTasks
capture(
429 main_thread_task_runner_
.get());
430 wait_for_capture
->Signal();
431 stop_capture
->Wait();
435 void InitializeOnMain() {
436 main_thread_task_runner_
=
437 BlockingTaskRunner::Create(main_thread_
.task_runner());
440 scoped_ptr
<TestMailboxHolder::MainThreadReference
>
442 base::Thread main_thread_
;
443 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
446 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_BothReleaseThenMain
) {
447 scoped_refptr
<TextureLayer
> test_layer
=
448 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
449 ASSERT_TRUE(test_layer
.get());
451 main_thread_
.message_loop()->task_runner()->PostTask(
452 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
453 base::Unretained(this)));
457 // The texture layer is attached to compositor1, and passes a reference to its
459 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
460 main_thread_
.message_loop()->task_runner()->PostTask(
461 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
462 base::Unretained(this), &compositor1
));
464 // Then the texture layer is removed and attached to compositor2, and passes a
465 // reference to its impl tree.
466 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
467 main_thread_
.message_loop()->task_runner()->PostTask(
468 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
469 base::Unretained(this), &compositor2
));
472 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
474 // The compositors both destroy their impl trees before the main thread layer
476 compositor1
->Run(100, false, main_thread_task_runner_
.get());
477 compositor2
->Run(200, false, main_thread_task_runner_
.get());
481 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
482 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
484 // The main thread ref is the last one, so the mailbox is released back to the
485 // embedder, with the last sync point provided by the impl trees.
486 EXPECT_CALL(test_data_
.mock_callback_
,
487 Release(test_data_
.mailbox_name1_
, 200, false)).Times(1);
489 main_thread_
.message_loop()->task_runner()->PostTask(
490 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
491 base::Unretained(this)));
493 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
496 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleaseBetween
) {
497 scoped_refptr
<TextureLayer
> test_layer
=
498 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
499 ASSERT_TRUE(test_layer
.get());
501 main_thread_
.message_loop()->task_runner()->PostTask(
502 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
503 base::Unretained(this)));
507 // The texture layer is attached to compositor1, and passes a reference to its
509 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
510 main_thread_
.message_loop()->task_runner()->PostTask(
511 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
512 base::Unretained(this), &compositor1
));
514 // Then the texture layer is removed and attached to compositor2, and passes a
515 // reference to its impl tree.
516 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
517 main_thread_
.message_loop()->task_runner()->PostTask(
518 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
519 base::Unretained(this), &compositor2
));
522 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
524 // One compositor destroys their impl tree.
525 compositor1
->Run(100, false, main_thread_task_runner_
.get());
527 // Then the main thread reference is destroyed.
528 main_thread_
.message_loop()->task_runner()->PostTask(
529 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
530 base::Unretained(this)));
534 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
535 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
537 // The second impl reference is destroyed last, causing the mailbox to be
538 // released back to the embedder with the last sync point from the impl tree.
539 EXPECT_CALL(test_data_
.mock_callback_
,
540 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
542 compositor2
->Run(200, true, main_thread_task_runner_
.get());
544 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
547 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleasedFirst
) {
548 scoped_refptr
<TextureLayer
> test_layer
=
549 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
550 ASSERT_TRUE(test_layer
.get());
552 main_thread_
.message_loop()->task_runner()->PostTask(
553 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
554 base::Unretained(this)));
558 // The texture layer is attached to compositor1, and passes a reference to its
560 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
561 main_thread_
.message_loop()->task_runner()->PostTask(
562 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
563 base::Unretained(this), &compositor1
));
565 // Then the texture layer is removed and attached to compositor2, and passes a
566 // reference to its impl tree.
567 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
568 main_thread_
.message_loop()->task_runner()->PostTask(
569 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
570 base::Unretained(this), &compositor2
));
573 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
575 // The main thread reference is destroyed first.
576 main_thread_
.message_loop()->task_runner()->PostTask(
577 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
578 base::Unretained(this)));
580 // One compositor destroys their impl tree.
581 compositor2
->Run(200, false, main_thread_task_runner_
.get());
585 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
586 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
588 // The second impl reference is destroyed last, causing the mailbox to be
589 // released back to the embedder with the last sync point from the impl tree.
590 EXPECT_CALL(test_data_
.mock_callback_
,
591 Release(test_data_
.mailbox_name1_
, 100, true)).Times(1);
593 compositor1
->Run(100, true, main_thread_task_runner_
.get());
595 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
598 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_SecondImplRefShortcut
) {
599 scoped_refptr
<TextureLayer
> test_layer
=
600 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
601 ASSERT_TRUE(test_layer
.get());
603 main_thread_
.message_loop()->task_runner()->PostTask(
604 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
605 base::Unretained(this)));
609 // The texture layer is attached to compositor1, and passes a reference to its
611 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
612 main_thread_
.message_loop()->task_runner()->PostTask(
613 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
614 base::Unretained(this), &compositor1
));
616 // Then the texture layer is removed and attached to compositor2, and passes a
617 // reference to its impl tree.
618 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
619 main_thread_
.message_loop()->task_runner()->PostTask(
620 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
621 base::Unretained(this), &compositor2
));
624 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
626 // The main thread reference is destroyed first.
627 main_thread_
.message_loop()->task_runner()->PostTask(
628 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
629 base::Unretained(this)));
631 EXPECT_CALL(test_data_
.mock_callback_
,
632 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
634 bool manual_reset
= false;
635 bool initially_signaled
= false;
636 base::WaitableEvent
begin_capture(manual_reset
, initially_signaled
);
637 base::WaitableEvent
wait_for_capture(manual_reset
, initially_signaled
);
638 base::WaitableEvent
stop_capture(manual_reset
, initially_signaled
);
640 // Post a task to start capturing tasks on the main thread. This will block
641 // the main thread until we signal the |stop_capture| event.
642 main_thread_
.message_loop()->task_runner()->PostTask(
644 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait
,
645 base::Unretained(this), &begin_capture
, &wait_for_capture
,
648 // Before the main thread capturing starts, one compositor destroys their
649 // impl reference. Since capturing did not start, this gets post-tasked to
651 compositor1
->Run(100, false, main_thread_task_runner_
.get());
653 // Start capturing on the main thread.
654 begin_capture
.Signal();
655 wait_for_capture
.Wait();
657 // Meanwhile, the second compositor released its impl reference, but this task
658 // gets shortcutted directly to the main thread. This means the reference is
659 // released before compositor1, whose reference will be released later when
660 // the post-task is serviced. But since it was destroyed _on the impl thread_
661 // last, its sync point values should be used.
662 compositor2
->Run(200, true, main_thread_task_runner_
.get());
664 stop_capture
.Signal();
667 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
670 class TextureLayerImplWithMailboxThreadedCallback
: public LayerTreeTest
{
672 TextureLayerImplWithMailboxThreadedCallback()
673 : callback_count_(0),
676 // Make sure callback is received on main and doesn't block the impl thread.
677 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
678 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
679 EXPECT_FALSE(lost_resource
);
683 void SetMailbox(char mailbox_char
) {
684 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
685 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
687 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback
,
688 base::Unretained(this)));
689 layer_
->SetTextureMailbox(
690 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
694 void BeginTest() override
{
695 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
697 gfx::Size
bounds(100, 100);
698 root_
= Layer::Create(layer_settings());
699 root_
->SetBounds(bounds
);
701 layer_
= TextureLayer::CreateForMailbox(layer_settings(), nullptr);
702 layer_
->SetIsDrawable(true);
703 layer_
->SetBounds(bounds
);
705 root_
->AddChild(layer_
);
706 layer_tree_host()->SetRootLayer(root_
);
707 layer_tree_host()->SetViewportSize(bounds
);
709 EXPECT_EQ(0, callback_count_
);
711 // Case #1: change mailbox before the commit. The old mailbox should be
712 // released immediately.
714 EXPECT_EQ(1, callback_count_
);
715 PostSetNeedsCommitToMainThread();
718 void DidCommit() override
{
720 switch (commit_count_
) {
722 // Case #2: change mailbox after the commit (and draw), where the
723 // layer draws. The old mailbox should be released during the next
726 EXPECT_EQ(1, callback_count_
);
729 EXPECT_EQ(2, callback_count_
);
730 // Case #3: change mailbox when the layer doesn't draw. The old
731 // mailbox should be released during the next commit.
732 layer_
->SetBounds(gfx::Size());
736 EXPECT_EQ(3, callback_count_
);
737 // Case #4: release mailbox that was committed but never drawn. The
738 // old mailbox should be released during the next commit.
739 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
742 // With impl painting, the texture mailbox will still be on the impl
743 // thread when the commit finishes, because the layer is not drawble
744 // when it has no texture mailbox, and thus does not block the commit
745 // on activation. So, we wait for activation.
746 // TODO(danakj): fix this. crbug.com/277953
747 layer_tree_host()->SetNeedsCommit();
750 EXPECT_EQ(4, callback_count_
);
751 // Restore a mailbox for the next step.
755 // Case #5: remove layer from tree. Callback should *not* be called, the
756 // mailbox is returned to the main thread.
757 EXPECT_EQ(4, callback_count_
);
758 layer_
->RemoveFromParent();
761 // With impl painting, the texture mailbox will still be on the impl
762 // thread when the commit finishes, because the layer is not around to
763 // block the commit on activation anymore. So, we wait for activation.
764 // TODO(danakj): fix this. crbug.com/277953
765 layer_tree_host()->SetNeedsCommit();
768 EXPECT_EQ(4, callback_count_
);
769 // Resetting the mailbox will call the callback now.
770 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
771 EXPECT_EQ(5, callback_count_
);
780 void AfterTest() override
{}
783 base::ThreadChecker main_thread_
;
786 scoped_refptr
<Layer
> root_
;
787 scoped_refptr
<TextureLayer
> layer_
;
790 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
791 TextureLayerImplWithMailboxThreadedCallback
);
794 class TextureLayerMailboxIsActivatedDuringCommit
: public LayerTreeTest
{
796 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
798 static void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {}
800 void SetMailbox(char mailbox_char
) {
801 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
803 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback
));
804 layer_
->SetTextureMailbox(
805 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
809 void BeginTest() override
{
810 gfx::Size
bounds(100, 100);
811 root_
= Layer::Create(layer_settings());
812 root_
->SetBounds(bounds
);
814 layer_
= TextureLayer::CreateForMailbox(layer_settings(), nullptr);
815 layer_
->SetIsDrawable(true);
816 layer_
->SetBounds(bounds
);
818 root_
->AddChild(layer_
);
819 layer_tree_host()->SetRootLayer(root_
);
820 layer_tree_host()->SetViewportSize(bounds
);
823 PostSetNeedsCommitToMainThread();
826 void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
827 base::AutoLock
lock(activate_count_lock_
);
831 void DidCommit() override
{
832 // The first frame doesn't cause anything to be returned so it does not
833 // need to wait for activation.
834 if (layer_tree_host()->source_frame_number() > 1) {
835 base::AutoLock
lock(activate_count_lock_
);
836 // The activate happened before commit is done on the main side.
837 EXPECT_EQ(activate_count_
, layer_tree_host()->source_frame_number());
840 switch (layer_tree_host()->source_frame_number()) {
842 // The first mailbox has been activated. Set a new mailbox, and
843 // expect the next commit to finish *after* it is activated.
847 // The second mailbox has been activated. Remove the layer from
848 // the tree to cause another commit/activation. The commit should
849 // finish *after* the layer is removed from the active tree.
850 layer_
->RemoveFromParent();
858 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
859 // The activate didn't happen before commit is done on the impl side (but it
860 // should happen before the main thread is done).
861 EXPECT_EQ(activate_count_
, host_impl
->sync_tree()->source_frame_number());
864 void AfterTest() override
{}
866 base::Lock activate_count_lock_
;
868 scoped_refptr
<Layer
> root_
;
869 scoped_refptr
<TextureLayer
> layer_
;
872 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
873 TextureLayerMailboxIsActivatedDuringCommit
);
875 class TextureLayerImplWithMailboxTest
: public TextureLayerTest
{
877 TextureLayerImplWithMailboxTest()
879 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)) {}
881 void SetUp() override
{
882 TextureLayerTest::SetUp();
884 MockLayerTreeHost::Create(&fake_client_
, &task_graph_runner_
);
885 EXPECT_TRUE(host_impl_
.InitializeRenderer(FakeOutputSurface::Create3d()));
888 bool WillDraw(TextureLayerImpl
* layer
, DrawMode mode
) {
889 bool will_draw
= layer
->WillDraw(
890 mode
, host_impl_
.active_tree()->resource_provider());
892 layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
896 FakeLayerTreeHostClient fake_client_
;
899 // Test conditions for results of TextureLayerImpl::WillDraw under
900 // different configurations of different mailbox, texture_id, and draw_mode.
901 TEST_F(TextureLayerImplWithMailboxTest
, TestWillDraw
) {
903 test_data_
.mock_callback_
,
904 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
906 EXPECT_CALL(test_data_
.mock_callback_
,
907 ReleaseImpl2(test_data_
.shared_bitmap_
.get(), 0, false, _
))
911 scoped_ptr
<TextureLayerImpl
> impl_layer
=
912 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
913 impl_layer
->SetTextureMailbox(
914 test_data_
.mailbox1_
,
915 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
916 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
920 scoped_ptr
<TextureLayerImpl
> impl_layer
=
921 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
922 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
923 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
927 // Software resource.
928 scoped_ptr
<TextureLayerImpl
> impl_layer
=
929 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
930 impl_layer
->SetTextureMailbox(
931 test_data_
.mailbox3_
,
932 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
933 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
938 scoped_ptr
<TextureLayerImpl
> impl_layer
=
939 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
940 impl_layer
->SetTextureMailbox(
941 test_data_
.mailbox1_
,
942 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
943 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
947 scoped_ptr
<TextureLayerImpl
> impl_layer
=
948 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
949 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
950 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
954 // Software resource.
955 scoped_ptr
<TextureLayerImpl
> impl_layer
=
956 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
957 impl_layer
->SetTextureMailbox(
958 test_data_
.mailbox3_
,
959 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
960 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
963 // Resourceless software mode.
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_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_RESOURCELESS_SOFTWARE
));
974 TEST_F(TextureLayerImplWithMailboxTest
, TestImplLayerCallbacks
) {
975 host_impl_
.CreatePendingTree();
976 scoped_ptr
<TextureLayerImpl
> pending_layer
;
977 pending_layer
= TextureLayerImpl::Create(host_impl_
.pending_tree(), 1);
978 ASSERT_TRUE(pending_layer
);
980 scoped_ptr
<LayerImpl
> active_layer(
981 pending_layer
->CreateLayerImpl(host_impl_
.active_tree()));
982 ASSERT_TRUE(active_layer
);
984 pending_layer
->SetTextureMailbox(
985 test_data_
.mailbox1_
,
986 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
988 // Test multiple commits without an activation.
990 test_data_
.mock_callback_
,
991 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
993 pending_layer
->SetTextureMailbox(
994 test_data_
.mailbox2_
,
995 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox2_impl_
));
996 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
998 // Test callback after activation.
999 pending_layer
->PushPropertiesTo(active_layer
.get());
1000 active_layer
->DidBecomeActive();
1002 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1003 pending_layer
->SetTextureMailbox(
1004 test_data_
.mailbox1_
,
1005 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1006 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1008 EXPECT_CALL(test_data_
.mock_callback_
,
1009 ReleaseImpl(test_data_
.mailbox_name2_
, _
, false, _
)).Times(1);
1010 pending_layer
->PushPropertiesTo(active_layer
.get());
1011 active_layer
->DidBecomeActive();
1012 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1014 // Test resetting the mailbox.
1015 EXPECT_CALL(test_data_
.mock_callback_
,
1016 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1017 pending_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1018 pending_layer
->PushPropertiesTo(active_layer
.get());
1019 active_layer
->DidBecomeActive();
1020 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1024 test_data_
.mock_callback_
,
1025 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1027 pending_layer
->SetTextureMailbox(
1028 test_data_
.mailbox1_
,
1029 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1032 TEST_F(TextureLayerImplWithMailboxTest
,
1033 TestDestructorCallbackOnCreatedResource
) {
1034 scoped_ptr
<TextureLayerImpl
> impl_layer
;
1035 impl_layer
= TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1036 ASSERT_TRUE(impl_layer
);
1038 EXPECT_CALL(test_data_
.mock_callback_
,
1039 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1040 impl_layer
->SetTextureMailbox(
1041 test_data_
.mailbox1_
,
1042 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1043 impl_layer
->DidBecomeActive();
1044 EXPECT_TRUE(impl_layer
->WillDraw(
1045 DRAW_MODE_HARDWARE
, host_impl_
.active_tree()->resource_provider()));
1046 impl_layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
1047 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1050 TEST_F(TextureLayerImplWithMailboxTest
, TestCallbackOnInUseResource
) {
1051 ResourceProvider
* provider
= host_impl_
.active_tree()->resource_provider();
1052 ResourceId id
= provider
->CreateResourceFromTextureMailbox(
1053 test_data_
.mailbox1_
,
1054 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1055 provider
->AllocateForTesting(id
);
1057 // Transfer some resources to the parent.
1058 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1059 resource_ids_to_transfer
.push_back(id
);
1060 TransferableResourceArray list
;
1061 provider
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1062 EXPECT_TRUE(provider
->InUseByConsumer(id
));
1063 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1064 provider
->DeleteResource(id
);
1065 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1066 EXPECT_CALL(test_data_
.mock_callback_
,
1067 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1068 ReturnedResourceArray returned
;
1069 TransferableResource::ReturnResources(list
, &returned
);
1070 provider
->ReceiveReturnsFromParent(returned
);
1073 // Checks that TextureLayer::Update does not cause an extra commit when setting
1074 // the texture mailbox.
1075 class TextureLayerNoExtraCommitForMailboxTest
1076 : public LayerTreeTest
,
1077 public TextureLayerClient
{
1079 // TextureLayerClient implementation.
1080 bool PrepareTextureMailbox(
1081 TextureMailbox
* texture_mailbox
,
1082 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1083 bool use_shared_memory
) override
{
1084 if (layer_tree_host()->source_frame_number() == 1) {
1085 // Once this has been committed, the mailbox will be released.
1086 *texture_mailbox
= TextureMailbox();
1090 *texture_mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1091 *release_callback
= SingleReleaseCallback::Create(
1092 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased
,
1093 base::Unretained(this)));
1097 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1098 // Source frame number during callback is the same as the source frame
1099 // on which it was released.
1100 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1104 void SetupTree() override
{
1105 scoped_refptr
<Layer
> root
= Layer::Create(layer_settings());
1106 root
->SetBounds(gfx::Size(10, 10));
1107 root
->SetIsDrawable(true);
1109 texture_layer_
= TextureLayer::CreateForMailbox(layer_settings(), this);
1110 texture_layer_
->SetBounds(gfx::Size(10, 10));
1111 texture_layer_
->SetIsDrawable(true);
1112 root
->AddChild(texture_layer_
);
1114 layer_tree_host()->SetRootLayer(root
);
1115 LayerTreeTest::SetupTree();
1118 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1120 void DidCommitAndDrawFrame() override
{
1121 switch (layer_tree_host()->source_frame_number()) {
1123 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1124 // Invalidate the texture layer to clear the mailbox before
1126 texture_layer_
->SetNeedsDisplay();
1136 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1137 ASSERT_TRUE(result
);
1138 DelegatedFrameData
* delegated_frame_data
=
1139 output_surface()->last_sent_frame().delegated_frame_data
.get();
1140 if (!delegated_frame_data
)
1143 // Return all resources immediately.
1144 TransferableResourceArray resources_to_return
=
1145 output_surface()->resources_held_by_parent();
1147 CompositorFrameAck ack
;
1148 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1149 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1150 host_impl
->ReclaimResources(&ack
);
1153 void AfterTest() override
{}
1156 scoped_refptr
<TextureLayer
> texture_layer_
;
1159 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest
);
1161 // Checks that changing a mailbox in the client for a TextureLayer that's
1162 // invisible correctly works and uses the new mailbox as soon as the layer
1163 // becomes visible (and returns the old one).
1164 class TextureLayerChangeInvisibleMailboxTest
1165 : public LayerTreeTest
,
1166 public TextureLayerClient
{
1168 TextureLayerChangeInvisibleMailboxTest()
1169 : mailbox_changed_(true),
1170 mailbox_returned_(0),
1173 mailbox_
= MakeMailbox('1');
1176 // TextureLayerClient implementation.
1177 bool PrepareTextureMailbox(
1178 TextureMailbox
* mailbox
,
1179 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1180 bool use_shared_memory
) override
{
1182 if (!mailbox_changed_
)
1184 *mailbox
= mailbox_
;
1185 *release_callback
= SingleReleaseCallback::Create(
1186 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased
,
1187 base::Unretained(this)));
1191 TextureMailbox
MakeMailbox(char name
) {
1192 return TextureMailbox(MailboxFromChar(name
), GL_TEXTURE_2D
, 0);
1195 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1196 ++mailbox_returned_
;
1199 void SetupTree() override
{
1200 scoped_refptr
<Layer
> root
= Layer::Create(layer_settings());
1201 root
->SetBounds(gfx::Size(10, 10));
1202 root
->SetIsDrawable(true);
1204 solid_layer_
= SolidColorLayer::Create(layer_settings());
1205 solid_layer_
->SetBounds(gfx::Size(10, 10));
1206 solid_layer_
->SetIsDrawable(true);
1207 solid_layer_
->SetBackgroundColor(SK_ColorWHITE
);
1208 root
->AddChild(solid_layer_
);
1210 parent_layer_
= Layer::Create(layer_settings());
1211 parent_layer_
->SetBounds(gfx::Size(10, 10));
1212 parent_layer_
->SetIsDrawable(true);
1213 root
->AddChild(parent_layer_
);
1215 texture_layer_
= TextureLayer::CreateForMailbox(layer_settings(), this);
1216 texture_layer_
->SetBounds(gfx::Size(10, 10));
1217 texture_layer_
->SetIsDrawable(true);
1218 parent_layer_
->AddChild(texture_layer_
);
1220 layer_tree_host()->SetRootLayer(root
);
1221 LayerTreeTest::SetupTree();
1224 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1226 void DidCommitAndDrawFrame() override
{
1228 switch (commit_count_
) {
1230 // We should have updated the layer, committing the texture.
1231 EXPECT_EQ(1, prepare_called_
);
1232 // Make layer invisible.
1233 parent_layer_
->SetOpacity(0.f
);
1236 // Layer shouldn't have been updated.
1237 EXPECT_EQ(1, prepare_called_
);
1238 // Change the texture.
1239 mailbox_
= MakeMailbox('2');
1240 mailbox_changed_
= true;
1241 texture_layer_
->SetNeedsDisplay();
1242 // Force a change to make sure we draw a frame.
1243 solid_layer_
->SetBackgroundColor(SK_ColorGRAY
);
1246 // Layer shouldn't have been updated.
1247 EXPECT_EQ(1, prepare_called_
);
1248 // So the old mailbox isn't returned yet.
1249 EXPECT_EQ(0, mailbox_returned_
);
1250 // Make layer visible again.
1251 parent_layer_
->SetOpacity(1.f
);
1254 // Layer should have been updated.
1255 EXPECT_EQ(2, prepare_called_
);
1256 // So the old mailbox should have been returned already.
1257 EXPECT_EQ(1, mailbox_returned_
);
1258 texture_layer_
->ClearClient();
1261 EXPECT_EQ(2, mailbox_returned_
);
1270 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1271 ASSERT_TRUE(result
);
1272 DelegatedFrameData
* delegated_frame_data
=
1273 output_surface()->last_sent_frame().delegated_frame_data
.get();
1274 if (!delegated_frame_data
)
1277 // Return all resources immediately.
1278 TransferableResourceArray resources_to_return
=
1279 output_surface()->resources_held_by_parent();
1281 CompositorFrameAck ack
;
1282 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1283 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1284 host_impl
->ReclaimResources(&ack
);
1287 void AfterTest() override
{}
1290 scoped_refptr
<SolidColorLayer
> solid_layer_
;
1291 scoped_refptr
<Layer
> parent_layer_
;
1292 scoped_refptr
<TextureLayer
> texture_layer_
;
1294 // Used on the main thread.
1295 bool mailbox_changed_
;
1296 TextureMailbox mailbox_
;
1297 int mailbox_returned_
;
1298 int prepare_called_
;
1302 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest
);
1304 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1305 // the mailbox back to TextureLayerClient.
1306 class TextureLayerReleaseResourcesBase
1307 : public LayerTreeTest
,
1308 public TextureLayerClient
{
1310 // TextureLayerClient implementation.
1311 bool PrepareTextureMailbox(
1312 TextureMailbox
* mailbox
,
1313 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1314 bool use_shared_memory
) override
{
1315 *mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1316 *release_callback
= SingleReleaseCallback::Create(
1317 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased
,
1318 base::Unretained(this)));
1322 void MailboxReleased(unsigned sync_point
, bool lost_resource
) {
1323 mailbox_released_
= true;
1326 void SetupTree() override
{
1327 LayerTreeTest::SetupTree();
1329 scoped_refptr
<TextureLayer
> texture_layer
=
1330 TextureLayer::CreateForMailbox(layer_settings(), this);
1331 texture_layer
->SetBounds(gfx::Size(10, 10));
1332 texture_layer
->SetIsDrawable(true);
1334 layer_tree_host()->root_layer()->AddChild(texture_layer
);
1337 void BeginTest() override
{
1338 mailbox_released_
= false;
1339 PostSetNeedsCommitToMainThread();
1342 void DidCommitAndDrawFrame() override
{ EndTest(); }
1344 void AfterTest() override
{ EXPECT_TRUE(mailbox_released_
); }
1347 bool mailbox_released_
;
1350 class TextureLayerReleaseResourcesAfterCommit
1351 : public TextureLayerReleaseResourcesBase
{
1353 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
1354 LayerTreeImpl
* tree
= nullptr;
1355 tree
= host_impl
->sync_tree();
1356 tree
->root_layer()->children()[0]->ReleaseResources();
1360 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit
);
1362 class TextureLayerReleaseResourcesAfterActivate
1363 : public TextureLayerReleaseResourcesBase
{
1365 void DidActivateTreeOnThread(LayerTreeHostImpl
* host_impl
) override
{
1366 host_impl
->active_tree()->root_layer()->children()[0]->ReleaseResources();
1370 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate
);
1372 class TextureLayerWithMailboxMainThreadDeleted
: public LayerTreeTest
{
1374 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1375 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1376 EXPECT_FALSE(lost_resource
);
1381 void SetMailbox(char mailbox_char
) {
1382 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1383 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1385 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback
,
1386 base::Unretained(this)));
1387 layer_
->SetTextureMailbox(
1388 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1392 void SetupTree() override
{
1393 gfx::Size
bounds(100, 100);
1394 root_
= Layer::Create(layer_settings());
1395 root_
->SetBounds(bounds
);
1397 layer_
= TextureLayer::CreateForMailbox(layer_settings(), nullptr);
1398 layer_
->SetIsDrawable(true);
1399 layer_
->SetBounds(bounds
);
1401 root_
->AddChild(layer_
);
1402 layer_tree_host()->SetRootLayer(root_
);
1403 layer_tree_host()->SetViewportSize(bounds
);
1406 void BeginTest() override
{
1407 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1409 callback_count_
= 0;
1411 // Set the mailbox on the main thread.
1413 EXPECT_EQ(0, callback_count_
);
1415 PostSetNeedsCommitToMainThread();
1418 void DidCommitAndDrawFrame() override
{
1419 switch (layer_tree_host()->source_frame_number()) {
1421 // Delete the TextureLayer on the main thread while the mailbox is in
1423 layer_
->RemoveFromParent();
1429 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1432 base::ThreadChecker main_thread_
;
1433 int callback_count_
;
1434 scoped_refptr
<Layer
> root_
;
1435 scoped_refptr
<TextureLayer
> layer_
;
1438 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1439 TextureLayerWithMailboxMainThreadDeleted
);
1441 class TextureLayerWithMailboxImplThreadDeleted
: public LayerTreeTest
{
1443 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1444 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1445 EXPECT_FALSE(lost_resource
);
1450 void SetMailbox(char mailbox_char
) {
1451 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1452 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1454 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback
,
1455 base::Unretained(this)));
1456 layer_
->SetTextureMailbox(
1457 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1461 void SetupTree() override
{
1462 gfx::Size
bounds(100, 100);
1463 root_
= Layer::Create(layer_settings());
1464 root_
->SetBounds(bounds
);
1466 layer_
= TextureLayer::CreateForMailbox(layer_settings(), nullptr);
1467 layer_
->SetIsDrawable(true);
1468 layer_
->SetBounds(bounds
);
1470 root_
->AddChild(layer_
);
1471 layer_tree_host()->SetRootLayer(root_
);
1472 layer_tree_host()->SetViewportSize(bounds
);
1475 void BeginTest() override
{
1476 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1478 callback_count_
= 0;
1480 // Set the mailbox on the main thread.
1482 EXPECT_EQ(0, callback_count_
);
1484 PostSetNeedsCommitToMainThread();
1487 void DidCommitAndDrawFrame() override
{
1488 switch (layer_tree_host()->source_frame_number()) {
1490 // Remove the TextureLayer on the main thread while the mailbox is in
1491 // the impl tree, but don't delete the TextureLayer until after the impl
1492 // tree side is deleted.
1493 layer_
->RemoveFromParent();
1501 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1504 base::ThreadChecker main_thread_
;
1505 int callback_count_
;
1506 scoped_refptr
<Layer
> root_
;
1507 scoped_refptr
<TextureLayer
> layer_
;
1510 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1511 TextureLayerWithMailboxImplThreadDeleted
);