1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/layers/texture_layer.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/thread.h"
14 #include "base/time/time.h"
15 #include "cc/layers/solid_color_layer.h"
16 #include "cc/layers/texture_layer_client.h"
17 #include "cc/layers/texture_layer_impl.h"
18 #include "cc/output/compositor_frame_ack.h"
19 #include "cc/output/context_provider.h"
20 #include "cc/resources/returned_resource.h"
21 #include "cc/test/fake_impl_proxy.h"
22 #include "cc/test/fake_layer_tree_host_client.h"
23 #include "cc/test/fake_layer_tree_host_impl.h"
24 #include "cc/test/fake_output_surface.h"
25 #include "cc/test/layer_test_common.h"
26 #include "cc/test/layer_tree_test.h"
27 #include "cc/test/test_web_graphics_context_3d.h"
28 #include "cc/trees/blocking_task_runner.h"
29 #include "cc/trees/layer_tree_host.h"
30 #include "cc/trees/layer_tree_impl.h"
31 #include "cc/trees/single_thread_proxy.h"
32 #include "gpu/GLES2/gl2extchromium.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "testing/gtest/include/gtest/gtest.h"
36 using ::testing::Mock
;
38 using ::testing::AtLeast
;
39 using ::testing::AnyNumber
;
40 using ::testing::InvokeWithoutArgs
;
45 gpu::Mailbox
MailboxFromChar(char value
) {
47 memset(mailbox
.name
, value
, sizeof(mailbox
.name
));
51 class MockLayerTreeHost
: public LayerTreeHost
{
53 explicit MockLayerTreeHost(FakeLayerTreeHostClient
* client
)
54 : LayerTreeHost(client
, nullptr, nullptr, LayerTreeSettings()) {
55 InitializeSingleThreaded(client
,
56 base::MessageLoopProxy::current(),
60 MOCK_METHOD0(SetNeedsCommit
, void());
61 MOCK_METHOD0(SetNeedsUpdateLayers
, void());
62 MOCK_METHOD0(StartRateLimiter
, void());
63 MOCK_METHOD0(StopRateLimiter
, void());
66 class FakeTextureLayerClient
: public TextureLayerClient
{
68 FakeTextureLayerClient() : mailbox_changed_(true) {}
70 bool PrepareTextureMailbox(
71 TextureMailbox
* mailbox
,
72 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
73 bool use_shared_memory
) override
{
74 if (!mailbox_changed_
)
78 *release_callback
= release_callback_
.Pass();
79 mailbox_changed_
= false;
83 void set_mailbox(const TextureMailbox
& mailbox
,
84 scoped_ptr
<SingleReleaseCallback
> release_callback
) {
86 release_callback_
= release_callback
.Pass();
87 mailbox_changed_
= true;
91 TextureMailbox mailbox_
;
92 scoped_ptr
<SingleReleaseCallback
> release_callback_
;
93 bool mailbox_changed_
;
94 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient
);
97 class MockMailboxCallback
{
100 void(const gpu::Mailbox
& mailbox
,
102 bool lost_resource
));
103 MOCK_METHOD3(Release2
,
104 void(SharedBitmap
* shared_bitmap
,
106 bool lost_resource
));
107 MOCK_METHOD4(ReleaseImpl
,
108 void(const gpu::Mailbox
& mailbox
,
111 BlockingTaskRunner
* main_thread_task_runner
));
112 MOCK_METHOD4(ReleaseImpl2
,
113 void(SharedBitmap
* shared_bitmap
,
116 BlockingTaskRunner
* main_thread_task_runner
));
119 struct CommonMailboxObjects
{
120 explicit CommonMailboxObjects(SharedBitmapManager
* manager
)
121 : mailbox_name1_(MailboxFromChar('1')),
122 mailbox_name2_(MailboxFromChar('2')),
125 release_mailbox1_
= base::Bind(&MockMailboxCallback::Release
,
126 base::Unretained(&mock_callback_
),
128 release_mailbox2_
= base::Bind(&MockMailboxCallback::Release
,
129 base::Unretained(&mock_callback_
),
131 release_mailbox1_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
132 base::Unretained(&mock_callback_
),
134 release_mailbox2_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
135 base::Unretained(&mock_callback_
),
137 const uint32 arbitrary_target1
= GL_TEXTURE_2D
;
138 const uint32 arbitrary_target2
= GL_TEXTURE_EXTERNAL_OES
;
139 mailbox1_
= TextureMailbox(mailbox_name1_
, arbitrary_target1
, sync_point1_
);
140 mailbox2_
= TextureMailbox(mailbox_name2_
, arbitrary_target2
, sync_point2_
);
141 gfx::Size
size(128, 128);
142 shared_bitmap_
= manager
->AllocateSharedBitmap(size
);
143 DCHECK(shared_bitmap_
);
145 base::Bind(&MockMailboxCallback::Release2
,
146 base::Unretained(&mock_callback_
), shared_bitmap_
.get());
147 release_mailbox3_impl_
=
148 base::Bind(&MockMailboxCallback::ReleaseImpl2
,
149 base::Unretained(&mock_callback_
), shared_bitmap_
.get());
150 mailbox3_
= TextureMailbox(shared_bitmap_
.get(), size
);
153 gpu::Mailbox mailbox_name1_
;
154 gpu::Mailbox mailbox_name2_
;
155 MockMailboxCallback mock_callback_
;
156 ReleaseCallback release_mailbox1_
;
157 ReleaseCallback release_mailbox2_
;
158 ReleaseCallback release_mailbox3_
;
159 ReleaseCallbackImpl release_mailbox1_impl_
;
160 ReleaseCallbackImpl release_mailbox2_impl_
;
161 ReleaseCallbackImpl release_mailbox3_impl_
;
162 TextureMailbox mailbox1_
;
163 TextureMailbox mailbox2_
;
164 TextureMailbox mailbox3_
;
167 scoped_ptr
<SharedBitmap
> shared_bitmap_
;
170 class TextureLayerTest
: public testing::Test
{
174 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)),
175 host_impl_(&proxy_
, &shared_bitmap_manager_
),
176 test_data_(&shared_bitmap_manager_
) {}
179 void SetUp() override
{
180 layer_tree_host_
.reset(new MockLayerTreeHost(&fake_client_
));
181 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
182 layer_tree_host_
->SetViewportSize(gfx::Size(10, 10));
183 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
186 void TearDown() override
{
187 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
188 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
190 layer_tree_host_
->SetRootLayer(nullptr);
191 layer_tree_host_
= nullptr;
194 scoped_ptr
<MockLayerTreeHost
> layer_tree_host_
;
195 FakeImplProxy proxy_
;
196 FakeLayerTreeHostClient fake_client_
;
197 TestSharedBitmapManager shared_bitmap_manager_
;
198 FakeLayerTreeHostImpl host_impl_
;
199 CommonMailboxObjects test_data_
;
202 TEST_F(TextureLayerTest
, CheckPropertyChangeCausesCorrectBehavior
) {
203 scoped_refptr
<TextureLayer
> test_layer
=
204 TextureLayer::CreateForMailbox(nullptr);
205 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_
->SetRootLayer(test_layer
));
207 // Test properties that should call SetNeedsCommit. All properties need to
208 // be set to new values in order for SetNeedsCommit to be called.
209 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetFlipped(false));
210 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetNearestNeighbor(true));
211 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetUV(
212 gfx::PointF(0.25f
, 0.25f
), gfx::PointF(0.75f
, 0.75f
)));
213 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetVertexOpacity(
214 0.5f
, 0.5f
, 0.5f
, 0.5f
));
215 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetPremultipliedAlpha(false));
216 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetBlendBackgroundColor(true));
219 TEST_F(TextureLayerTest
, VisibleContentOpaqueRegion
) {
220 const gfx::Size
layer_bounds(100, 100);
221 const gfx::Rect
layer_rect(layer_bounds
);
222 const Region
layer_region(layer_rect
);
224 scoped_refptr
<TextureLayer
> layer
= TextureLayer::CreateForMailbox(nullptr);
225 layer
->SetBounds(layer_bounds
);
226 layer
->draw_properties().visible_content_rect
= layer_rect
;
227 layer
->SetBlendBackgroundColor(true);
229 // Verify initial conditions.
230 EXPECT_FALSE(layer
->contents_opaque());
231 EXPECT_EQ(0u, layer
->background_color());
232 EXPECT_EQ(Region().ToString(),
233 layer
->VisibleContentOpaqueRegion().ToString());
235 // Opaque background.
236 layer
->SetBackgroundColor(SK_ColorWHITE
);
237 EXPECT_EQ(layer_region
.ToString(),
238 layer
->VisibleContentOpaqueRegion().ToString());
240 // Transparent background.
241 layer
->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
242 EXPECT_EQ(Region().ToString(),
243 layer
->VisibleContentOpaqueRegion().ToString());
246 TEST_F(TextureLayerTest
, RateLimiter
) {
247 FakeTextureLayerClient client
;
248 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(
250 test_layer
->SetIsDrawable(true);
251 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
252 layer_tree_host_
->SetRootLayer(test_layer
);
254 // Don't rate limit until we invalidate.
255 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
256 test_layer
->SetRateLimitContext(true);
257 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
259 // Do rate limit after we invalidate.
260 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
261 test_layer
->SetNeedsDisplay();
262 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
264 // Stop rate limiter when we don't want it any more.
265 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
266 test_layer
->SetRateLimitContext(false);
267 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
269 // Or we clear the client.
270 test_layer
->SetRateLimitContext(true);
271 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
272 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
273 test_layer
->ClearClient();
274 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
276 // Reset to a layer with a client, that started the rate limiter.
277 test_layer
= TextureLayer::CreateForMailbox(
279 test_layer
->SetIsDrawable(true);
280 test_layer
->SetRateLimitContext(true);
281 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
282 layer_tree_host_
->SetRootLayer(test_layer
);
283 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
284 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
285 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
286 test_layer
->SetNeedsDisplay();
287 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
289 // Stop rate limiter when we're removed from the tree.
290 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
291 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(1);
292 layer_tree_host_
->SetRootLayer(nullptr);
293 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
296 class TestMailboxHolder
: public TextureLayer::TextureMailboxHolder
{
298 using TextureLayer::TextureMailboxHolder::Create
;
301 ~TestMailboxHolder() override
{}
304 class TextureLayerWithMailboxTest
: public TextureLayerTest
{
306 void TearDown() override
{
307 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
308 EXPECT_CALL(test_data_
.mock_callback_
,
309 Release(test_data_
.mailbox_name1_
,
310 test_data_
.sync_point1_
,
312 TextureLayerTest::TearDown();
316 TEST_F(TextureLayerWithMailboxTest
, ReplaceMailboxOnMainThreadBeforeCommit
) {
317 scoped_refptr
<TextureLayer
> test_layer
=
318 TextureLayer::CreateForMailbox(nullptr);
319 ASSERT_TRUE(test_layer
.get());
321 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
322 layer_tree_host_
->SetRootLayer(test_layer
);
323 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
325 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
326 test_layer
->SetTextureMailbox(
327 test_data_
.mailbox1_
,
328 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
329 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
331 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
332 EXPECT_CALL(test_data_
.mock_callback_
,
333 Release(test_data_
.mailbox_name1_
,
334 test_data_
.sync_point1_
,
337 test_layer
->SetTextureMailbox(
338 test_data_
.mailbox2_
,
339 SingleReleaseCallback::Create(test_data_
.release_mailbox2_
));
340 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
341 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
343 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
344 EXPECT_CALL(test_data_
.mock_callback_
,
345 Release(test_data_
.mailbox_name2_
,
346 test_data_
.sync_point2_
,
349 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
350 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
351 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
353 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
354 test_layer
->SetTextureMailbox(
355 test_data_
.mailbox3_
,
356 SingleReleaseCallback::Create(test_data_
.release_mailbox3_
));
357 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
358 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
360 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
361 EXPECT_CALL(test_data_
.mock_callback_
,
362 Release2(test_data_
.shared_bitmap_
.get(), 0, false)).Times(1);
363 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
364 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
365 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
368 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
369 test_layer
->SetTextureMailbox(
370 test_data_
.mailbox1_
,
371 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
374 TEST_F(TextureLayerTest
, SetTextureMailboxWithoutReleaseCallback
) {
375 scoped_refptr
<TextureLayer
> test_layer
=
376 TextureLayer::CreateForMailbox(nullptr);
377 ASSERT_TRUE(test_layer
.get());
379 // These use the same gpu::Mailbox, but different sync points.
380 TextureMailbox
mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D
, 1);
381 TextureMailbox
mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D
, 2);
383 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
384 layer_tree_host_
->SetRootLayer(test_layer
);
385 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
387 // Set the mailbox the first time. It should cause a commit.
388 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
389 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox1
);
390 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
392 // Set the mailbox again with a new sync point, as the backing texture has
393 // been updated. It should cause a new commit.
394 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
395 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox2
);
396 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
399 class TextureLayerMailboxHolderTest
: public TextureLayerTest
{
401 TextureLayerMailboxHolderTest()
402 : main_thread_("MAIN") {
403 main_thread_
.Start();
404 main_thread_
.message_loop()->PostTask(
406 base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain
,
407 base::Unretained(this)));
411 void Wait(const base::Thread
& thread
) {
412 bool manual_reset
= false;
413 bool initially_signaled
= false;
414 base::WaitableEvent
event(manual_reset
, initially_signaled
);
415 thread
.message_loop()->PostTask(
417 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
421 void CreateMainRef() {
422 main_ref_
= TestMailboxHolder::Create(
423 test_data_
.mailbox1_
,
424 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
)).Pass();
427 void ReleaseMainRef() { main_ref_
= nullptr; }
429 void CreateImplRef(scoped_ptr
<SingleReleaseCallbackImpl
>* impl_ref
) {
430 *impl_ref
= main_ref_
->holder()->GetCallbackForImplThread();
433 void CapturePostTasksAndWait(base::WaitableEvent
* begin_capture
,
434 base::WaitableEvent
* wait_for_capture
,
435 base::WaitableEvent
* stop_capture
) {
436 begin_capture
->Wait();
437 BlockingTaskRunner::CapturePostTasks
capture(
438 main_thread_task_runner_
.get());
439 wait_for_capture
->Signal();
440 stop_capture
->Wait();
444 void InitializeOnMain() {
445 main_thread_task_runner_
=
446 BlockingTaskRunner::Create(main_thread_
.message_loop_proxy());
449 scoped_ptr
<TestMailboxHolder::MainThreadReference
>
451 base::Thread main_thread_
;
452 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
455 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_BothReleaseThenMain
) {
456 scoped_refptr
<TextureLayer
> test_layer
=
457 TextureLayer::CreateForMailbox(nullptr);
458 ASSERT_TRUE(test_layer
.get());
460 main_thread_
.message_loop()->PostTask(
462 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
463 base::Unretained(this)));
467 // The texture layer is attached to compositor1, and passes a reference to its
469 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
470 main_thread_
.message_loop()->PostTask(
472 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
473 base::Unretained(this),
476 // Then the texture layer is removed and attached to compositor2, and passes a
477 // reference to its impl tree.
478 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
479 main_thread_
.message_loop()->PostTask(
481 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
482 base::Unretained(this),
486 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
488 // The compositors both destroy their impl trees before the main thread layer
490 compositor1
->Run(100, false, main_thread_task_runner_
.get());
491 compositor2
->Run(200, false, main_thread_task_runner_
.get());
495 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
496 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
498 // The main thread ref is the last one, so the mailbox is released back to the
499 // embedder, with the last sync point provided by the impl trees.
500 EXPECT_CALL(test_data_
.mock_callback_
,
501 Release(test_data_
.mailbox_name1_
, 200, false)).Times(1);
503 main_thread_
.message_loop()->PostTask(
505 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
506 base::Unretained(this)));
508 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
511 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleaseBetween
) {
512 scoped_refptr
<TextureLayer
> test_layer
=
513 TextureLayer::CreateForMailbox(nullptr);
514 ASSERT_TRUE(test_layer
.get());
516 main_thread_
.message_loop()->PostTask(
518 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
519 base::Unretained(this)));
523 // The texture layer is attached to compositor1, and passes a reference to its
525 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
526 main_thread_
.message_loop()->PostTask(
528 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
529 base::Unretained(this),
532 // Then the texture layer is removed and attached to compositor2, and passes a
533 // reference to its impl tree.
534 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
535 main_thread_
.message_loop()->PostTask(
537 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
538 base::Unretained(this),
542 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
544 // One compositor destroys their impl tree.
545 compositor1
->Run(100, false, main_thread_task_runner_
.get());
547 // Then the main thread reference is destroyed.
548 main_thread_
.message_loop()->PostTask(
550 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
551 base::Unretained(this)));
555 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
556 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
558 // The second impl reference is destroyed last, causing the mailbox to be
559 // released back to the embedder with the last sync point from the impl tree.
560 EXPECT_CALL(test_data_
.mock_callback_
,
561 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
563 compositor2
->Run(200, true, main_thread_task_runner_
.get());
565 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
568 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleasedFirst
) {
569 scoped_refptr
<TextureLayer
> test_layer
=
570 TextureLayer::CreateForMailbox(nullptr);
571 ASSERT_TRUE(test_layer
.get());
573 main_thread_
.message_loop()->PostTask(
575 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
576 base::Unretained(this)));
580 // The texture layer is attached to compositor1, and passes a reference to its
582 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
583 main_thread_
.message_loop()->PostTask(
585 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
586 base::Unretained(this),
589 // Then the texture layer is removed and attached to compositor2, and passes a
590 // reference to its impl tree.
591 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
592 main_thread_
.message_loop()->PostTask(
594 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
595 base::Unretained(this),
599 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
601 // The main thread reference is destroyed first.
602 main_thread_
.message_loop()->PostTask(
604 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
605 base::Unretained(this)));
607 // One compositor destroys their impl tree.
608 compositor2
->Run(200, false, main_thread_task_runner_
.get());
612 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
613 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
615 // The second impl reference is destroyed last, causing the mailbox to be
616 // released back to the embedder with the last sync point from the impl tree.
617 EXPECT_CALL(test_data_
.mock_callback_
,
618 Release(test_data_
.mailbox_name1_
, 100, true)).Times(1);
620 compositor1
->Run(100, true, main_thread_task_runner_
.get());
622 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
625 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_SecondImplRefShortcut
) {
626 scoped_refptr
<TextureLayer
> test_layer
=
627 TextureLayer::CreateForMailbox(nullptr);
628 ASSERT_TRUE(test_layer
.get());
630 main_thread_
.message_loop()->PostTask(
632 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
633 base::Unretained(this)));
637 // The texture layer is attached to compositor1, and passes a reference to its
639 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
640 main_thread_
.message_loop()->PostTask(
642 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
643 base::Unretained(this),
646 // Then the texture layer is removed and attached to compositor2, and passes a
647 // reference to its impl tree.
648 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
649 main_thread_
.message_loop()->PostTask(
651 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
652 base::Unretained(this),
656 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
658 // The main thread reference is destroyed first.
659 main_thread_
.message_loop()->PostTask(
661 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
662 base::Unretained(this)));
664 EXPECT_CALL(test_data_
.mock_callback_
,
665 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
667 bool manual_reset
= false;
668 bool initially_signaled
= false;
669 base::WaitableEvent
begin_capture(manual_reset
, initially_signaled
);
670 base::WaitableEvent
wait_for_capture(manual_reset
, initially_signaled
);
671 base::WaitableEvent
stop_capture(manual_reset
, initially_signaled
);
673 // Post a task to start capturing tasks on the main thread. This will block
674 // the main thread until we signal the |stop_capture| event.
675 main_thread_
.message_loop()->PostTask(
677 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait
,
678 base::Unretained(this),
683 // Before the main thread capturing starts, one compositor destroys their
684 // impl reference. Since capturing did not start, this gets post-tasked to
686 compositor1
->Run(100, false, main_thread_task_runner_
.get());
688 // Start capturing on the main thread.
689 begin_capture
.Signal();
690 wait_for_capture
.Wait();
692 // Meanwhile, the second compositor released its impl reference, but this task
693 // gets shortcutted directly to the main thread. This means the reference is
694 // released before compositor1, whose reference will be released later when
695 // the post-task is serviced. But since it was destroyed _on the impl thread_
696 // last, its sync point values should be used.
697 compositor2
->Run(200, true, main_thread_task_runner_
.get());
699 stop_capture
.Signal();
702 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
705 class TextureLayerImplWithMailboxThreadedCallback
: public LayerTreeTest
{
707 TextureLayerImplWithMailboxThreadedCallback()
708 : callback_count_(0),
711 // Make sure callback is received on main and doesn't block the impl thread.
712 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
713 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
714 EXPECT_FALSE(lost_resource
);
718 void SetMailbox(char mailbox_char
) {
719 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
720 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
722 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback
,
723 base::Unretained(this)));
724 layer_
->SetTextureMailbox(
725 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
729 void BeginTest() override
{
730 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
732 gfx::Size
bounds(100, 100);
733 root_
= Layer::Create();
734 root_
->SetBounds(bounds
);
736 layer_
= TextureLayer::CreateForMailbox(nullptr);
737 layer_
->SetIsDrawable(true);
738 layer_
->SetBounds(bounds
);
740 root_
->AddChild(layer_
);
741 layer_tree_host()->SetRootLayer(root_
);
742 layer_tree_host()->SetViewportSize(bounds
);
744 EXPECT_EQ(0, callback_count_
);
746 // Case #1: change mailbox before the commit. The old mailbox should be
747 // released immediately.
749 EXPECT_EQ(1, callback_count_
);
750 PostSetNeedsCommitToMainThread();
753 void DidCommit() override
{
755 switch (commit_count_
) {
757 // Case #2: change mailbox after the commit (and draw), where the
758 // layer draws. The old mailbox should be released during the next
761 EXPECT_EQ(1, callback_count_
);
764 EXPECT_EQ(2, callback_count_
);
765 // Case #3: change mailbox when the layer doesn't draw. The old
766 // mailbox should be released during the next commit.
767 layer_
->SetBounds(gfx::Size());
771 EXPECT_EQ(3, callback_count_
);
772 // Case #4: release mailbox that was committed but never drawn. The
773 // old mailbox should be released during the next commit.
774 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
777 if (layer_tree_host()->settings().impl_side_painting
) {
778 // With impl painting, the texture mailbox will still be on the impl
779 // thread when the commit finishes, because the layer is not drawble
780 // when it has no texture mailbox, and thus does not block the commit
781 // on activation. So, we wait for activation.
782 // TODO(danakj): fix this. crbug.com/277953
783 layer_tree_host()->SetNeedsCommit();
789 EXPECT_EQ(4, callback_count_
);
790 // Restore a mailbox for the next step.
794 // Case #5: remove layer from tree. Callback should *not* be called, the
795 // mailbox is returned to the main thread.
796 EXPECT_EQ(4, callback_count_
);
797 layer_
->RemoveFromParent();
800 if (layer_tree_host()->settings().impl_side_painting
) {
801 // With impl painting, the texture mailbox will still be on the impl
802 // thread when the commit finishes, because the layer is not around to
803 // block the commit on activation anymore. So, we wait for activation.
804 // TODO(danakj): fix this. crbug.com/277953
805 layer_tree_host()->SetNeedsCommit();
811 EXPECT_EQ(4, callback_count_
);
812 // Resetting the mailbox will call the callback now.
813 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
814 EXPECT_EQ(5, callback_count_
);
823 void AfterTest() override
{}
826 base::ThreadChecker main_thread_
;
829 scoped_refptr
<Layer
> root_
;
830 scoped_refptr
<TextureLayer
> layer_
;
833 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
834 TextureLayerImplWithMailboxThreadedCallback
);
837 class TextureLayerMailboxIsActivatedDuringCommit
: public LayerTreeTest
{
839 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
841 static void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {}
843 void SetMailbox(char mailbox_char
) {
844 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
846 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback
));
847 layer_
->SetTextureMailbox(
848 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
852 void BeginTest() override
{
853 gfx::Size
bounds(100, 100);
854 root_
= Layer::Create();
855 root_
->SetBounds(bounds
);
857 layer_
= TextureLayer::CreateForMailbox(nullptr);
858 layer_
->SetIsDrawable(true);
859 layer_
->SetBounds(bounds
);
861 root_
->AddChild(layer_
);
862 layer_tree_host()->SetRootLayer(root_
);
863 layer_tree_host()->SetViewportSize(bounds
);
866 PostSetNeedsCommitToMainThread();
869 void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
873 void DidCommit() override
{
874 switch (layer_tree_host()->source_frame_number()) {
876 // The first mailbox has been activated. Set a new mailbox, and
877 // expect the next commit to finish *after* it is activated.
881 // The second mailbox has been activated. Remove the layer from
882 // the tree to cause another commit/activation. The commit should
883 // finish *after* the layer is removed from the active tree.
884 layer_
->RemoveFromParent();
892 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
893 switch (host_impl
->active_tree()->source_frame_number()) {
895 // The activate for the 1st mailbox should have happened before now.
896 EXPECT_EQ(1, activate_count_
);
900 // The activate for the 2nd mailbox should have happened before now.
901 EXPECT_EQ(2, activate_count_
);
905 // The activate to remove the layer should have happened before now.
906 EXPECT_EQ(3, activate_count_
);
916 void AfterTest() override
{}
919 scoped_refptr
<Layer
> root_
;
920 scoped_refptr
<TextureLayer
> layer_
;
923 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
924 TextureLayerMailboxIsActivatedDuringCommit
);
926 class TextureLayerImplWithMailboxTest
: public TextureLayerTest
{
928 TextureLayerImplWithMailboxTest()
930 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)) {}
932 void SetUp() override
{
933 TextureLayerTest::SetUp();
934 layer_tree_host_
.reset(new MockLayerTreeHost(&fake_client_
));
935 EXPECT_TRUE(host_impl_
.InitializeRenderer(FakeOutputSurface::Create3d()));
938 bool WillDraw(TextureLayerImpl
* layer
, DrawMode mode
) {
939 bool will_draw
= layer
->WillDraw(
940 mode
, host_impl_
.active_tree()->resource_provider());
942 layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
946 FakeLayerTreeHostClient fake_client_
;
949 // Test conditions for results of TextureLayerImpl::WillDraw under
950 // different configurations of different mailbox, texture_id, and draw_mode.
951 TEST_F(TextureLayerImplWithMailboxTest
, TestWillDraw
) {
953 test_data_
.mock_callback_
,
954 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
956 EXPECT_CALL(test_data_
.mock_callback_
,
957 ReleaseImpl2(test_data_
.shared_bitmap_
.get(), 0, false, _
))
961 scoped_ptr
<TextureLayerImpl
> impl_layer
=
962 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
963 impl_layer
->SetTextureMailbox(
964 test_data_
.mailbox1_
,
965 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
966 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
970 scoped_ptr
<TextureLayerImpl
> impl_layer
=
971 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
972 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
973 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
977 // Software resource.
978 scoped_ptr
<TextureLayerImpl
> impl_layer
=
979 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
980 impl_layer
->SetTextureMailbox(
981 test_data_
.mailbox3_
,
982 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
983 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
988 scoped_ptr
<TextureLayerImpl
> impl_layer
=
989 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
990 impl_layer
->SetTextureMailbox(
991 test_data_
.mailbox1_
,
992 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
993 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
997 scoped_ptr
<TextureLayerImpl
> impl_layer
=
998 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
999 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1000 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
1004 // Software resource.
1005 scoped_ptr
<TextureLayerImpl
> impl_layer
=
1006 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1007 impl_layer
->SetTextureMailbox(
1008 test_data_
.mailbox3_
,
1009 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
1010 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
1013 // Resourceless software mode.
1015 scoped_ptr
<TextureLayerImpl
> impl_layer
=
1016 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1017 impl_layer
->SetTextureMailbox(
1018 test_data_
.mailbox1_
,
1019 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1020 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_RESOURCELESS_SOFTWARE
));
1024 TEST_F(TextureLayerImplWithMailboxTest
, TestImplLayerCallbacks
) {
1025 host_impl_
.CreatePendingTree();
1026 scoped_ptr
<TextureLayerImpl
> pending_layer
;
1027 pending_layer
= TextureLayerImpl::Create(host_impl_
.pending_tree(), 1);
1028 ASSERT_TRUE(pending_layer
);
1030 scoped_ptr
<LayerImpl
> active_layer(
1031 pending_layer
->CreateLayerImpl(host_impl_
.active_tree()));
1032 ASSERT_TRUE(active_layer
);
1034 pending_layer
->SetTextureMailbox(
1035 test_data_
.mailbox1_
,
1036 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1038 // Test multiple commits without an activation.
1040 test_data_
.mock_callback_
,
1041 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1043 pending_layer
->SetTextureMailbox(
1044 test_data_
.mailbox2_
,
1045 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox2_impl_
));
1046 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1048 // Test callback after activation.
1049 pending_layer
->PushPropertiesTo(active_layer
.get());
1050 active_layer
->DidBecomeActive();
1052 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1053 pending_layer
->SetTextureMailbox(
1054 test_data_
.mailbox1_
,
1055 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1056 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1058 EXPECT_CALL(test_data_
.mock_callback_
,
1059 ReleaseImpl(test_data_
.mailbox_name2_
, _
, false, _
)).Times(1);
1060 pending_layer
->PushPropertiesTo(active_layer
.get());
1061 active_layer
->DidBecomeActive();
1062 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1064 // Test resetting the mailbox.
1065 EXPECT_CALL(test_data_
.mock_callback_
,
1066 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1067 pending_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1068 pending_layer
->PushPropertiesTo(active_layer
.get());
1069 active_layer
->DidBecomeActive();
1070 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1074 test_data_
.mock_callback_
,
1075 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1077 pending_layer
->SetTextureMailbox(
1078 test_data_
.mailbox1_
,
1079 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1082 TEST_F(TextureLayerImplWithMailboxTest
,
1083 TestDestructorCallbackOnCreatedResource
) {
1084 scoped_ptr
<TextureLayerImpl
> impl_layer
;
1085 impl_layer
= TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1086 ASSERT_TRUE(impl_layer
);
1088 EXPECT_CALL(test_data_
.mock_callback_
,
1089 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1090 impl_layer
->SetTextureMailbox(
1091 test_data_
.mailbox1_
,
1092 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1093 impl_layer
->DidBecomeActive();
1094 EXPECT_TRUE(impl_layer
->WillDraw(
1095 DRAW_MODE_HARDWARE
, host_impl_
.active_tree()->resource_provider()));
1096 impl_layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
1097 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1100 TEST_F(TextureLayerImplWithMailboxTest
, TestCallbackOnInUseResource
) {
1101 ResourceProvider
* provider
= host_impl_
.active_tree()->resource_provider();
1102 ResourceProvider::ResourceId id
= provider
->CreateResourceFromTextureMailbox(
1103 test_data_
.mailbox1_
,
1104 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1105 provider
->AllocateForTesting(id
);
1107 // Transfer some resources to the parent.
1108 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1109 resource_ids_to_transfer
.push_back(id
);
1110 TransferableResourceArray list
;
1111 provider
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1112 EXPECT_TRUE(provider
->InUseByConsumer(id
));
1113 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1114 provider
->DeleteResource(id
);
1115 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1116 EXPECT_CALL(test_data_
.mock_callback_
,
1117 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1118 ReturnedResourceArray returned
;
1119 TransferableResource::ReturnResources(list
, &returned
);
1120 provider
->ReceiveReturnsFromParent(returned
);
1123 // Checks that TextureLayer::Update does not cause an extra commit when setting
1124 // the texture mailbox.
1125 class TextureLayerNoExtraCommitForMailboxTest
1126 : public LayerTreeTest
,
1127 public TextureLayerClient
{
1129 // TextureLayerClient implementation.
1130 bool PrepareTextureMailbox(
1131 TextureMailbox
* texture_mailbox
,
1132 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1133 bool use_shared_memory
) override
{
1134 if (layer_tree_host()->source_frame_number() == 1) {
1135 // Once this has been committed, the mailbox will be released.
1136 *texture_mailbox
= TextureMailbox();
1140 *texture_mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1141 *release_callback
= SingleReleaseCallback::Create(
1142 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased
,
1143 base::Unretained(this)));
1147 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1148 // Source frame number during callback is the same as the source frame
1149 // on which it was released.
1150 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1154 void SetupTree() override
{
1155 scoped_refptr
<Layer
> root
= Layer::Create();
1156 root
->SetBounds(gfx::Size(10, 10));
1157 root
->SetIsDrawable(true);
1159 texture_layer_
= TextureLayer::CreateForMailbox(this);
1160 texture_layer_
->SetBounds(gfx::Size(10, 10));
1161 texture_layer_
->SetIsDrawable(true);
1162 root
->AddChild(texture_layer_
);
1164 layer_tree_host()->SetRootLayer(root
);
1165 LayerTreeTest::SetupTree();
1168 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1170 void DidCommitAndDrawFrame() override
{
1171 switch (layer_tree_host()->source_frame_number()) {
1173 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1174 // Invalidate the texture layer to clear the mailbox before
1176 texture_layer_
->SetNeedsDisplay();
1186 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1187 ASSERT_TRUE(result
);
1188 DelegatedFrameData
* delegated_frame_data
=
1189 output_surface()->last_sent_frame().delegated_frame_data
.get();
1190 if (!delegated_frame_data
)
1193 // Return all resources immediately.
1194 TransferableResourceArray resources_to_return
=
1195 output_surface()->resources_held_by_parent();
1197 CompositorFrameAck ack
;
1198 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1199 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1200 host_impl
->ReclaimResources(&ack
);
1203 void AfterTest() override
{}
1206 scoped_refptr
<TextureLayer
> texture_layer_
;
1209 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest
);
1211 // Checks that changing a mailbox in the client for a TextureLayer that's
1212 // invisible correctly works and uses the new mailbox as soon as the layer
1213 // becomes visible (and returns the old one).
1214 class TextureLayerChangeInvisibleMailboxTest
1215 : public LayerTreeTest
,
1216 public TextureLayerClient
{
1218 TextureLayerChangeInvisibleMailboxTest()
1219 : mailbox_changed_(true),
1220 mailbox_returned_(0),
1223 mailbox_
= MakeMailbox('1');
1226 // TextureLayerClient implementation.
1227 bool PrepareTextureMailbox(
1228 TextureMailbox
* mailbox
,
1229 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1230 bool use_shared_memory
) override
{
1232 if (!mailbox_changed_
)
1234 *mailbox
= mailbox_
;
1235 *release_callback
= SingleReleaseCallback::Create(
1236 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased
,
1237 base::Unretained(this)));
1241 TextureMailbox
MakeMailbox(char name
) {
1242 return TextureMailbox(MailboxFromChar(name
), GL_TEXTURE_2D
, 0);
1245 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1246 ++mailbox_returned_
;
1249 void SetupTree() override
{
1250 scoped_refptr
<Layer
> root
= Layer::Create();
1251 root
->SetBounds(gfx::Size(10, 10));
1252 root
->SetIsDrawable(true);
1254 solid_layer_
= SolidColorLayer::Create();
1255 solid_layer_
->SetBounds(gfx::Size(10, 10));
1256 solid_layer_
->SetIsDrawable(true);
1257 solid_layer_
->SetBackgroundColor(SK_ColorWHITE
);
1258 root
->AddChild(solid_layer_
);
1260 parent_layer_
= Layer::Create();
1261 parent_layer_
->SetBounds(gfx::Size(10, 10));
1262 parent_layer_
->SetIsDrawable(true);
1263 root
->AddChild(parent_layer_
);
1265 texture_layer_
= TextureLayer::CreateForMailbox(this);
1266 texture_layer_
->SetBounds(gfx::Size(10, 10));
1267 texture_layer_
->SetIsDrawable(true);
1268 parent_layer_
->AddChild(texture_layer_
);
1270 layer_tree_host()->SetRootLayer(root
);
1271 LayerTreeTest::SetupTree();
1274 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1276 void DidCommitAndDrawFrame() override
{
1278 switch (commit_count_
) {
1280 // We should have updated the layer, committing the texture.
1281 EXPECT_EQ(1, prepare_called_
);
1282 // Make layer invisible.
1283 parent_layer_
->SetOpacity(0.f
);
1286 // Layer shouldn't have been updated.
1287 EXPECT_EQ(1, prepare_called_
);
1288 // Change the texture.
1289 mailbox_
= MakeMailbox('2');
1290 mailbox_changed_
= true;
1291 texture_layer_
->SetNeedsDisplay();
1292 // Force a change to make sure we draw a frame.
1293 solid_layer_
->SetBackgroundColor(SK_ColorGRAY
);
1296 // Layer shouldn't have been updated.
1297 EXPECT_EQ(1, prepare_called_
);
1298 // So the old mailbox isn't returned yet.
1299 EXPECT_EQ(0, mailbox_returned_
);
1300 // Make layer visible again.
1301 parent_layer_
->SetOpacity(1.f
);
1304 // Layer should have been updated.
1305 EXPECT_EQ(2, prepare_called_
);
1306 // So the old mailbox should have been returned already.
1307 EXPECT_EQ(1, mailbox_returned_
);
1308 texture_layer_
->ClearClient();
1311 EXPECT_EQ(2, mailbox_returned_
);
1320 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1321 ASSERT_TRUE(result
);
1322 DelegatedFrameData
* delegated_frame_data
=
1323 output_surface()->last_sent_frame().delegated_frame_data
.get();
1324 if (!delegated_frame_data
)
1327 // Return all resources immediately.
1328 TransferableResourceArray resources_to_return
=
1329 output_surface()->resources_held_by_parent();
1331 CompositorFrameAck ack
;
1332 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1333 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1334 host_impl
->ReclaimResources(&ack
);
1337 void AfterTest() override
{}
1340 scoped_refptr
<SolidColorLayer
> solid_layer_
;
1341 scoped_refptr
<Layer
> parent_layer_
;
1342 scoped_refptr
<TextureLayer
> texture_layer_
;
1344 // Used on the main thread.
1345 bool mailbox_changed_
;
1346 TextureMailbox mailbox_
;
1347 int mailbox_returned_
;
1348 int prepare_called_
;
1352 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest
);
1354 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1355 // the mailbox back to TextureLayerClient.
1356 class TextureLayerReleaseResourcesBase
1357 : public LayerTreeTest
,
1358 public TextureLayerClient
{
1360 // TextureLayerClient implementation.
1361 bool PrepareTextureMailbox(
1362 TextureMailbox
* mailbox
,
1363 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1364 bool use_shared_memory
) override
{
1365 *mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1366 *release_callback
= SingleReleaseCallback::Create(
1367 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased
,
1368 base::Unretained(this)));
1372 void MailboxReleased(unsigned sync_point
, bool lost_resource
) {
1373 mailbox_released_
= true;
1376 void SetupTree() override
{
1377 LayerTreeTest::SetupTree();
1379 scoped_refptr
<TextureLayer
> texture_layer
=
1380 TextureLayer::CreateForMailbox(this);
1381 texture_layer
->SetBounds(gfx::Size(10, 10));
1382 texture_layer
->SetIsDrawable(true);
1384 layer_tree_host()->root_layer()->AddChild(texture_layer
);
1387 void BeginTest() override
{
1388 mailbox_released_
= false;
1389 PostSetNeedsCommitToMainThread();
1392 void DidCommitAndDrawFrame() override
{ EndTest(); }
1394 void AfterTest() override
{ EXPECT_TRUE(mailbox_released_
); }
1397 bool mailbox_released_
;
1400 class TextureLayerReleaseResourcesAfterCommit
1401 : public TextureLayerReleaseResourcesBase
{
1403 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
1404 LayerTreeImpl
* tree
= nullptr;
1405 if (host_impl
->settings().impl_side_painting
)
1406 tree
= host_impl
->pending_tree();
1408 tree
= host_impl
->active_tree();
1409 tree
->root_layer()->children()[0]->ReleaseResources();
1413 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit
);
1415 class TextureLayerReleaseResourcesAfterActivate
1416 : public TextureLayerReleaseResourcesBase
{
1418 void DidActivateTreeOnThread(LayerTreeHostImpl
* host_impl
) override
{
1419 host_impl
->active_tree()->root_layer()->children()[0]->ReleaseResources();
1423 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate
);
1425 class TextureLayerWithMailboxMainThreadDeleted
: public LayerTreeTest
{
1427 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1428 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1429 EXPECT_FALSE(lost_resource
);
1434 void SetMailbox(char mailbox_char
) {
1435 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1436 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1438 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback
,
1439 base::Unretained(this)));
1440 layer_
->SetTextureMailbox(
1441 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1445 void SetupTree() override
{
1446 gfx::Size
bounds(100, 100);
1447 root_
= Layer::Create();
1448 root_
->SetBounds(bounds
);
1450 layer_
= TextureLayer::CreateForMailbox(nullptr);
1451 layer_
->SetIsDrawable(true);
1452 layer_
->SetBounds(bounds
);
1454 root_
->AddChild(layer_
);
1455 layer_tree_host()->SetRootLayer(root_
);
1456 layer_tree_host()->SetViewportSize(bounds
);
1459 void BeginTest() override
{
1460 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1462 callback_count_
= 0;
1464 // Set the mailbox on the main thread.
1466 EXPECT_EQ(0, callback_count_
);
1468 PostSetNeedsCommitToMainThread();
1471 void DidCommitAndDrawFrame() override
{
1472 switch (layer_tree_host()->source_frame_number()) {
1474 // Delete the TextureLayer on the main thread while the mailbox is in
1476 layer_
->RemoveFromParent();
1482 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1485 base::ThreadChecker main_thread_
;
1486 int callback_count_
;
1487 scoped_refptr
<Layer
> root_
;
1488 scoped_refptr
<TextureLayer
> layer_
;
1491 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1492 TextureLayerWithMailboxMainThreadDeleted
);
1494 class TextureLayerWithMailboxImplThreadDeleted
: public LayerTreeTest
{
1496 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1497 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1498 EXPECT_FALSE(lost_resource
);
1503 void SetMailbox(char mailbox_char
) {
1504 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1505 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1507 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback
,
1508 base::Unretained(this)));
1509 layer_
->SetTextureMailbox(
1510 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1514 void SetupTree() override
{
1515 gfx::Size
bounds(100, 100);
1516 root_
= Layer::Create();
1517 root_
->SetBounds(bounds
);
1519 layer_
= TextureLayer::CreateForMailbox(nullptr);
1520 layer_
->SetIsDrawable(true);
1521 layer_
->SetBounds(bounds
);
1523 root_
->AddChild(layer_
);
1524 layer_tree_host()->SetRootLayer(root_
);
1525 layer_tree_host()->SetViewportSize(bounds
);
1528 void BeginTest() override
{
1529 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1531 callback_count_
= 0;
1533 // Set the mailbox on the main thread.
1535 EXPECT_EQ(0, callback_count_
);
1537 PostSetNeedsCommitToMainThread();
1540 void DidCommitAndDrawFrame() override
{
1541 switch (layer_tree_host()->source_frame_number()) {
1543 // Remove the TextureLayer on the main thread while the mailbox is in
1544 // the impl tree, but don't delete the TextureLayer until after the impl
1545 // tree side is deleted.
1546 layer_
->RemoveFromParent();
1554 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1557 base::ThreadChecker main_thread_
;
1558 int callback_count_
;
1559 scoped_refptr
<Layer
> root_
;
1560 scoped_refptr
<TextureLayer
> layer_
;
1563 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1564 TextureLayerWithMailboxImplThreadDeleted
);