1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/layers/texture_layer.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/location.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/threading/thread.h"
17 #include "base/time/time.h"
18 #include "cc/layers/solid_color_layer.h"
19 #include "cc/layers/texture_layer_client.h"
20 #include "cc/layers/texture_layer_impl.h"
21 #include "cc/output/compositor_frame_ack.h"
22 #include "cc/output/context_provider.h"
23 #include "cc/resources/returned_resource.h"
24 #include "cc/test/fake_impl_proxy.h"
25 #include "cc/test/fake_layer_tree_host_client.h"
26 #include "cc/test/fake_layer_tree_host_impl.h"
27 #include "cc/test/fake_output_surface.h"
28 #include "cc/test/layer_test_common.h"
29 #include "cc/test/layer_tree_test.h"
30 #include "cc/test/test_task_graph_runner.h"
31 #include "cc/test/test_web_graphics_context_3d.h"
32 #include "cc/trees/blocking_task_runner.h"
33 #include "cc/trees/layer_tree_host.h"
34 #include "cc/trees/layer_tree_impl.h"
35 #include "cc/trees/single_thread_proxy.h"
36 #include "gpu/GLES2/gl2extchromium.h"
37 #include "testing/gmock/include/gmock/gmock.h"
38 #include "testing/gtest/include/gtest/gtest.h"
40 using ::testing::Mock
;
42 using ::testing::AtLeast
;
43 using ::testing::AnyNumber
;
44 using ::testing::InvokeWithoutArgs
;
49 gpu::Mailbox
MailboxFromChar(char value
) {
51 memset(mailbox
.name
, value
, sizeof(mailbox
.name
));
55 class MockLayerTreeHost
: public LayerTreeHost
{
57 static scoped_ptr
<MockLayerTreeHost
> Create(FakeLayerTreeHostClient
* client
) {
58 LayerTreeHost::InitParams params
;
59 params
.client
= client
;
60 LayerTreeSettings settings
;
61 params
.settings
= &settings
;
62 return make_scoped_ptr(new MockLayerTreeHost(client
, ¶ms
));
65 MOCK_METHOD0(SetNeedsCommit
, void());
66 MOCK_METHOD0(SetNeedsUpdateLayers
, void());
67 MOCK_METHOD0(StartRateLimiter
, void());
68 MOCK_METHOD0(StopRateLimiter
, void());
71 MockLayerTreeHost(FakeLayerTreeHostClient
* client
,
72 LayerTreeHost::InitParams
* params
)
73 : LayerTreeHost(params
) {
74 InitializeSingleThreaded(client
, base::ThreadTaskRunnerHandle::Get(),
79 class FakeTextureLayerClient
: public TextureLayerClient
{
81 FakeTextureLayerClient() : mailbox_changed_(true) {}
83 bool PrepareTextureMailbox(
84 TextureMailbox
* mailbox
,
85 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
86 bool use_shared_memory
) override
{
87 if (!mailbox_changed_
)
91 *release_callback
= release_callback_
.Pass();
92 mailbox_changed_
= false;
96 void set_mailbox(const TextureMailbox
& mailbox
,
97 scoped_ptr
<SingleReleaseCallback
> release_callback
) {
99 release_callback_
= release_callback
.Pass();
100 mailbox_changed_
= true;
104 TextureMailbox mailbox_
;
105 scoped_ptr
<SingleReleaseCallback
> release_callback_
;
106 bool mailbox_changed_
;
107 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient
);
110 class MockMailboxCallback
{
112 MOCK_METHOD3(Release
,
113 void(const gpu::Mailbox
& mailbox
,
115 bool lost_resource
));
116 MOCK_METHOD3(Release2
,
117 void(SharedBitmap
* shared_bitmap
,
119 bool lost_resource
));
120 MOCK_METHOD4(ReleaseImpl
,
121 void(const gpu::Mailbox
& mailbox
,
124 BlockingTaskRunner
* main_thread_task_runner
));
125 MOCK_METHOD4(ReleaseImpl2
,
126 void(SharedBitmap
* shared_bitmap
,
129 BlockingTaskRunner
* main_thread_task_runner
));
132 struct CommonMailboxObjects
{
133 explicit CommonMailboxObjects(SharedBitmapManager
* manager
)
134 : mailbox_name1_(MailboxFromChar('1')),
135 mailbox_name2_(MailboxFromChar('2')),
138 release_mailbox1_
= base::Bind(&MockMailboxCallback::Release
,
139 base::Unretained(&mock_callback_
),
141 release_mailbox2_
= base::Bind(&MockMailboxCallback::Release
,
142 base::Unretained(&mock_callback_
),
144 release_mailbox1_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
145 base::Unretained(&mock_callback_
),
147 release_mailbox2_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
148 base::Unretained(&mock_callback_
),
150 const uint32 arbitrary_target1
= GL_TEXTURE_2D
;
151 const uint32 arbitrary_target2
= GL_TEXTURE_EXTERNAL_OES
;
152 mailbox1_
= TextureMailbox(mailbox_name1_
, arbitrary_target1
, sync_point1_
);
153 mailbox2_
= TextureMailbox(mailbox_name2_
, arbitrary_target2
, sync_point2_
);
154 gfx::Size
size(128, 128);
155 shared_bitmap_
= manager
->AllocateSharedBitmap(size
);
156 DCHECK(shared_bitmap_
);
158 base::Bind(&MockMailboxCallback::Release2
,
159 base::Unretained(&mock_callback_
), shared_bitmap_
.get());
160 release_mailbox3_impl_
=
161 base::Bind(&MockMailboxCallback::ReleaseImpl2
,
162 base::Unretained(&mock_callback_
), shared_bitmap_
.get());
163 mailbox3_
= TextureMailbox(shared_bitmap_
.get(), size
);
166 gpu::Mailbox mailbox_name1_
;
167 gpu::Mailbox mailbox_name2_
;
168 MockMailboxCallback mock_callback_
;
169 ReleaseCallback release_mailbox1_
;
170 ReleaseCallback release_mailbox2_
;
171 ReleaseCallback release_mailbox3_
;
172 ReleaseCallbackImpl release_mailbox1_impl_
;
173 ReleaseCallbackImpl release_mailbox2_impl_
;
174 ReleaseCallbackImpl release_mailbox3_impl_
;
175 TextureMailbox mailbox1_
;
176 TextureMailbox mailbox2_
;
177 TextureMailbox mailbox3_
;
180 scoped_ptr
<SharedBitmap
> shared_bitmap_
;
183 class TextureLayerTest
: public testing::Test
{
187 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)),
188 host_impl_(&proxy_
, &shared_bitmap_manager_
, &task_graph_runner_
),
189 test_data_(&shared_bitmap_manager_
) {}
192 void SetUp() override
{
193 layer_tree_host_
= MockLayerTreeHost::Create(&fake_client_
);
194 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
195 layer_tree_host_
->SetViewportSize(gfx::Size(10, 10));
196 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
199 void TearDown() override
{
200 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
201 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
203 layer_tree_host_
->SetRootLayer(nullptr);
204 layer_tree_host_
= nullptr;
207 scoped_ptr
<MockLayerTreeHost
> layer_tree_host_
;
208 FakeImplProxy proxy_
;
209 FakeLayerTreeHostClient fake_client_
;
210 TestSharedBitmapManager shared_bitmap_manager_
;
211 TestTaskGraphRunner task_graph_runner_
;
212 FakeLayerTreeHostImpl host_impl_
;
213 CommonMailboxObjects test_data_
;
216 TEST_F(TextureLayerTest
, CheckPropertyChangeCausesCorrectBehavior
) {
217 scoped_refptr
<TextureLayer
> test_layer
=
218 TextureLayer::CreateForMailbox(nullptr);
219 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_
->SetRootLayer(test_layer
));
221 // Test properties that should call SetNeedsCommit. All properties need to
222 // be set to new values in order for SetNeedsCommit to be called.
223 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetFlipped(false));
224 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetNearestNeighbor(true));
225 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetUV(
226 gfx::PointF(0.25f
, 0.25f
), gfx::PointF(0.75f
, 0.75f
)));
227 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetVertexOpacity(
228 0.5f
, 0.5f
, 0.5f
, 0.5f
));
229 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetPremultipliedAlpha(false));
230 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetBlendBackgroundColor(true));
233 TEST_F(TextureLayerTest
, VisibleContentOpaqueRegion
) {
234 const gfx::Size
layer_bounds(100, 100);
235 const gfx::Rect
layer_rect(layer_bounds
);
236 const Region
layer_region(layer_rect
);
238 scoped_refptr
<TextureLayer
> layer
= TextureLayer::CreateForMailbox(nullptr);
239 layer
->SetBounds(layer_bounds
);
240 layer
->draw_properties().visible_content_rect
= layer_rect
;
241 layer
->SetBlendBackgroundColor(true);
243 // Verify initial conditions.
244 EXPECT_FALSE(layer
->contents_opaque());
245 EXPECT_EQ(0u, layer
->background_color());
246 EXPECT_EQ(Region().ToString(),
247 layer
->VisibleContentOpaqueRegion().ToString());
249 // Opaque background.
250 layer
->SetBackgroundColor(SK_ColorWHITE
);
251 EXPECT_EQ(layer_region
.ToString(),
252 layer
->VisibleContentOpaqueRegion().ToString());
254 // Transparent background.
255 layer
->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
256 EXPECT_EQ(Region().ToString(),
257 layer
->VisibleContentOpaqueRegion().ToString());
260 TEST_F(TextureLayerTest
, RateLimiter
) {
261 FakeTextureLayerClient client
;
262 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(
264 test_layer
->SetIsDrawable(true);
265 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
266 layer_tree_host_
->SetRootLayer(test_layer
);
268 // Don't rate limit until we invalidate.
269 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
270 test_layer
->SetRateLimitContext(true);
271 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
273 // Do rate limit after we invalidate.
274 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
275 test_layer
->SetNeedsDisplay();
276 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
278 // Stop rate limiter when we don't want it any more.
279 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
280 test_layer
->SetRateLimitContext(false);
281 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
283 // Or we clear the client.
284 test_layer
->SetRateLimitContext(true);
285 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
286 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
287 test_layer
->ClearClient();
288 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
290 // Reset to a layer with a client, that started the rate limiter.
291 test_layer
= TextureLayer::CreateForMailbox(
293 test_layer
->SetIsDrawable(true);
294 test_layer
->SetRateLimitContext(true);
295 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
296 layer_tree_host_
->SetRootLayer(test_layer
);
297 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
298 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
299 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
300 test_layer
->SetNeedsDisplay();
301 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
303 // Stop rate limiter when we're removed from the tree.
304 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
305 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(1);
306 layer_tree_host_
->SetRootLayer(nullptr);
307 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
310 class TestMailboxHolder
: public TextureLayer::TextureMailboxHolder
{
312 using TextureLayer::TextureMailboxHolder::Create
;
315 ~TestMailboxHolder() override
{}
318 class TextureLayerWithMailboxTest
: public TextureLayerTest
{
320 void TearDown() override
{
321 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
322 EXPECT_CALL(test_data_
.mock_callback_
,
323 Release(test_data_
.mailbox_name1_
,
324 test_data_
.sync_point1_
,
326 TextureLayerTest::TearDown();
330 TEST_F(TextureLayerWithMailboxTest
, ReplaceMailboxOnMainThreadBeforeCommit
) {
331 scoped_refptr
<TextureLayer
> test_layer
=
332 TextureLayer::CreateForMailbox(nullptr);
333 ASSERT_TRUE(test_layer
.get());
335 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
336 layer_tree_host_
->SetRootLayer(test_layer
);
337 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
339 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
340 test_layer
->SetTextureMailbox(
341 test_data_
.mailbox1_
,
342 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
343 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
345 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
346 EXPECT_CALL(test_data_
.mock_callback_
,
347 Release(test_data_
.mailbox_name1_
,
348 test_data_
.sync_point1_
,
351 test_layer
->SetTextureMailbox(
352 test_data_
.mailbox2_
,
353 SingleReleaseCallback::Create(test_data_
.release_mailbox2_
));
354 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
355 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
357 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
358 EXPECT_CALL(test_data_
.mock_callback_
,
359 Release(test_data_
.mailbox_name2_
,
360 test_data_
.sync_point2_
,
363 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
364 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
365 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
367 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
368 test_layer
->SetTextureMailbox(
369 test_data_
.mailbox3_
,
370 SingleReleaseCallback::Create(test_data_
.release_mailbox3_
));
371 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
372 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
374 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
375 EXPECT_CALL(test_data_
.mock_callback_
,
376 Release2(test_data_
.shared_bitmap_
.get(), 0, false)).Times(1);
377 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
378 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
379 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
382 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
383 test_layer
->SetTextureMailbox(
384 test_data_
.mailbox1_
,
385 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
388 TEST_F(TextureLayerTest
, SetTextureMailboxWithoutReleaseCallback
) {
389 scoped_refptr
<TextureLayer
> test_layer
=
390 TextureLayer::CreateForMailbox(nullptr);
391 ASSERT_TRUE(test_layer
.get());
393 // These use the same gpu::Mailbox, but different sync points.
394 TextureMailbox
mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D
, 1);
395 TextureMailbox
mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D
, 2);
397 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
398 layer_tree_host_
->SetRootLayer(test_layer
);
399 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
401 // Set the mailbox the first time. It should cause a commit.
402 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
403 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox1
);
404 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
406 // Set the mailbox again with a new sync point, as the backing texture has
407 // been updated. It should cause a new commit.
408 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
409 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox2
);
410 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
413 class TextureLayerMailboxHolderTest
: public TextureLayerTest
{
415 TextureLayerMailboxHolderTest()
416 : main_thread_("MAIN") {
417 main_thread_
.Start();
418 main_thread_
.message_loop()->task_runner()->PostTask(
419 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain
,
420 base::Unretained(this)));
424 void Wait(const base::Thread
& thread
) {
425 bool manual_reset
= false;
426 bool initially_signaled
= false;
427 base::WaitableEvent
event(manual_reset
, initially_signaled
);
428 thread
.message_loop()->task_runner()->PostTask(
430 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
434 void CreateMainRef() {
435 main_ref_
= TestMailboxHolder::Create(
436 test_data_
.mailbox1_
,
437 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
)).Pass();
440 void ReleaseMainRef() { main_ref_
= nullptr; }
442 void CreateImplRef(scoped_ptr
<SingleReleaseCallbackImpl
>* impl_ref
) {
443 *impl_ref
= main_ref_
->holder()->GetCallbackForImplThread();
446 void CapturePostTasksAndWait(base::WaitableEvent
* begin_capture
,
447 base::WaitableEvent
* wait_for_capture
,
448 base::WaitableEvent
* stop_capture
) {
449 begin_capture
->Wait();
450 BlockingTaskRunner::CapturePostTasks
capture(
451 main_thread_task_runner_
.get());
452 wait_for_capture
->Signal();
453 stop_capture
->Wait();
457 void InitializeOnMain() {
458 main_thread_task_runner_
=
459 BlockingTaskRunner::Create(main_thread_
.task_runner());
462 scoped_ptr
<TestMailboxHolder::MainThreadReference
>
464 base::Thread main_thread_
;
465 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
468 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_BothReleaseThenMain
) {
469 scoped_refptr
<TextureLayer
> test_layer
=
470 TextureLayer::CreateForMailbox(nullptr);
471 ASSERT_TRUE(test_layer
.get());
473 main_thread_
.message_loop()->task_runner()->PostTask(
474 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
475 base::Unretained(this)));
479 // The texture layer is attached to compositor1, and passes a reference to its
481 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
482 main_thread_
.message_loop()->task_runner()->PostTask(
483 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
484 base::Unretained(this), &compositor1
));
486 // Then the texture layer is removed and attached to compositor2, and passes a
487 // reference to its impl tree.
488 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
489 main_thread_
.message_loop()->task_runner()->PostTask(
490 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
491 base::Unretained(this), &compositor2
));
494 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
496 // The compositors both destroy their impl trees before the main thread layer
498 compositor1
->Run(100, false, main_thread_task_runner_
.get());
499 compositor2
->Run(200, false, main_thread_task_runner_
.get());
503 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
504 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
506 // The main thread ref is the last one, so the mailbox is released back to the
507 // embedder, with the last sync point provided by the impl trees.
508 EXPECT_CALL(test_data_
.mock_callback_
,
509 Release(test_data_
.mailbox_name1_
, 200, false)).Times(1);
511 main_thread_
.message_loop()->task_runner()->PostTask(
512 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
513 base::Unretained(this)));
515 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
518 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleaseBetween
) {
519 scoped_refptr
<TextureLayer
> test_layer
=
520 TextureLayer::CreateForMailbox(nullptr);
521 ASSERT_TRUE(test_layer
.get());
523 main_thread_
.message_loop()->task_runner()->PostTask(
524 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
525 base::Unretained(this)));
529 // The texture layer is attached to compositor1, and passes a reference to its
531 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
532 main_thread_
.message_loop()->task_runner()->PostTask(
533 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
534 base::Unretained(this), &compositor1
));
536 // Then the texture layer is removed and attached to compositor2, and passes a
537 // reference to its impl tree.
538 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
539 main_thread_
.message_loop()->task_runner()->PostTask(
540 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
541 base::Unretained(this), &compositor2
));
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()->task_runner()->PostTask(
551 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
552 base::Unretained(this)));
556 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
557 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
559 // The second impl reference is destroyed last, causing the mailbox to be
560 // released back to the embedder with the last sync point from the impl tree.
561 EXPECT_CALL(test_data_
.mock_callback_
,
562 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
564 compositor2
->Run(200, true, main_thread_task_runner_
.get());
566 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
569 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleasedFirst
) {
570 scoped_refptr
<TextureLayer
> test_layer
=
571 TextureLayer::CreateForMailbox(nullptr);
572 ASSERT_TRUE(test_layer
.get());
574 main_thread_
.message_loop()->task_runner()->PostTask(
575 FROM_HERE
, 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()->task_runner()->PostTask(
584 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
585 base::Unretained(this), &compositor1
));
587 // Then the texture layer is removed and attached to compositor2, and passes a
588 // reference to its impl tree.
589 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
590 main_thread_
.message_loop()->task_runner()->PostTask(
591 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
592 base::Unretained(this), &compositor2
));
595 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
597 // The main thread reference is destroyed first.
598 main_thread_
.message_loop()->task_runner()->PostTask(
599 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
600 base::Unretained(this)));
602 // One compositor destroys their impl tree.
603 compositor2
->Run(200, false, main_thread_task_runner_
.get());
607 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
608 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
610 // The second impl reference is destroyed last, causing the mailbox to be
611 // released back to the embedder with the last sync point from the impl tree.
612 EXPECT_CALL(test_data_
.mock_callback_
,
613 Release(test_data_
.mailbox_name1_
, 100, true)).Times(1);
615 compositor1
->Run(100, true, main_thread_task_runner_
.get());
617 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
620 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_SecondImplRefShortcut
) {
621 scoped_refptr
<TextureLayer
> test_layer
=
622 TextureLayer::CreateForMailbox(nullptr);
623 ASSERT_TRUE(test_layer
.get());
625 main_thread_
.message_loop()->task_runner()->PostTask(
626 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
627 base::Unretained(this)));
631 // The texture layer is attached to compositor1, and passes a reference to its
633 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
634 main_thread_
.message_loop()->task_runner()->PostTask(
635 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
636 base::Unretained(this), &compositor1
));
638 // Then the texture layer is removed and attached to compositor2, and passes a
639 // reference to its impl tree.
640 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
641 main_thread_
.message_loop()->task_runner()->PostTask(
642 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
643 base::Unretained(this), &compositor2
));
646 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
648 // The main thread reference is destroyed first.
649 main_thread_
.message_loop()->task_runner()->PostTask(
650 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
651 base::Unretained(this)));
653 EXPECT_CALL(test_data_
.mock_callback_
,
654 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
656 bool manual_reset
= false;
657 bool initially_signaled
= false;
658 base::WaitableEvent
begin_capture(manual_reset
, initially_signaled
);
659 base::WaitableEvent
wait_for_capture(manual_reset
, initially_signaled
);
660 base::WaitableEvent
stop_capture(manual_reset
, initially_signaled
);
662 // Post a task to start capturing tasks on the main thread. This will block
663 // the main thread until we signal the |stop_capture| event.
664 main_thread_
.message_loop()->task_runner()->PostTask(
666 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait
,
667 base::Unretained(this), &begin_capture
, &wait_for_capture
,
670 // Before the main thread capturing starts, one compositor destroys their
671 // impl reference. Since capturing did not start, this gets post-tasked to
673 compositor1
->Run(100, false, main_thread_task_runner_
.get());
675 // Start capturing on the main thread.
676 begin_capture
.Signal();
677 wait_for_capture
.Wait();
679 // Meanwhile, the second compositor released its impl reference, but this task
680 // gets shortcutted directly to the main thread. This means the reference is
681 // released before compositor1, whose reference will be released later when
682 // the post-task is serviced. But since it was destroyed _on the impl thread_
683 // last, its sync point values should be used.
684 compositor2
->Run(200, true, main_thread_task_runner_
.get());
686 stop_capture
.Signal();
689 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
692 class TextureLayerImplWithMailboxThreadedCallback
: public LayerTreeTest
{
694 TextureLayerImplWithMailboxThreadedCallback()
695 : callback_count_(0),
698 // Make sure callback is received on main and doesn't block the impl thread.
699 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
700 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
701 EXPECT_FALSE(lost_resource
);
705 void SetMailbox(char mailbox_char
) {
706 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
707 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
709 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback
,
710 base::Unretained(this)));
711 layer_
->SetTextureMailbox(
712 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
716 void BeginTest() override
{
717 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
719 gfx::Size
bounds(100, 100);
720 root_
= Layer::Create();
721 root_
->SetBounds(bounds
);
723 layer_
= TextureLayer::CreateForMailbox(nullptr);
724 layer_
->SetIsDrawable(true);
725 layer_
->SetBounds(bounds
);
727 root_
->AddChild(layer_
);
728 layer_tree_host()->SetRootLayer(root_
);
729 layer_tree_host()->SetViewportSize(bounds
);
731 EXPECT_EQ(0, callback_count_
);
733 // Case #1: change mailbox before the commit. The old mailbox should be
734 // released immediately.
736 EXPECT_EQ(1, callback_count_
);
737 PostSetNeedsCommitToMainThread();
740 void DidCommit() override
{
742 switch (commit_count_
) {
744 // Case #2: change mailbox after the commit (and draw), where the
745 // layer draws. The old mailbox should be released during the next
748 EXPECT_EQ(1, callback_count_
);
751 EXPECT_EQ(2, callback_count_
);
752 // Case #3: change mailbox when the layer doesn't draw. The old
753 // mailbox should be released during the next commit.
754 layer_
->SetBounds(gfx::Size());
758 EXPECT_EQ(3, callback_count_
);
759 // Case #4: release mailbox that was committed but never drawn. The
760 // old mailbox should be released during the next commit.
761 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
764 if (layer_tree_host()->settings().impl_side_painting
) {
765 // With impl painting, the texture mailbox will still be on the impl
766 // thread when the commit finishes, because the layer is not drawble
767 // when it has no texture mailbox, and thus does not block the commit
768 // on activation. So, we wait for activation.
769 // TODO(danakj): fix this. crbug.com/277953
770 layer_tree_host()->SetNeedsCommit();
776 EXPECT_EQ(4, callback_count_
);
777 // Restore a mailbox for the next step.
781 // Case #5: remove layer from tree. Callback should *not* be called, the
782 // mailbox is returned to the main thread.
783 EXPECT_EQ(4, callback_count_
);
784 layer_
->RemoveFromParent();
787 if (layer_tree_host()->settings().impl_side_painting
) {
788 // With impl painting, the texture mailbox will still be on the impl
789 // thread when the commit finishes, because the layer is not around to
790 // block the commit on activation anymore. So, we wait for activation.
791 // TODO(danakj): fix this. crbug.com/277953
792 layer_tree_host()->SetNeedsCommit();
798 EXPECT_EQ(4, callback_count_
);
799 // Resetting the mailbox will call the callback now.
800 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
801 EXPECT_EQ(5, callback_count_
);
810 void AfterTest() override
{}
813 base::ThreadChecker main_thread_
;
816 scoped_refptr
<Layer
> root_
;
817 scoped_refptr
<TextureLayer
> layer_
;
820 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
821 TextureLayerImplWithMailboxThreadedCallback
);
824 class TextureLayerMailboxIsActivatedDuringCommit
: public LayerTreeTest
{
826 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
828 static void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {}
830 void SetMailbox(char mailbox_char
) {
831 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
833 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback
));
834 layer_
->SetTextureMailbox(
835 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
839 void BeginTest() override
{
840 gfx::Size
bounds(100, 100);
841 root_
= Layer::Create();
842 root_
->SetBounds(bounds
);
844 layer_
= TextureLayer::CreateForMailbox(nullptr);
845 layer_
->SetIsDrawable(true);
846 layer_
->SetBounds(bounds
);
848 root_
->AddChild(layer_
);
849 layer_tree_host()->SetRootLayer(root_
);
850 layer_tree_host()->SetViewportSize(bounds
);
853 PostSetNeedsCommitToMainThread();
856 void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
860 void DidCommit() override
{
861 switch (layer_tree_host()->source_frame_number()) {
863 // The first mailbox has been activated. Set a new mailbox, and
864 // expect the next commit to finish *after* it is activated.
868 // The second mailbox has been activated. Remove the layer from
869 // the tree to cause another commit/activation. The commit should
870 // finish *after* the layer is removed from the active tree.
871 layer_
->RemoveFromParent();
879 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
880 switch (host_impl
->active_tree()->source_frame_number()) {
882 // The activate for the 1st mailbox should have happened before now.
883 EXPECT_EQ(1, activate_count_
);
887 // The activate for the 2nd mailbox should have happened before now.
888 EXPECT_EQ(2, activate_count_
);
892 // The activate to remove the layer should have happened before now.
893 EXPECT_EQ(3, activate_count_
);
903 void AfterTest() override
{}
906 scoped_refptr
<Layer
> root_
;
907 scoped_refptr
<TextureLayer
> layer_
;
910 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
911 TextureLayerMailboxIsActivatedDuringCommit
);
913 class TextureLayerImplWithMailboxTest
: public TextureLayerTest
{
915 TextureLayerImplWithMailboxTest()
917 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)) {}
919 void SetUp() override
{
920 TextureLayerTest::SetUp();
921 layer_tree_host_
= MockLayerTreeHost::Create(&fake_client_
);
922 EXPECT_TRUE(host_impl_
.InitializeRenderer(FakeOutputSurface::Create3d()));
925 bool WillDraw(TextureLayerImpl
* layer
, DrawMode mode
) {
926 bool will_draw
= layer
->WillDraw(
927 mode
, host_impl_
.active_tree()->resource_provider());
929 layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
933 FakeLayerTreeHostClient fake_client_
;
936 // Test conditions for results of TextureLayerImpl::WillDraw under
937 // different configurations of different mailbox, texture_id, and draw_mode.
938 TEST_F(TextureLayerImplWithMailboxTest
, TestWillDraw
) {
940 test_data_
.mock_callback_
,
941 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
943 EXPECT_CALL(test_data_
.mock_callback_
,
944 ReleaseImpl2(test_data_
.shared_bitmap_
.get(), 0, false, _
))
948 scoped_ptr
<TextureLayerImpl
> impl_layer
=
949 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
950 impl_layer
->SetTextureMailbox(
951 test_data_
.mailbox1_
,
952 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
953 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
957 scoped_ptr
<TextureLayerImpl
> impl_layer
=
958 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
959 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
960 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
964 // Software resource.
965 scoped_ptr
<TextureLayerImpl
> impl_layer
=
966 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
967 impl_layer
->SetTextureMailbox(
968 test_data_
.mailbox3_
,
969 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
970 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
975 scoped_ptr
<TextureLayerImpl
> impl_layer
=
976 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
977 impl_layer
->SetTextureMailbox(
978 test_data_
.mailbox1_
,
979 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
980 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
984 scoped_ptr
<TextureLayerImpl
> impl_layer
=
985 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
986 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
987 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
991 // Software resource.
992 scoped_ptr
<TextureLayerImpl
> impl_layer
=
993 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
994 impl_layer
->SetTextureMailbox(
995 test_data_
.mailbox3_
,
996 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
997 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
1000 // Resourceless software mode.
1002 scoped_ptr
<TextureLayerImpl
> impl_layer
=
1003 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1004 impl_layer
->SetTextureMailbox(
1005 test_data_
.mailbox1_
,
1006 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1007 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_RESOURCELESS_SOFTWARE
));
1011 TEST_F(TextureLayerImplWithMailboxTest
, TestImplLayerCallbacks
) {
1012 host_impl_
.CreatePendingTree();
1013 scoped_ptr
<TextureLayerImpl
> pending_layer
;
1014 pending_layer
= TextureLayerImpl::Create(host_impl_
.pending_tree(), 1);
1015 ASSERT_TRUE(pending_layer
);
1017 scoped_ptr
<LayerImpl
> active_layer(
1018 pending_layer
->CreateLayerImpl(host_impl_
.active_tree()));
1019 ASSERT_TRUE(active_layer
);
1021 pending_layer
->SetTextureMailbox(
1022 test_data_
.mailbox1_
,
1023 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1025 // Test multiple commits without an activation.
1027 test_data_
.mock_callback_
,
1028 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1030 pending_layer
->SetTextureMailbox(
1031 test_data_
.mailbox2_
,
1032 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox2_impl_
));
1033 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1035 // Test callback after activation.
1036 pending_layer
->PushPropertiesTo(active_layer
.get());
1037 active_layer
->DidBecomeActive();
1039 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1040 pending_layer
->SetTextureMailbox(
1041 test_data_
.mailbox1_
,
1042 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1043 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1045 EXPECT_CALL(test_data_
.mock_callback_
,
1046 ReleaseImpl(test_data_
.mailbox_name2_
, _
, false, _
)).Times(1);
1047 pending_layer
->PushPropertiesTo(active_layer
.get());
1048 active_layer
->DidBecomeActive();
1049 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1051 // Test resetting the mailbox.
1052 EXPECT_CALL(test_data_
.mock_callback_
,
1053 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1054 pending_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1055 pending_layer
->PushPropertiesTo(active_layer
.get());
1056 active_layer
->DidBecomeActive();
1057 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1061 test_data_
.mock_callback_
,
1062 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1064 pending_layer
->SetTextureMailbox(
1065 test_data_
.mailbox1_
,
1066 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1069 TEST_F(TextureLayerImplWithMailboxTest
,
1070 TestDestructorCallbackOnCreatedResource
) {
1071 scoped_ptr
<TextureLayerImpl
> impl_layer
;
1072 impl_layer
= TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1073 ASSERT_TRUE(impl_layer
);
1075 EXPECT_CALL(test_data_
.mock_callback_
,
1076 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1077 impl_layer
->SetTextureMailbox(
1078 test_data_
.mailbox1_
,
1079 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1080 impl_layer
->DidBecomeActive();
1081 EXPECT_TRUE(impl_layer
->WillDraw(
1082 DRAW_MODE_HARDWARE
, host_impl_
.active_tree()->resource_provider()));
1083 impl_layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
1084 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1087 TEST_F(TextureLayerImplWithMailboxTest
, TestCallbackOnInUseResource
) {
1088 ResourceProvider
* provider
= host_impl_
.active_tree()->resource_provider();
1089 ResourceId id
= provider
->CreateResourceFromTextureMailbox(
1090 test_data_
.mailbox1_
,
1091 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1092 provider
->AllocateForTesting(id
);
1094 // Transfer some resources to the parent.
1095 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1096 resource_ids_to_transfer
.push_back(id
);
1097 TransferableResourceArray list
;
1098 provider
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1099 EXPECT_TRUE(provider
->InUseByConsumer(id
));
1100 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1101 provider
->DeleteResource(id
);
1102 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1103 EXPECT_CALL(test_data_
.mock_callback_
,
1104 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1105 ReturnedResourceArray returned
;
1106 TransferableResource::ReturnResources(list
, &returned
);
1107 provider
->ReceiveReturnsFromParent(returned
);
1110 // Checks that TextureLayer::Update does not cause an extra commit when setting
1111 // the texture mailbox.
1112 class TextureLayerNoExtraCommitForMailboxTest
1113 : public LayerTreeTest
,
1114 public TextureLayerClient
{
1116 // TextureLayerClient implementation.
1117 bool PrepareTextureMailbox(
1118 TextureMailbox
* texture_mailbox
,
1119 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1120 bool use_shared_memory
) override
{
1121 if (layer_tree_host()->source_frame_number() == 1) {
1122 // Once this has been committed, the mailbox will be released.
1123 *texture_mailbox
= TextureMailbox();
1127 *texture_mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1128 *release_callback
= SingleReleaseCallback::Create(
1129 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased
,
1130 base::Unretained(this)));
1134 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1135 // Source frame number during callback is the same as the source frame
1136 // on which it was released.
1137 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1141 void SetupTree() override
{
1142 scoped_refptr
<Layer
> root
= Layer::Create();
1143 root
->SetBounds(gfx::Size(10, 10));
1144 root
->SetIsDrawable(true);
1146 texture_layer_
= TextureLayer::CreateForMailbox(this);
1147 texture_layer_
->SetBounds(gfx::Size(10, 10));
1148 texture_layer_
->SetIsDrawable(true);
1149 root
->AddChild(texture_layer_
);
1151 layer_tree_host()->SetRootLayer(root
);
1152 LayerTreeTest::SetupTree();
1155 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1157 void DidCommitAndDrawFrame() override
{
1158 switch (layer_tree_host()->source_frame_number()) {
1160 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1161 // Invalidate the texture layer to clear the mailbox before
1163 texture_layer_
->SetNeedsDisplay();
1173 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1174 ASSERT_TRUE(result
);
1175 DelegatedFrameData
* delegated_frame_data
=
1176 output_surface()->last_sent_frame().delegated_frame_data
.get();
1177 if (!delegated_frame_data
)
1180 // Return all resources immediately.
1181 TransferableResourceArray resources_to_return
=
1182 output_surface()->resources_held_by_parent();
1184 CompositorFrameAck ack
;
1185 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1186 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1187 host_impl
->ReclaimResources(&ack
);
1190 void AfterTest() override
{}
1193 scoped_refptr
<TextureLayer
> texture_layer_
;
1196 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest
);
1198 // Checks that changing a mailbox in the client for a TextureLayer that's
1199 // invisible correctly works and uses the new mailbox as soon as the layer
1200 // becomes visible (and returns the old one).
1201 class TextureLayerChangeInvisibleMailboxTest
1202 : public LayerTreeTest
,
1203 public TextureLayerClient
{
1205 TextureLayerChangeInvisibleMailboxTest()
1206 : mailbox_changed_(true),
1207 mailbox_returned_(0),
1210 mailbox_
= MakeMailbox('1');
1213 // TextureLayerClient implementation.
1214 bool PrepareTextureMailbox(
1215 TextureMailbox
* mailbox
,
1216 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1217 bool use_shared_memory
) override
{
1219 if (!mailbox_changed_
)
1221 *mailbox
= mailbox_
;
1222 *release_callback
= SingleReleaseCallback::Create(
1223 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased
,
1224 base::Unretained(this)));
1228 TextureMailbox
MakeMailbox(char name
) {
1229 return TextureMailbox(MailboxFromChar(name
), GL_TEXTURE_2D
, 0);
1232 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1233 ++mailbox_returned_
;
1236 void SetupTree() override
{
1237 scoped_refptr
<Layer
> root
= Layer::Create();
1238 root
->SetBounds(gfx::Size(10, 10));
1239 root
->SetIsDrawable(true);
1241 solid_layer_
= SolidColorLayer::Create();
1242 solid_layer_
->SetBounds(gfx::Size(10, 10));
1243 solid_layer_
->SetIsDrawable(true);
1244 solid_layer_
->SetBackgroundColor(SK_ColorWHITE
);
1245 root
->AddChild(solid_layer_
);
1247 parent_layer_
= Layer::Create();
1248 parent_layer_
->SetBounds(gfx::Size(10, 10));
1249 parent_layer_
->SetIsDrawable(true);
1250 root
->AddChild(parent_layer_
);
1252 texture_layer_
= TextureLayer::CreateForMailbox(this);
1253 texture_layer_
->SetBounds(gfx::Size(10, 10));
1254 texture_layer_
->SetIsDrawable(true);
1255 parent_layer_
->AddChild(texture_layer_
);
1257 layer_tree_host()->SetRootLayer(root
);
1258 LayerTreeTest::SetupTree();
1261 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1263 void DidCommitAndDrawFrame() override
{
1265 switch (commit_count_
) {
1267 // We should have updated the layer, committing the texture.
1268 EXPECT_EQ(1, prepare_called_
);
1269 // Make layer invisible.
1270 parent_layer_
->SetOpacity(0.f
);
1273 // Layer shouldn't have been updated.
1274 EXPECT_EQ(1, prepare_called_
);
1275 // Change the texture.
1276 mailbox_
= MakeMailbox('2');
1277 mailbox_changed_
= true;
1278 texture_layer_
->SetNeedsDisplay();
1279 // Force a change to make sure we draw a frame.
1280 solid_layer_
->SetBackgroundColor(SK_ColorGRAY
);
1283 // Layer shouldn't have been updated.
1284 EXPECT_EQ(1, prepare_called_
);
1285 // So the old mailbox isn't returned yet.
1286 EXPECT_EQ(0, mailbox_returned_
);
1287 // Make layer visible again.
1288 parent_layer_
->SetOpacity(1.f
);
1291 // Layer should have been updated.
1292 EXPECT_EQ(2, prepare_called_
);
1293 // So the old mailbox should have been returned already.
1294 EXPECT_EQ(1, mailbox_returned_
);
1295 texture_layer_
->ClearClient();
1298 EXPECT_EQ(2, mailbox_returned_
);
1307 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1308 ASSERT_TRUE(result
);
1309 DelegatedFrameData
* delegated_frame_data
=
1310 output_surface()->last_sent_frame().delegated_frame_data
.get();
1311 if (!delegated_frame_data
)
1314 // Return all resources immediately.
1315 TransferableResourceArray resources_to_return
=
1316 output_surface()->resources_held_by_parent();
1318 CompositorFrameAck ack
;
1319 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1320 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1321 host_impl
->ReclaimResources(&ack
);
1324 void AfterTest() override
{}
1327 scoped_refptr
<SolidColorLayer
> solid_layer_
;
1328 scoped_refptr
<Layer
> parent_layer_
;
1329 scoped_refptr
<TextureLayer
> texture_layer_
;
1331 // Used on the main thread.
1332 bool mailbox_changed_
;
1333 TextureMailbox mailbox_
;
1334 int mailbox_returned_
;
1335 int prepare_called_
;
1339 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest
);
1341 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1342 // the mailbox back to TextureLayerClient.
1343 class TextureLayerReleaseResourcesBase
1344 : public LayerTreeTest
,
1345 public TextureLayerClient
{
1347 // TextureLayerClient implementation.
1348 bool PrepareTextureMailbox(
1349 TextureMailbox
* mailbox
,
1350 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1351 bool use_shared_memory
) override
{
1352 *mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1353 *release_callback
= SingleReleaseCallback::Create(
1354 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased
,
1355 base::Unretained(this)));
1359 void MailboxReleased(unsigned sync_point
, bool lost_resource
) {
1360 mailbox_released_
= true;
1363 void SetupTree() override
{
1364 LayerTreeTest::SetupTree();
1366 scoped_refptr
<TextureLayer
> texture_layer
=
1367 TextureLayer::CreateForMailbox(this);
1368 texture_layer
->SetBounds(gfx::Size(10, 10));
1369 texture_layer
->SetIsDrawable(true);
1371 layer_tree_host()->root_layer()->AddChild(texture_layer
);
1374 void BeginTest() override
{
1375 mailbox_released_
= false;
1376 PostSetNeedsCommitToMainThread();
1379 void DidCommitAndDrawFrame() override
{ EndTest(); }
1381 void AfterTest() override
{ EXPECT_TRUE(mailbox_released_
); }
1384 bool mailbox_released_
;
1387 class TextureLayerReleaseResourcesAfterCommit
1388 : public TextureLayerReleaseResourcesBase
{
1390 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
1391 LayerTreeImpl
* tree
= nullptr;
1392 tree
= host_impl
->sync_tree();
1393 tree
->root_layer()->children()[0]->ReleaseResources();
1397 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit
);
1399 class TextureLayerReleaseResourcesAfterActivate
1400 : public TextureLayerReleaseResourcesBase
{
1402 void DidActivateTreeOnThread(LayerTreeHostImpl
* host_impl
) override
{
1403 host_impl
->active_tree()->root_layer()->children()[0]->ReleaseResources();
1407 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate
);
1409 class TextureLayerWithMailboxMainThreadDeleted
: public LayerTreeTest
{
1411 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1412 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1413 EXPECT_FALSE(lost_resource
);
1418 void SetMailbox(char mailbox_char
) {
1419 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1420 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1422 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback
,
1423 base::Unretained(this)));
1424 layer_
->SetTextureMailbox(
1425 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1429 void SetupTree() override
{
1430 gfx::Size
bounds(100, 100);
1431 root_
= Layer::Create();
1432 root_
->SetBounds(bounds
);
1434 layer_
= TextureLayer::CreateForMailbox(nullptr);
1435 layer_
->SetIsDrawable(true);
1436 layer_
->SetBounds(bounds
);
1438 root_
->AddChild(layer_
);
1439 layer_tree_host()->SetRootLayer(root_
);
1440 layer_tree_host()->SetViewportSize(bounds
);
1443 void BeginTest() override
{
1444 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1446 callback_count_
= 0;
1448 // Set the mailbox on the main thread.
1450 EXPECT_EQ(0, callback_count_
);
1452 PostSetNeedsCommitToMainThread();
1455 void DidCommitAndDrawFrame() override
{
1456 switch (layer_tree_host()->source_frame_number()) {
1458 // Delete the TextureLayer on the main thread while the mailbox is in
1460 layer_
->RemoveFromParent();
1466 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1469 base::ThreadChecker main_thread_
;
1470 int callback_count_
;
1471 scoped_refptr
<Layer
> root_
;
1472 scoped_refptr
<TextureLayer
> layer_
;
1475 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1476 TextureLayerWithMailboxMainThreadDeleted
);
1478 class TextureLayerWithMailboxImplThreadDeleted
: public LayerTreeTest
{
1480 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1481 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1482 EXPECT_FALSE(lost_resource
);
1487 void SetMailbox(char mailbox_char
) {
1488 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1489 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1491 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback
,
1492 base::Unretained(this)));
1493 layer_
->SetTextureMailbox(
1494 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1498 void SetupTree() override
{
1499 gfx::Size
bounds(100, 100);
1500 root_
= Layer::Create();
1501 root_
->SetBounds(bounds
);
1503 layer_
= TextureLayer::CreateForMailbox(nullptr);
1504 layer_
->SetIsDrawable(true);
1505 layer_
->SetBounds(bounds
);
1507 root_
->AddChild(layer_
);
1508 layer_tree_host()->SetRootLayer(root_
);
1509 layer_tree_host()->SetViewportSize(bounds
);
1512 void BeginTest() override
{
1513 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1515 callback_count_
= 0;
1517 // Set the mailbox on the main thread.
1519 EXPECT_EQ(0, callback_count_
);
1521 PostSetNeedsCommitToMainThread();
1524 void DidCommitAndDrawFrame() override
{
1525 switch (layer_tree_host()->source_frame_number()) {
1527 // Remove the TextureLayer on the main thread while the mailbox is in
1528 // the impl tree, but don't delete the TextureLayer until after the impl
1529 // tree side is deleted.
1530 layer_
->RemoveFromParent();
1538 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1541 base::ThreadChecker main_thread_
;
1542 int callback_count_
;
1543 scoped_refptr
<Layer
> root_
;
1544 scoped_refptr
<TextureLayer
> layer_
;
1547 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1548 TextureLayerWithMailboxImplThreadDeleted
);