1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/layers/texture_layer.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/thread.h"
14 #include "base/time/time.h"
15 #include "cc/layers/solid_color_layer.h"
16 #include "cc/layers/texture_layer_client.h"
17 #include "cc/layers/texture_layer_impl.h"
18 #include "cc/output/compositor_frame_ack.h"
19 #include "cc/output/context_provider.h"
20 #include "cc/resources/returned_resource.h"
21 #include "cc/test/fake_impl_proxy.h"
22 #include "cc/test/fake_layer_tree_host_client.h"
23 #include "cc/test/fake_layer_tree_host_impl.h"
24 #include "cc/test/fake_output_surface.h"
25 #include "cc/test/layer_test_common.h"
26 #include "cc/test/layer_tree_test.h"
27 #include "cc/test/test_task_graph_runner.h"
28 #include "cc/test/test_web_graphics_context_3d.h"
29 #include "cc/trees/blocking_task_runner.h"
30 #include "cc/trees/layer_tree_host.h"
31 #include "cc/trees/layer_tree_impl.h"
32 #include "cc/trees/single_thread_proxy.h"
33 #include "gpu/GLES2/gl2extchromium.h"
34 #include "testing/gmock/include/gmock/gmock.h"
35 #include "testing/gtest/include/gtest/gtest.h"
37 using ::testing::Mock
;
39 using ::testing::AtLeast
;
40 using ::testing::AnyNumber
;
41 using ::testing::InvokeWithoutArgs
;
46 gpu::Mailbox
MailboxFromChar(char value
) {
48 memset(mailbox
.name
, value
, sizeof(mailbox
.name
));
52 class MockLayerTreeHost
: public LayerTreeHost
{
54 explicit MockLayerTreeHost(FakeLayerTreeHostClient
* client
)
55 : LayerTreeHost(client
, nullptr, nullptr, nullptr, LayerTreeSettings()) {
56 InitializeSingleThreaded(client
,
57 base::MessageLoopProxy::current(),
61 MOCK_METHOD0(SetNeedsCommit
, void());
62 MOCK_METHOD0(SetNeedsUpdateLayers
, void());
63 MOCK_METHOD0(StartRateLimiter
, void());
64 MOCK_METHOD0(StopRateLimiter
, void());
67 class FakeTextureLayerClient
: public TextureLayerClient
{
69 FakeTextureLayerClient() : mailbox_changed_(true) {}
71 bool PrepareTextureMailbox(
72 TextureMailbox
* mailbox
,
73 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
74 bool use_shared_memory
) override
{
75 if (!mailbox_changed_
)
79 *release_callback
= release_callback_
.Pass();
80 mailbox_changed_
= false;
84 void set_mailbox(const TextureMailbox
& mailbox
,
85 scoped_ptr
<SingleReleaseCallback
> release_callback
) {
87 release_callback_
= release_callback
.Pass();
88 mailbox_changed_
= true;
92 TextureMailbox mailbox_
;
93 scoped_ptr
<SingleReleaseCallback
> release_callback_
;
94 bool mailbox_changed_
;
95 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient
);
98 class MockMailboxCallback
{
100 MOCK_METHOD3(Release
,
101 void(const gpu::Mailbox
& mailbox
,
103 bool lost_resource
));
104 MOCK_METHOD3(Release2
,
105 void(SharedBitmap
* shared_bitmap
,
107 bool lost_resource
));
108 MOCK_METHOD4(ReleaseImpl
,
109 void(const gpu::Mailbox
& mailbox
,
112 BlockingTaskRunner
* main_thread_task_runner
));
113 MOCK_METHOD4(ReleaseImpl2
,
114 void(SharedBitmap
* shared_bitmap
,
117 BlockingTaskRunner
* main_thread_task_runner
));
120 struct CommonMailboxObjects
{
121 explicit CommonMailboxObjects(SharedBitmapManager
* manager
)
122 : mailbox_name1_(MailboxFromChar('1')),
123 mailbox_name2_(MailboxFromChar('2')),
126 release_mailbox1_
= base::Bind(&MockMailboxCallback::Release
,
127 base::Unretained(&mock_callback_
),
129 release_mailbox2_
= base::Bind(&MockMailboxCallback::Release
,
130 base::Unretained(&mock_callback_
),
132 release_mailbox1_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
133 base::Unretained(&mock_callback_
),
135 release_mailbox2_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
136 base::Unretained(&mock_callback_
),
138 const uint32 arbitrary_target1
= GL_TEXTURE_2D
;
139 const uint32 arbitrary_target2
= GL_TEXTURE_EXTERNAL_OES
;
140 mailbox1_
= TextureMailbox(mailbox_name1_
, arbitrary_target1
, sync_point1_
);
141 mailbox2_
= TextureMailbox(mailbox_name2_
, arbitrary_target2
, sync_point2_
);
142 gfx::Size
size(128, 128);
143 shared_bitmap_
= manager
->AllocateSharedBitmap(size
);
144 DCHECK(shared_bitmap_
);
146 base::Bind(&MockMailboxCallback::Release2
,
147 base::Unretained(&mock_callback_
), shared_bitmap_
.get());
148 release_mailbox3_impl_
=
149 base::Bind(&MockMailboxCallback::ReleaseImpl2
,
150 base::Unretained(&mock_callback_
), shared_bitmap_
.get());
151 mailbox3_
= TextureMailbox(shared_bitmap_
.get(), size
);
154 gpu::Mailbox mailbox_name1_
;
155 gpu::Mailbox mailbox_name2_
;
156 MockMailboxCallback mock_callback_
;
157 ReleaseCallback release_mailbox1_
;
158 ReleaseCallback release_mailbox2_
;
159 ReleaseCallback release_mailbox3_
;
160 ReleaseCallbackImpl release_mailbox1_impl_
;
161 ReleaseCallbackImpl release_mailbox2_impl_
;
162 ReleaseCallbackImpl release_mailbox3_impl_
;
163 TextureMailbox mailbox1_
;
164 TextureMailbox mailbox2_
;
165 TextureMailbox mailbox3_
;
168 scoped_ptr
<SharedBitmap
> shared_bitmap_
;
171 class TextureLayerTest
: public testing::Test
{
175 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)),
176 host_impl_(&proxy_
, &shared_bitmap_manager_
, &task_graph_runner_
),
177 test_data_(&shared_bitmap_manager_
) {}
180 void SetUp() override
{
181 layer_tree_host_
.reset(new MockLayerTreeHost(&fake_client_
));
182 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
183 layer_tree_host_
->SetViewportSize(gfx::Size(10, 10));
184 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
187 void TearDown() override
{
188 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
189 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
191 layer_tree_host_
->SetRootLayer(nullptr);
192 layer_tree_host_
= nullptr;
195 scoped_ptr
<MockLayerTreeHost
> layer_tree_host_
;
196 FakeImplProxy proxy_
;
197 FakeLayerTreeHostClient fake_client_
;
198 TestSharedBitmapManager shared_bitmap_manager_
;
199 TestTaskGraphRunner task_graph_runner_
;
200 FakeLayerTreeHostImpl host_impl_
;
201 CommonMailboxObjects test_data_
;
204 TEST_F(TextureLayerTest
, CheckPropertyChangeCausesCorrectBehavior
) {
205 scoped_refptr
<TextureLayer
> test_layer
=
206 TextureLayer::CreateForMailbox(nullptr);
207 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_
->SetRootLayer(test_layer
));
209 // Test properties that should call SetNeedsCommit. All properties need to
210 // be set to new values in order for SetNeedsCommit to be called.
211 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetFlipped(false));
212 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetNearestNeighbor(true));
213 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetUV(
214 gfx::PointF(0.25f
, 0.25f
), gfx::PointF(0.75f
, 0.75f
)));
215 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetVertexOpacity(
216 0.5f
, 0.5f
, 0.5f
, 0.5f
));
217 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetPremultipliedAlpha(false));
218 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetBlendBackgroundColor(true));
221 TEST_F(TextureLayerTest
, VisibleContentOpaqueRegion
) {
222 const gfx::Size
layer_bounds(100, 100);
223 const gfx::Rect
layer_rect(layer_bounds
);
224 const Region
layer_region(layer_rect
);
226 scoped_refptr
<TextureLayer
> layer
= TextureLayer::CreateForMailbox(nullptr);
227 layer
->SetBounds(layer_bounds
);
228 layer
->draw_properties().visible_content_rect
= layer_rect
;
229 layer
->SetBlendBackgroundColor(true);
231 // Verify initial conditions.
232 EXPECT_FALSE(layer
->contents_opaque());
233 EXPECT_EQ(0u, layer
->background_color());
234 EXPECT_EQ(Region().ToString(),
235 layer
->VisibleContentOpaqueRegion().ToString());
237 // Opaque background.
238 layer
->SetBackgroundColor(SK_ColorWHITE
);
239 EXPECT_EQ(layer_region
.ToString(),
240 layer
->VisibleContentOpaqueRegion().ToString());
242 // Transparent background.
243 layer
->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
244 EXPECT_EQ(Region().ToString(),
245 layer
->VisibleContentOpaqueRegion().ToString());
248 TEST_F(TextureLayerTest
, RateLimiter
) {
249 FakeTextureLayerClient client
;
250 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(
252 test_layer
->SetIsDrawable(true);
253 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
254 layer_tree_host_
->SetRootLayer(test_layer
);
256 // Don't rate limit until we invalidate.
257 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
258 test_layer
->SetRateLimitContext(true);
259 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
261 // Do rate limit after we invalidate.
262 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
263 test_layer
->SetNeedsDisplay();
264 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
266 // Stop rate limiter when we don't want it any more.
267 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
268 test_layer
->SetRateLimitContext(false);
269 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
271 // Or we clear the client.
272 test_layer
->SetRateLimitContext(true);
273 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
274 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
275 test_layer
->ClearClient();
276 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
278 // Reset to a layer with a client, that started the rate limiter.
279 test_layer
= TextureLayer::CreateForMailbox(
281 test_layer
->SetIsDrawable(true);
282 test_layer
->SetRateLimitContext(true);
283 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
284 layer_tree_host_
->SetRootLayer(test_layer
);
285 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
286 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
287 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
288 test_layer
->SetNeedsDisplay();
289 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
291 // Stop rate limiter when we're removed from the tree.
292 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
293 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(1);
294 layer_tree_host_
->SetRootLayer(nullptr);
295 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
298 class TestMailboxHolder
: public TextureLayer::TextureMailboxHolder
{
300 using TextureLayer::TextureMailboxHolder::Create
;
303 ~TestMailboxHolder() override
{}
306 class TextureLayerWithMailboxTest
: public TextureLayerTest
{
308 void TearDown() override
{
309 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
310 EXPECT_CALL(test_data_
.mock_callback_
,
311 Release(test_data_
.mailbox_name1_
,
312 test_data_
.sync_point1_
,
314 TextureLayerTest::TearDown();
318 TEST_F(TextureLayerWithMailboxTest
, ReplaceMailboxOnMainThreadBeforeCommit
) {
319 scoped_refptr
<TextureLayer
> test_layer
=
320 TextureLayer::CreateForMailbox(nullptr);
321 ASSERT_TRUE(test_layer
.get());
323 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
324 layer_tree_host_
->SetRootLayer(test_layer
);
325 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
327 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
328 test_layer
->SetTextureMailbox(
329 test_data_
.mailbox1_
,
330 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
331 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
333 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
334 EXPECT_CALL(test_data_
.mock_callback_
,
335 Release(test_data_
.mailbox_name1_
,
336 test_data_
.sync_point1_
,
339 test_layer
->SetTextureMailbox(
340 test_data_
.mailbox2_
,
341 SingleReleaseCallback::Create(test_data_
.release_mailbox2_
));
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 EXPECT_CALL(test_data_
.mock_callback_
,
347 Release(test_data_
.mailbox_name2_
,
348 test_data_
.sync_point2_
,
351 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
352 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
353 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
355 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
356 test_layer
->SetTextureMailbox(
357 test_data_
.mailbox3_
,
358 SingleReleaseCallback::Create(test_data_
.release_mailbox3_
));
359 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
360 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
362 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
363 EXPECT_CALL(test_data_
.mock_callback_
,
364 Release2(test_data_
.shared_bitmap_
.get(), 0, false)).Times(1);
365 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
366 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
367 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
370 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
371 test_layer
->SetTextureMailbox(
372 test_data_
.mailbox1_
,
373 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
376 TEST_F(TextureLayerTest
, SetTextureMailboxWithoutReleaseCallback
) {
377 scoped_refptr
<TextureLayer
> test_layer
=
378 TextureLayer::CreateForMailbox(nullptr);
379 ASSERT_TRUE(test_layer
.get());
381 // These use the same gpu::Mailbox, but different sync points.
382 TextureMailbox
mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D
, 1);
383 TextureMailbox
mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D
, 2);
385 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
386 layer_tree_host_
->SetRootLayer(test_layer
);
387 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
389 // Set the mailbox the first time. It should cause a commit.
390 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
391 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox1
);
392 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
394 // Set the mailbox again with a new sync point, as the backing texture has
395 // been updated. It should cause a new commit.
396 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
397 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox2
);
398 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
401 class TextureLayerMailboxHolderTest
: public TextureLayerTest
{
403 TextureLayerMailboxHolderTest()
404 : main_thread_("MAIN") {
405 main_thread_
.Start();
406 main_thread_
.message_loop()->PostTask(
408 base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain
,
409 base::Unretained(this)));
413 void Wait(const base::Thread
& thread
) {
414 bool manual_reset
= false;
415 bool initially_signaled
= false;
416 base::WaitableEvent
event(manual_reset
, initially_signaled
);
417 thread
.message_loop()->PostTask(
419 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
423 void CreateMainRef() {
424 main_ref_
= TestMailboxHolder::Create(
425 test_data_
.mailbox1_
,
426 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
)).Pass();
429 void ReleaseMainRef() { main_ref_
= nullptr; }
431 void CreateImplRef(scoped_ptr
<SingleReleaseCallbackImpl
>* impl_ref
) {
432 *impl_ref
= main_ref_
->holder()->GetCallbackForImplThread();
435 void CapturePostTasksAndWait(base::WaitableEvent
* begin_capture
,
436 base::WaitableEvent
* wait_for_capture
,
437 base::WaitableEvent
* stop_capture
) {
438 begin_capture
->Wait();
439 BlockingTaskRunner::CapturePostTasks
capture(
440 main_thread_task_runner_
.get());
441 wait_for_capture
->Signal();
442 stop_capture
->Wait();
446 void InitializeOnMain() {
447 main_thread_task_runner_
=
448 BlockingTaskRunner::Create(main_thread_
.message_loop_proxy());
451 scoped_ptr
<TestMailboxHolder::MainThreadReference
>
453 base::Thread main_thread_
;
454 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
457 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_BothReleaseThenMain
) {
458 scoped_refptr
<TextureLayer
> test_layer
=
459 TextureLayer::CreateForMailbox(nullptr);
460 ASSERT_TRUE(test_layer
.get());
462 main_thread_
.message_loop()->PostTask(
464 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
465 base::Unretained(this)));
469 // The texture layer is attached to compositor1, and passes a reference to its
471 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
472 main_thread_
.message_loop()->PostTask(
474 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
475 base::Unretained(this),
478 // Then the texture layer is removed and attached to compositor2, and passes a
479 // reference to its impl tree.
480 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
481 main_thread_
.message_loop()->PostTask(
483 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
484 base::Unretained(this),
488 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
490 // The compositors both destroy their impl trees before the main thread layer
492 compositor1
->Run(100, false, main_thread_task_runner_
.get());
493 compositor2
->Run(200, false, main_thread_task_runner_
.get());
497 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
498 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
500 // The main thread ref is the last one, so the mailbox is released back to the
501 // embedder, with the last sync point provided by the impl trees.
502 EXPECT_CALL(test_data_
.mock_callback_
,
503 Release(test_data_
.mailbox_name1_
, 200, false)).Times(1);
505 main_thread_
.message_loop()->PostTask(
507 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
508 base::Unretained(this)));
510 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
513 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleaseBetween
) {
514 scoped_refptr
<TextureLayer
> test_layer
=
515 TextureLayer::CreateForMailbox(nullptr);
516 ASSERT_TRUE(test_layer
.get());
518 main_thread_
.message_loop()->PostTask(
520 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
521 base::Unretained(this)));
525 // The texture layer is attached to compositor1, and passes a reference to its
527 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
528 main_thread_
.message_loop()->PostTask(
530 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
531 base::Unretained(this),
534 // Then the texture layer is removed and attached to compositor2, and passes a
535 // reference to its impl tree.
536 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
537 main_thread_
.message_loop()->PostTask(
539 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
540 base::Unretained(this),
544 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
546 // One compositor destroys their impl tree.
547 compositor1
->Run(100, false, main_thread_task_runner_
.get());
549 // Then the main thread reference is destroyed.
550 main_thread_
.message_loop()->PostTask(
552 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
553 base::Unretained(this)));
557 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
558 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
560 // The second impl reference is destroyed last, causing the mailbox to be
561 // released back to the embedder with the last sync point from the impl tree.
562 EXPECT_CALL(test_data_
.mock_callback_
,
563 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
565 compositor2
->Run(200, true, main_thread_task_runner_
.get());
567 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
570 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleasedFirst
) {
571 scoped_refptr
<TextureLayer
> test_layer
=
572 TextureLayer::CreateForMailbox(nullptr);
573 ASSERT_TRUE(test_layer
.get());
575 main_thread_
.message_loop()->PostTask(
577 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
578 base::Unretained(this)));
582 // The texture layer is attached to compositor1, and passes a reference to its
584 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
585 main_thread_
.message_loop()->PostTask(
587 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
588 base::Unretained(this),
591 // Then the texture layer is removed and attached to compositor2, and passes a
592 // reference to its impl tree.
593 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
594 main_thread_
.message_loop()->PostTask(
596 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
597 base::Unretained(this),
601 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
603 // The main thread reference is destroyed first.
604 main_thread_
.message_loop()->PostTask(
606 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
607 base::Unretained(this)));
609 // One compositor destroys their impl tree.
610 compositor2
->Run(200, false, main_thread_task_runner_
.get());
614 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
615 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
617 // The second impl reference is destroyed last, causing the mailbox to be
618 // released back to the embedder with the last sync point from the impl tree.
619 EXPECT_CALL(test_data_
.mock_callback_
,
620 Release(test_data_
.mailbox_name1_
, 100, true)).Times(1);
622 compositor1
->Run(100, true, main_thread_task_runner_
.get());
624 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
627 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_SecondImplRefShortcut
) {
628 scoped_refptr
<TextureLayer
> test_layer
=
629 TextureLayer::CreateForMailbox(nullptr);
630 ASSERT_TRUE(test_layer
.get());
632 main_thread_
.message_loop()->PostTask(
634 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
635 base::Unretained(this)));
639 // The texture layer is attached to compositor1, and passes a reference to its
641 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
642 main_thread_
.message_loop()->PostTask(
644 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
645 base::Unretained(this),
648 // Then the texture layer is removed and attached to compositor2, and passes a
649 // reference to its impl tree.
650 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
651 main_thread_
.message_loop()->PostTask(
653 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
654 base::Unretained(this),
658 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
660 // The main thread reference is destroyed first.
661 main_thread_
.message_loop()->PostTask(
663 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
664 base::Unretained(this)));
666 EXPECT_CALL(test_data_
.mock_callback_
,
667 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
669 bool manual_reset
= false;
670 bool initially_signaled
= false;
671 base::WaitableEvent
begin_capture(manual_reset
, initially_signaled
);
672 base::WaitableEvent
wait_for_capture(manual_reset
, initially_signaled
);
673 base::WaitableEvent
stop_capture(manual_reset
, initially_signaled
);
675 // Post a task to start capturing tasks on the main thread. This will block
676 // the main thread until we signal the |stop_capture| event.
677 main_thread_
.message_loop()->PostTask(
679 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait
,
680 base::Unretained(this),
685 // Before the main thread capturing starts, one compositor destroys their
686 // impl reference. Since capturing did not start, this gets post-tasked to
688 compositor1
->Run(100, false, main_thread_task_runner_
.get());
690 // Start capturing on the main thread.
691 begin_capture
.Signal();
692 wait_for_capture
.Wait();
694 // Meanwhile, the second compositor released its impl reference, but this task
695 // gets shortcutted directly to the main thread. This means the reference is
696 // released before compositor1, whose reference will be released later when
697 // the post-task is serviced. But since it was destroyed _on the impl thread_
698 // last, its sync point values should be used.
699 compositor2
->Run(200, true, main_thread_task_runner_
.get());
701 stop_capture
.Signal();
704 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
707 class TextureLayerImplWithMailboxThreadedCallback
: public LayerTreeTest
{
709 TextureLayerImplWithMailboxThreadedCallback()
710 : callback_count_(0),
713 // Make sure callback is received on main and doesn't block the impl thread.
714 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
715 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
716 EXPECT_FALSE(lost_resource
);
720 void SetMailbox(char mailbox_char
) {
721 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
722 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
724 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback
,
725 base::Unretained(this)));
726 layer_
->SetTextureMailbox(
727 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
731 void BeginTest() override
{
732 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
734 gfx::Size
bounds(100, 100);
735 root_
= Layer::Create();
736 root_
->SetBounds(bounds
);
738 layer_
= TextureLayer::CreateForMailbox(nullptr);
739 layer_
->SetIsDrawable(true);
740 layer_
->SetBounds(bounds
);
742 root_
->AddChild(layer_
);
743 layer_tree_host()->SetRootLayer(root_
);
744 layer_tree_host()->SetViewportSize(bounds
);
746 EXPECT_EQ(0, callback_count_
);
748 // Case #1: change mailbox before the commit. The old mailbox should be
749 // released immediately.
751 EXPECT_EQ(1, callback_count_
);
752 PostSetNeedsCommitToMainThread();
755 void DidCommit() override
{
757 switch (commit_count_
) {
759 // Case #2: change mailbox after the commit (and draw), where the
760 // layer draws. The old mailbox should be released during the next
763 EXPECT_EQ(1, callback_count_
);
766 EXPECT_EQ(2, callback_count_
);
767 // Case #3: change mailbox when the layer doesn't draw. The old
768 // mailbox should be released during the next commit.
769 layer_
->SetBounds(gfx::Size());
773 EXPECT_EQ(3, callback_count_
);
774 // Case #4: release mailbox that was committed but never drawn. The
775 // old mailbox should be released during the next commit.
776 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
779 if (layer_tree_host()->settings().impl_side_painting
) {
780 // With impl painting, the texture mailbox will still be on the impl
781 // thread when the commit finishes, because the layer is not drawble
782 // when it has no texture mailbox, and thus does not block the commit
783 // on activation. So, we wait for activation.
784 // TODO(danakj): fix this. crbug.com/277953
785 layer_tree_host()->SetNeedsCommit();
791 EXPECT_EQ(4, callback_count_
);
792 // Restore a mailbox for the next step.
796 // Case #5: remove layer from tree. Callback should *not* be called, the
797 // mailbox is returned to the main thread.
798 EXPECT_EQ(4, callback_count_
);
799 layer_
->RemoveFromParent();
802 if (layer_tree_host()->settings().impl_side_painting
) {
803 // With impl painting, the texture mailbox will still be on the impl
804 // thread when the commit finishes, because the layer is not around to
805 // block the commit on activation anymore. So, we wait for activation.
806 // TODO(danakj): fix this. crbug.com/277953
807 layer_tree_host()->SetNeedsCommit();
813 EXPECT_EQ(4, callback_count_
);
814 // Resetting the mailbox will call the callback now.
815 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
816 EXPECT_EQ(5, callback_count_
);
825 void AfterTest() override
{}
828 base::ThreadChecker main_thread_
;
831 scoped_refptr
<Layer
> root_
;
832 scoped_refptr
<TextureLayer
> layer_
;
835 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
836 TextureLayerImplWithMailboxThreadedCallback
);
839 class TextureLayerMailboxIsActivatedDuringCommit
: public LayerTreeTest
{
841 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
843 static void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {}
845 void SetMailbox(char mailbox_char
) {
846 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
848 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback
));
849 layer_
->SetTextureMailbox(
850 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
854 void BeginTest() override
{
855 gfx::Size
bounds(100, 100);
856 root_
= Layer::Create();
857 root_
->SetBounds(bounds
);
859 layer_
= TextureLayer::CreateForMailbox(nullptr);
860 layer_
->SetIsDrawable(true);
861 layer_
->SetBounds(bounds
);
863 root_
->AddChild(layer_
);
864 layer_tree_host()->SetRootLayer(root_
);
865 layer_tree_host()->SetViewportSize(bounds
);
868 PostSetNeedsCommitToMainThread();
871 void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
875 void DidCommit() override
{
876 switch (layer_tree_host()->source_frame_number()) {
878 // The first mailbox has been activated. Set a new mailbox, and
879 // expect the next commit to finish *after* it is activated.
883 // The second mailbox has been activated. Remove the layer from
884 // the tree to cause another commit/activation. The commit should
885 // finish *after* the layer is removed from the active tree.
886 layer_
->RemoveFromParent();
894 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
895 switch (host_impl
->active_tree()->source_frame_number()) {
897 // The activate for the 1st mailbox should have happened before now.
898 EXPECT_EQ(1, activate_count_
);
902 // The activate for the 2nd mailbox should have happened before now.
903 EXPECT_EQ(2, activate_count_
);
907 // The activate to remove the layer should have happened before now.
908 EXPECT_EQ(3, activate_count_
);
918 void AfterTest() override
{}
921 scoped_refptr
<Layer
> root_
;
922 scoped_refptr
<TextureLayer
> layer_
;
925 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
926 TextureLayerMailboxIsActivatedDuringCommit
);
928 class TextureLayerImplWithMailboxTest
: public TextureLayerTest
{
930 TextureLayerImplWithMailboxTest()
932 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)) {}
934 void SetUp() override
{
935 TextureLayerTest::SetUp();
936 layer_tree_host_
.reset(new MockLayerTreeHost(&fake_client_
));
937 EXPECT_TRUE(host_impl_
.InitializeRenderer(FakeOutputSurface::Create3d()));
940 bool WillDraw(TextureLayerImpl
* layer
, DrawMode mode
) {
941 bool will_draw
= layer
->WillDraw(
942 mode
, host_impl_
.active_tree()->resource_provider());
944 layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
948 FakeLayerTreeHostClient fake_client_
;
951 // Test conditions for results of TextureLayerImpl::WillDraw under
952 // different configurations of different mailbox, texture_id, and draw_mode.
953 TEST_F(TextureLayerImplWithMailboxTest
, TestWillDraw
) {
955 test_data_
.mock_callback_
,
956 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
958 EXPECT_CALL(test_data_
.mock_callback_
,
959 ReleaseImpl2(test_data_
.shared_bitmap_
.get(), 0, false, _
))
963 scoped_ptr
<TextureLayerImpl
> impl_layer
=
964 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
965 impl_layer
->SetTextureMailbox(
966 test_data_
.mailbox1_
,
967 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
968 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
972 scoped_ptr
<TextureLayerImpl
> impl_layer
=
973 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
974 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
975 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
979 // Software resource.
980 scoped_ptr
<TextureLayerImpl
> impl_layer
=
981 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
982 impl_layer
->SetTextureMailbox(
983 test_data_
.mailbox3_
,
984 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
985 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
990 scoped_ptr
<TextureLayerImpl
> impl_layer
=
991 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
992 impl_layer
->SetTextureMailbox(
993 test_data_
.mailbox1_
,
994 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
995 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
999 scoped_ptr
<TextureLayerImpl
> impl_layer
=
1000 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1001 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1002 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
1006 // Software resource.
1007 scoped_ptr
<TextureLayerImpl
> impl_layer
=
1008 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1009 impl_layer
->SetTextureMailbox(
1010 test_data_
.mailbox3_
,
1011 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
1012 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
1015 // Resourceless software mode.
1017 scoped_ptr
<TextureLayerImpl
> impl_layer
=
1018 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1019 impl_layer
->SetTextureMailbox(
1020 test_data_
.mailbox1_
,
1021 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1022 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_RESOURCELESS_SOFTWARE
));
1026 TEST_F(TextureLayerImplWithMailboxTest
, TestImplLayerCallbacks
) {
1027 host_impl_
.CreatePendingTree();
1028 scoped_ptr
<TextureLayerImpl
> pending_layer
;
1029 pending_layer
= TextureLayerImpl::Create(host_impl_
.pending_tree(), 1);
1030 ASSERT_TRUE(pending_layer
);
1032 scoped_ptr
<LayerImpl
> active_layer(
1033 pending_layer
->CreateLayerImpl(host_impl_
.active_tree()));
1034 ASSERT_TRUE(active_layer
);
1036 pending_layer
->SetTextureMailbox(
1037 test_data_
.mailbox1_
,
1038 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1040 // Test multiple commits without an activation.
1042 test_data_
.mock_callback_
,
1043 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1045 pending_layer
->SetTextureMailbox(
1046 test_data_
.mailbox2_
,
1047 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox2_impl_
));
1048 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1050 // Test callback after activation.
1051 pending_layer
->PushPropertiesTo(active_layer
.get());
1052 active_layer
->DidBecomeActive();
1054 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1055 pending_layer
->SetTextureMailbox(
1056 test_data_
.mailbox1_
,
1057 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1058 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1060 EXPECT_CALL(test_data_
.mock_callback_
,
1061 ReleaseImpl(test_data_
.mailbox_name2_
, _
, false, _
)).Times(1);
1062 pending_layer
->PushPropertiesTo(active_layer
.get());
1063 active_layer
->DidBecomeActive();
1064 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1066 // Test resetting the mailbox.
1067 EXPECT_CALL(test_data_
.mock_callback_
,
1068 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1069 pending_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1070 pending_layer
->PushPropertiesTo(active_layer
.get());
1071 active_layer
->DidBecomeActive();
1072 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1076 test_data_
.mock_callback_
,
1077 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1079 pending_layer
->SetTextureMailbox(
1080 test_data_
.mailbox1_
,
1081 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1084 TEST_F(TextureLayerImplWithMailboxTest
,
1085 TestDestructorCallbackOnCreatedResource
) {
1086 scoped_ptr
<TextureLayerImpl
> impl_layer
;
1087 impl_layer
= TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1088 ASSERT_TRUE(impl_layer
);
1090 EXPECT_CALL(test_data_
.mock_callback_
,
1091 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1092 impl_layer
->SetTextureMailbox(
1093 test_data_
.mailbox1_
,
1094 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1095 impl_layer
->DidBecomeActive();
1096 EXPECT_TRUE(impl_layer
->WillDraw(
1097 DRAW_MODE_HARDWARE
, host_impl_
.active_tree()->resource_provider()));
1098 impl_layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
1099 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1102 TEST_F(TextureLayerImplWithMailboxTest
, TestCallbackOnInUseResource
) {
1103 ResourceProvider
* provider
= host_impl_
.active_tree()->resource_provider();
1104 ResourceProvider::ResourceId id
= provider
->CreateResourceFromTextureMailbox(
1105 test_data_
.mailbox1_
,
1106 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1107 provider
->AllocateForTesting(id
);
1109 // Transfer some resources to the parent.
1110 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1111 resource_ids_to_transfer
.push_back(id
);
1112 TransferableResourceArray list
;
1113 provider
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1114 EXPECT_TRUE(provider
->InUseByConsumer(id
));
1115 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1116 provider
->DeleteResource(id
);
1117 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1118 EXPECT_CALL(test_data_
.mock_callback_
,
1119 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1120 ReturnedResourceArray returned
;
1121 TransferableResource::ReturnResources(list
, &returned
);
1122 provider
->ReceiveReturnsFromParent(returned
);
1125 // Checks that TextureLayer::Update does not cause an extra commit when setting
1126 // the texture mailbox.
1127 class TextureLayerNoExtraCommitForMailboxTest
1128 : public LayerTreeTest
,
1129 public TextureLayerClient
{
1131 // TextureLayerClient implementation.
1132 bool PrepareTextureMailbox(
1133 TextureMailbox
* texture_mailbox
,
1134 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1135 bool use_shared_memory
) override
{
1136 if (layer_tree_host()->source_frame_number() == 1) {
1137 // Once this has been committed, the mailbox will be released.
1138 *texture_mailbox
= TextureMailbox();
1142 *texture_mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1143 *release_callback
= SingleReleaseCallback::Create(
1144 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased
,
1145 base::Unretained(this)));
1149 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1150 // Source frame number during callback is the same as the source frame
1151 // on which it was released.
1152 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1156 void SetupTree() override
{
1157 scoped_refptr
<Layer
> root
= Layer::Create();
1158 root
->SetBounds(gfx::Size(10, 10));
1159 root
->SetIsDrawable(true);
1161 texture_layer_
= TextureLayer::CreateForMailbox(this);
1162 texture_layer_
->SetBounds(gfx::Size(10, 10));
1163 texture_layer_
->SetIsDrawable(true);
1164 root
->AddChild(texture_layer_
);
1166 layer_tree_host()->SetRootLayer(root
);
1167 LayerTreeTest::SetupTree();
1170 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1172 void DidCommitAndDrawFrame() override
{
1173 switch (layer_tree_host()->source_frame_number()) {
1175 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1176 // Invalidate the texture layer to clear the mailbox before
1178 texture_layer_
->SetNeedsDisplay();
1188 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1189 ASSERT_TRUE(result
);
1190 DelegatedFrameData
* delegated_frame_data
=
1191 output_surface()->last_sent_frame().delegated_frame_data
.get();
1192 if (!delegated_frame_data
)
1195 // Return all resources immediately.
1196 TransferableResourceArray resources_to_return
=
1197 output_surface()->resources_held_by_parent();
1199 CompositorFrameAck ack
;
1200 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1201 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1202 host_impl
->ReclaimResources(&ack
);
1205 void AfterTest() override
{}
1208 scoped_refptr
<TextureLayer
> texture_layer_
;
1211 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest
);
1213 // Checks that changing a mailbox in the client for a TextureLayer that's
1214 // invisible correctly works and uses the new mailbox as soon as the layer
1215 // becomes visible (and returns the old one).
1216 class TextureLayerChangeInvisibleMailboxTest
1217 : public LayerTreeTest
,
1218 public TextureLayerClient
{
1220 TextureLayerChangeInvisibleMailboxTest()
1221 : mailbox_changed_(true),
1222 mailbox_returned_(0),
1225 mailbox_
= MakeMailbox('1');
1228 // TextureLayerClient implementation.
1229 bool PrepareTextureMailbox(
1230 TextureMailbox
* mailbox
,
1231 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1232 bool use_shared_memory
) override
{
1234 if (!mailbox_changed_
)
1236 *mailbox
= mailbox_
;
1237 *release_callback
= SingleReleaseCallback::Create(
1238 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased
,
1239 base::Unretained(this)));
1243 TextureMailbox
MakeMailbox(char name
) {
1244 return TextureMailbox(MailboxFromChar(name
), GL_TEXTURE_2D
, 0);
1247 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1248 ++mailbox_returned_
;
1251 void SetupTree() override
{
1252 scoped_refptr
<Layer
> root
= Layer::Create();
1253 root
->SetBounds(gfx::Size(10, 10));
1254 root
->SetIsDrawable(true);
1256 solid_layer_
= SolidColorLayer::Create();
1257 solid_layer_
->SetBounds(gfx::Size(10, 10));
1258 solid_layer_
->SetIsDrawable(true);
1259 solid_layer_
->SetBackgroundColor(SK_ColorWHITE
);
1260 root
->AddChild(solid_layer_
);
1262 parent_layer_
= Layer::Create();
1263 parent_layer_
->SetBounds(gfx::Size(10, 10));
1264 parent_layer_
->SetIsDrawable(true);
1265 root
->AddChild(parent_layer_
);
1267 texture_layer_
= TextureLayer::CreateForMailbox(this);
1268 texture_layer_
->SetBounds(gfx::Size(10, 10));
1269 texture_layer_
->SetIsDrawable(true);
1270 parent_layer_
->AddChild(texture_layer_
);
1272 layer_tree_host()->SetRootLayer(root
);
1273 LayerTreeTest::SetupTree();
1276 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1278 void DidCommitAndDrawFrame() override
{
1280 switch (commit_count_
) {
1282 // We should have updated the layer, committing the texture.
1283 EXPECT_EQ(1, prepare_called_
);
1284 // Make layer invisible.
1285 parent_layer_
->SetOpacity(0.f
);
1288 // Layer shouldn't have been updated.
1289 EXPECT_EQ(1, prepare_called_
);
1290 // Change the texture.
1291 mailbox_
= MakeMailbox('2');
1292 mailbox_changed_
= true;
1293 texture_layer_
->SetNeedsDisplay();
1294 // Force a change to make sure we draw a frame.
1295 solid_layer_
->SetBackgroundColor(SK_ColorGRAY
);
1298 // Layer shouldn't have been updated.
1299 EXPECT_EQ(1, prepare_called_
);
1300 // So the old mailbox isn't returned yet.
1301 EXPECT_EQ(0, mailbox_returned_
);
1302 // Make layer visible again.
1303 parent_layer_
->SetOpacity(1.f
);
1306 // Layer should have been updated.
1307 EXPECT_EQ(2, prepare_called_
);
1308 // So the old mailbox should have been returned already.
1309 EXPECT_EQ(1, mailbox_returned_
);
1310 texture_layer_
->ClearClient();
1313 EXPECT_EQ(2, mailbox_returned_
);
1322 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1323 ASSERT_TRUE(result
);
1324 DelegatedFrameData
* delegated_frame_data
=
1325 output_surface()->last_sent_frame().delegated_frame_data
.get();
1326 if (!delegated_frame_data
)
1329 // Return all resources immediately.
1330 TransferableResourceArray resources_to_return
=
1331 output_surface()->resources_held_by_parent();
1333 CompositorFrameAck ack
;
1334 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1335 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1336 host_impl
->ReclaimResources(&ack
);
1339 void AfterTest() override
{}
1342 scoped_refptr
<SolidColorLayer
> solid_layer_
;
1343 scoped_refptr
<Layer
> parent_layer_
;
1344 scoped_refptr
<TextureLayer
> texture_layer_
;
1346 // Used on the main thread.
1347 bool mailbox_changed_
;
1348 TextureMailbox mailbox_
;
1349 int mailbox_returned_
;
1350 int prepare_called_
;
1354 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest
);
1356 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1357 // the mailbox back to TextureLayerClient.
1358 class TextureLayerReleaseResourcesBase
1359 : public LayerTreeTest
,
1360 public TextureLayerClient
{
1362 // TextureLayerClient implementation.
1363 bool PrepareTextureMailbox(
1364 TextureMailbox
* mailbox
,
1365 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1366 bool use_shared_memory
) override
{
1367 *mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1368 *release_callback
= SingleReleaseCallback::Create(
1369 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased
,
1370 base::Unretained(this)));
1374 void MailboxReleased(unsigned sync_point
, bool lost_resource
) {
1375 mailbox_released_
= true;
1378 void SetupTree() override
{
1379 LayerTreeTest::SetupTree();
1381 scoped_refptr
<TextureLayer
> texture_layer
=
1382 TextureLayer::CreateForMailbox(this);
1383 texture_layer
->SetBounds(gfx::Size(10, 10));
1384 texture_layer
->SetIsDrawable(true);
1386 layer_tree_host()->root_layer()->AddChild(texture_layer
);
1389 void BeginTest() override
{
1390 mailbox_released_
= false;
1391 PostSetNeedsCommitToMainThread();
1394 void DidCommitAndDrawFrame() override
{ EndTest(); }
1396 void AfterTest() override
{ EXPECT_TRUE(mailbox_released_
); }
1399 bool mailbox_released_
;
1402 class TextureLayerReleaseResourcesAfterCommit
1403 : public TextureLayerReleaseResourcesBase
{
1405 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
1406 LayerTreeImpl
* tree
= nullptr;
1407 tree
= host_impl
->sync_tree();
1408 tree
->root_layer()->children()[0]->ReleaseResources();
1412 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit
);
1414 class TextureLayerReleaseResourcesAfterActivate
1415 : public TextureLayerReleaseResourcesBase
{
1417 void DidActivateTreeOnThread(LayerTreeHostImpl
* host_impl
) override
{
1418 host_impl
->active_tree()->root_layer()->children()[0]->ReleaseResources();
1422 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate
);
1424 class TextureLayerWithMailboxMainThreadDeleted
: public LayerTreeTest
{
1426 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1427 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1428 EXPECT_FALSE(lost_resource
);
1433 void SetMailbox(char mailbox_char
) {
1434 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1435 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1437 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback
,
1438 base::Unretained(this)));
1439 layer_
->SetTextureMailbox(
1440 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1444 void SetupTree() override
{
1445 gfx::Size
bounds(100, 100);
1446 root_
= Layer::Create();
1447 root_
->SetBounds(bounds
);
1449 layer_
= TextureLayer::CreateForMailbox(nullptr);
1450 layer_
->SetIsDrawable(true);
1451 layer_
->SetBounds(bounds
);
1453 root_
->AddChild(layer_
);
1454 layer_tree_host()->SetRootLayer(root_
);
1455 layer_tree_host()->SetViewportSize(bounds
);
1458 void BeginTest() override
{
1459 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1461 callback_count_
= 0;
1463 // Set the mailbox on the main thread.
1465 EXPECT_EQ(0, callback_count_
);
1467 PostSetNeedsCommitToMainThread();
1470 void DidCommitAndDrawFrame() override
{
1471 switch (layer_tree_host()->source_frame_number()) {
1473 // Delete the TextureLayer on the main thread while the mailbox is in
1475 layer_
->RemoveFromParent();
1481 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1484 base::ThreadChecker main_thread_
;
1485 int callback_count_
;
1486 scoped_refptr
<Layer
> root_
;
1487 scoped_refptr
<TextureLayer
> layer_
;
1490 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1491 TextureLayerWithMailboxMainThreadDeleted
);
1493 class TextureLayerWithMailboxImplThreadDeleted
: public LayerTreeTest
{
1495 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1496 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1497 EXPECT_FALSE(lost_resource
);
1502 void SetMailbox(char mailbox_char
) {
1503 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1504 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1506 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback
,
1507 base::Unretained(this)));
1508 layer_
->SetTextureMailbox(
1509 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1513 void SetupTree() override
{
1514 gfx::Size
bounds(100, 100);
1515 root_
= Layer::Create();
1516 root_
->SetBounds(bounds
);
1518 layer_
= TextureLayer::CreateForMailbox(nullptr);
1519 layer_
->SetIsDrawable(true);
1520 layer_
->SetBounds(bounds
);
1522 root_
->AddChild(layer_
);
1523 layer_tree_host()->SetRootLayer(root_
);
1524 layer_tree_host()->SetViewportSize(bounds
);
1527 void BeginTest() override
{
1528 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1530 callback_count_
= 0;
1532 // Set the mailbox on the main thread.
1534 EXPECT_EQ(0, callback_count_
);
1536 PostSetNeedsCommitToMainThread();
1539 void DidCommitAndDrawFrame() override
{
1540 switch (layer_tree_host()->source_frame_number()) {
1542 // Remove the TextureLayer on the main thread while the mailbox is in
1543 // the impl tree, but don't delete the TextureLayer until after the impl
1544 // tree side is deleted.
1545 layer_
->RemoveFromParent();
1553 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1556 base::ThreadChecker main_thread_
;
1557 int callback_count_
;
1558 scoped_refptr
<Layer
> root_
;
1559 scoped_refptr
<TextureLayer
> layer_
;
1562 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1563 TextureLayerWithMailboxImplThreadDeleted
);