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_
;
214 LayerSettings layer_settings_
;
217 TEST_F(TextureLayerTest
, CheckPropertyChangeCausesCorrectBehavior
) {
218 scoped_refptr
<TextureLayer
> test_layer
=
219 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
220 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_
->SetRootLayer(test_layer
));
222 // Test properties that should call SetNeedsCommit. All properties need to
223 // be set to new values in order for SetNeedsCommit to be called.
224 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetFlipped(false));
225 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetNearestNeighbor(true));
226 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetUV(
227 gfx::PointF(0.25f
, 0.25f
), gfx::PointF(0.75f
, 0.75f
)));
228 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetVertexOpacity(
229 0.5f
, 0.5f
, 0.5f
, 0.5f
));
230 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetPremultipliedAlpha(false));
231 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetBlendBackgroundColor(true));
234 TEST_F(TextureLayerTest
, VisibleContentOpaqueRegion
) {
235 const gfx::Size
layer_bounds(100, 100);
236 const gfx::Rect
layer_rect(layer_bounds
);
237 const Region
layer_region(layer_rect
);
239 scoped_refptr
<TextureLayer
> layer
=
240 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
241 layer
->SetBounds(layer_bounds
);
242 layer
->draw_properties().visible_content_rect
= layer_rect
;
243 layer
->SetBlendBackgroundColor(true);
245 // Verify initial conditions.
246 EXPECT_FALSE(layer
->contents_opaque());
247 EXPECT_EQ(0u, layer
->background_color());
248 EXPECT_EQ(Region().ToString(),
249 layer
->VisibleContentOpaqueRegion().ToString());
251 // Opaque background.
252 layer
->SetBackgroundColor(SK_ColorWHITE
);
253 EXPECT_EQ(layer_region
.ToString(),
254 layer
->VisibleContentOpaqueRegion().ToString());
256 // Transparent background.
257 layer
->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
258 EXPECT_EQ(Region().ToString(),
259 layer
->VisibleContentOpaqueRegion().ToString());
262 TEST_F(TextureLayerTest
, RateLimiter
) {
263 FakeTextureLayerClient client
;
264 scoped_refptr
<TextureLayer
> test_layer
=
265 TextureLayer::CreateForMailbox(layer_settings_
, &client
);
266 test_layer
->SetIsDrawable(true);
267 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
268 layer_tree_host_
->SetRootLayer(test_layer
);
270 // Don't rate limit until we invalidate.
271 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
272 test_layer
->SetRateLimitContext(true);
273 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
275 // Do rate limit after we invalidate.
276 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
277 test_layer
->SetNeedsDisplay();
278 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
280 // Stop rate limiter when we don't want it any more.
281 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
282 test_layer
->SetRateLimitContext(false);
283 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
285 // Or we clear the client.
286 test_layer
->SetRateLimitContext(true);
287 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
288 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
289 test_layer
->ClearClient();
290 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
292 // Reset to a layer with a client, that started the rate limiter.
293 test_layer
= TextureLayer::CreateForMailbox(layer_settings_
, &client
);
294 test_layer
->SetIsDrawable(true);
295 test_layer
->SetRateLimitContext(true);
296 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
297 layer_tree_host_
->SetRootLayer(test_layer
);
298 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
299 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
300 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
301 test_layer
->SetNeedsDisplay();
302 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
304 // Stop rate limiter when we're removed from the tree.
305 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
306 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(1);
307 layer_tree_host_
->SetRootLayer(nullptr);
308 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
311 class TestMailboxHolder
: public TextureLayer::TextureMailboxHolder
{
313 using TextureLayer::TextureMailboxHolder::Create
;
316 ~TestMailboxHolder() override
{}
319 class TextureLayerWithMailboxTest
: public TextureLayerTest
{
321 void TearDown() override
{
322 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
323 EXPECT_CALL(test_data_
.mock_callback_
,
324 Release(test_data_
.mailbox_name1_
,
325 test_data_
.sync_point1_
,
327 TextureLayerTest::TearDown();
331 TEST_F(TextureLayerWithMailboxTest
, ReplaceMailboxOnMainThreadBeforeCommit
) {
332 scoped_refptr
<TextureLayer
> test_layer
=
333 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
334 ASSERT_TRUE(test_layer
.get());
336 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
337 layer_tree_host_
->SetRootLayer(test_layer
);
338 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
340 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
341 test_layer
->SetTextureMailbox(
342 test_data_
.mailbox1_
,
343 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
344 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
346 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
347 EXPECT_CALL(test_data_
.mock_callback_
,
348 Release(test_data_
.mailbox_name1_
,
349 test_data_
.sync_point1_
,
352 test_layer
->SetTextureMailbox(
353 test_data_
.mailbox2_
,
354 SingleReleaseCallback::Create(test_data_
.release_mailbox2_
));
355 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
356 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
358 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
359 EXPECT_CALL(test_data_
.mock_callback_
,
360 Release(test_data_
.mailbox_name2_
,
361 test_data_
.sync_point2_
,
364 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
365 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
366 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
368 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
369 test_layer
->SetTextureMailbox(
370 test_data_
.mailbox3_
,
371 SingleReleaseCallback::Create(test_data_
.release_mailbox3_
));
372 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
373 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
375 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
376 EXPECT_CALL(test_data_
.mock_callback_
,
377 Release2(test_data_
.shared_bitmap_
.get(), 0, false)).Times(1);
378 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
379 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
380 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
383 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
384 test_layer
->SetTextureMailbox(
385 test_data_
.mailbox1_
,
386 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
389 TEST_F(TextureLayerTest
, SetTextureMailboxWithoutReleaseCallback
) {
390 scoped_refptr
<TextureLayer
> test_layer
=
391 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
392 ASSERT_TRUE(test_layer
.get());
394 // These use the same gpu::Mailbox, but different sync points.
395 TextureMailbox
mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D
, 1);
396 TextureMailbox
mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D
, 2);
398 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
399 layer_tree_host_
->SetRootLayer(test_layer
);
400 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
402 // Set the mailbox the first time. It should cause a commit.
403 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
404 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox1
);
405 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
407 // Set the mailbox again with a new sync point, as the backing texture has
408 // been updated. It should cause a new commit.
409 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
410 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox2
);
411 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
414 class TextureLayerMailboxHolderTest
: public TextureLayerTest
{
416 TextureLayerMailboxHolderTest()
417 : main_thread_("MAIN") {
418 main_thread_
.Start();
419 main_thread_
.message_loop()->task_runner()->PostTask(
420 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain
,
421 base::Unretained(this)));
425 void Wait(const base::Thread
& thread
) {
426 bool manual_reset
= false;
427 bool initially_signaled
= false;
428 base::WaitableEvent
event(manual_reset
, initially_signaled
);
429 thread
.message_loop()->task_runner()->PostTask(
431 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
435 void CreateMainRef() {
436 main_ref_
= TestMailboxHolder::Create(
437 test_data_
.mailbox1_
,
438 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
)).Pass();
441 void ReleaseMainRef() { main_ref_
= nullptr; }
443 void CreateImplRef(scoped_ptr
<SingleReleaseCallbackImpl
>* impl_ref
) {
444 *impl_ref
= main_ref_
->holder()->GetCallbackForImplThread();
447 void CapturePostTasksAndWait(base::WaitableEvent
* begin_capture
,
448 base::WaitableEvent
* wait_for_capture
,
449 base::WaitableEvent
* stop_capture
) {
450 begin_capture
->Wait();
451 BlockingTaskRunner::CapturePostTasks
capture(
452 main_thread_task_runner_
.get());
453 wait_for_capture
->Signal();
454 stop_capture
->Wait();
458 void InitializeOnMain() {
459 main_thread_task_runner_
=
460 BlockingTaskRunner::Create(main_thread_
.task_runner());
463 scoped_ptr
<TestMailboxHolder::MainThreadReference
>
465 base::Thread main_thread_
;
466 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
469 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_BothReleaseThenMain
) {
470 scoped_refptr
<TextureLayer
> test_layer
=
471 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
472 ASSERT_TRUE(test_layer
.get());
474 main_thread_
.message_loop()->task_runner()->PostTask(
475 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
476 base::Unretained(this)));
480 // The texture layer is attached to compositor1, and passes a reference to its
482 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
483 main_thread_
.message_loop()->task_runner()->PostTask(
484 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
485 base::Unretained(this), &compositor1
));
487 // Then the texture layer is removed and attached to compositor2, and passes a
488 // reference to its impl tree.
489 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
490 main_thread_
.message_loop()->task_runner()->PostTask(
491 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
492 base::Unretained(this), &compositor2
));
495 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
497 // The compositors both destroy their impl trees before the main thread layer
499 compositor1
->Run(100, false, main_thread_task_runner_
.get());
500 compositor2
->Run(200, false, main_thread_task_runner_
.get());
504 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
505 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
507 // The main thread ref is the last one, so the mailbox is released back to the
508 // embedder, with the last sync point provided by the impl trees.
509 EXPECT_CALL(test_data_
.mock_callback_
,
510 Release(test_data_
.mailbox_name1_
, 200, false)).Times(1);
512 main_thread_
.message_loop()->task_runner()->PostTask(
513 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
514 base::Unretained(this)));
516 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
519 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleaseBetween
) {
520 scoped_refptr
<TextureLayer
> test_layer
=
521 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
522 ASSERT_TRUE(test_layer
.get());
524 main_thread_
.message_loop()->task_runner()->PostTask(
525 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
526 base::Unretained(this)));
530 // The texture layer is attached to compositor1, and passes a reference to its
532 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
533 main_thread_
.message_loop()->task_runner()->PostTask(
534 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
535 base::Unretained(this), &compositor1
));
537 // Then the texture layer is removed and attached to compositor2, and passes a
538 // reference to its impl tree.
539 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
540 main_thread_
.message_loop()->task_runner()->PostTask(
541 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
542 base::Unretained(this), &compositor2
));
545 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
547 // One compositor destroys their impl tree.
548 compositor1
->Run(100, false, main_thread_task_runner_
.get());
550 // Then the main thread reference is destroyed.
551 main_thread_
.message_loop()->task_runner()->PostTask(
552 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
553 base::Unretained(this)));
557 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
558 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
560 // The second impl reference is destroyed last, causing the mailbox to be
561 // released back to the embedder with the last sync point from the impl tree.
562 EXPECT_CALL(test_data_
.mock_callback_
,
563 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
565 compositor2
->Run(200, true, main_thread_task_runner_
.get());
567 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
570 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleasedFirst
) {
571 scoped_refptr
<TextureLayer
> test_layer
=
572 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
573 ASSERT_TRUE(test_layer
.get());
575 main_thread_
.message_loop()->task_runner()->PostTask(
576 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
577 base::Unretained(this)));
581 // The texture layer is attached to compositor1, and passes a reference to its
583 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
584 main_thread_
.message_loop()->task_runner()->PostTask(
585 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
586 base::Unretained(this), &compositor1
));
588 // Then the texture layer is removed and attached to compositor2, and passes a
589 // reference to its impl tree.
590 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
591 main_thread_
.message_loop()->task_runner()->PostTask(
592 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
593 base::Unretained(this), &compositor2
));
596 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
598 // The main thread reference is destroyed first.
599 main_thread_
.message_loop()->task_runner()->PostTask(
600 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
601 base::Unretained(this)));
603 // One compositor destroys their impl tree.
604 compositor2
->Run(200, false, main_thread_task_runner_
.get());
608 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
609 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
611 // The second impl reference is destroyed last, causing the mailbox to be
612 // released back to the embedder with the last sync point from the impl tree.
613 EXPECT_CALL(test_data_
.mock_callback_
,
614 Release(test_data_
.mailbox_name1_
, 100, true)).Times(1);
616 compositor1
->Run(100, true, main_thread_task_runner_
.get());
618 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
621 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_SecondImplRefShortcut
) {
622 scoped_refptr
<TextureLayer
> test_layer
=
623 TextureLayer::CreateForMailbox(layer_settings_
, nullptr);
624 ASSERT_TRUE(test_layer
.get());
626 main_thread_
.message_loop()->task_runner()->PostTask(
627 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
628 base::Unretained(this)));
632 // The texture layer is attached to compositor1, and passes a reference to its
634 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
635 main_thread_
.message_loop()->task_runner()->PostTask(
636 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
637 base::Unretained(this), &compositor1
));
639 // Then the texture layer is removed and attached to compositor2, and passes a
640 // reference to its impl tree.
641 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
642 main_thread_
.message_loop()->task_runner()->PostTask(
643 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
644 base::Unretained(this), &compositor2
));
647 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
649 // The main thread reference is destroyed first.
650 main_thread_
.message_loop()->task_runner()->PostTask(
651 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
652 base::Unretained(this)));
654 EXPECT_CALL(test_data_
.mock_callback_
,
655 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
657 bool manual_reset
= false;
658 bool initially_signaled
= false;
659 base::WaitableEvent
begin_capture(manual_reset
, initially_signaled
);
660 base::WaitableEvent
wait_for_capture(manual_reset
, initially_signaled
);
661 base::WaitableEvent
stop_capture(manual_reset
, initially_signaled
);
663 // Post a task to start capturing tasks on the main thread. This will block
664 // the main thread until we signal the |stop_capture| event.
665 main_thread_
.message_loop()->task_runner()->PostTask(
667 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait
,
668 base::Unretained(this), &begin_capture
, &wait_for_capture
,
671 // Before the main thread capturing starts, one compositor destroys their
672 // impl reference. Since capturing did not start, this gets post-tasked to
674 compositor1
->Run(100, false, main_thread_task_runner_
.get());
676 // Start capturing on the main thread.
677 begin_capture
.Signal();
678 wait_for_capture
.Wait();
680 // Meanwhile, the second compositor released its impl reference, but this task
681 // gets shortcutted directly to the main thread. This means the reference is
682 // released before compositor1, whose reference will be released later when
683 // the post-task is serviced. But since it was destroyed _on the impl thread_
684 // last, its sync point values should be used.
685 compositor2
->Run(200, true, main_thread_task_runner_
.get());
687 stop_capture
.Signal();
690 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
693 class TextureLayerImplWithMailboxThreadedCallback
: public LayerTreeTest
{
695 TextureLayerImplWithMailboxThreadedCallback()
696 : callback_count_(0),
699 // Make sure callback is received on main and doesn't block the impl thread.
700 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
701 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
702 EXPECT_FALSE(lost_resource
);
706 void SetMailbox(char mailbox_char
) {
707 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
708 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
710 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback
,
711 base::Unretained(this)));
712 layer_
->SetTextureMailbox(
713 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
717 void BeginTest() override
{
718 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
720 gfx::Size
bounds(100, 100);
721 root_
= Layer::Create(layer_settings());
722 root_
->SetBounds(bounds
);
724 layer_
= TextureLayer::CreateForMailbox(layer_settings(), nullptr);
725 layer_
->SetIsDrawable(true);
726 layer_
->SetBounds(bounds
);
728 root_
->AddChild(layer_
);
729 layer_tree_host()->SetRootLayer(root_
);
730 layer_tree_host()->SetViewportSize(bounds
);
732 EXPECT_EQ(0, callback_count_
);
734 // Case #1: change mailbox before the commit. The old mailbox should be
735 // released immediately.
737 EXPECT_EQ(1, callback_count_
);
738 PostSetNeedsCommitToMainThread();
741 void DidCommit() override
{
743 switch (commit_count_
) {
745 // Case #2: change mailbox after the commit (and draw), where the
746 // layer draws. The old mailbox should be released during the next
749 EXPECT_EQ(1, callback_count_
);
752 EXPECT_EQ(2, callback_count_
);
753 // Case #3: change mailbox when the layer doesn't draw. The old
754 // mailbox should be released during the next commit.
755 layer_
->SetBounds(gfx::Size());
759 EXPECT_EQ(3, callback_count_
);
760 // Case #4: release mailbox that was committed but never drawn. The
761 // old mailbox should be released during the next commit.
762 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
765 if (layer_tree_host()->settings().impl_side_painting
) {
766 // With impl painting, the texture mailbox will still be on the impl
767 // thread when the commit finishes, because the layer is not drawble
768 // when it has no texture mailbox, and thus does not block the commit
769 // on activation. So, we wait for activation.
770 // TODO(danakj): fix this. crbug.com/277953
771 layer_tree_host()->SetNeedsCommit();
777 EXPECT_EQ(4, callback_count_
);
778 // Restore a mailbox for the next step.
782 // Case #5: remove layer from tree. Callback should *not* be called, the
783 // mailbox is returned to the main thread.
784 EXPECT_EQ(4, callback_count_
);
785 layer_
->RemoveFromParent();
788 if (layer_tree_host()->settings().impl_side_painting
) {
789 // With impl painting, the texture mailbox will still be on the impl
790 // thread when the commit finishes, because the layer is not around to
791 // block the commit on activation anymore. So, we wait for activation.
792 // TODO(danakj): fix this. crbug.com/277953
793 layer_tree_host()->SetNeedsCommit();
799 EXPECT_EQ(4, callback_count_
);
800 // Resetting the mailbox will call the callback now.
801 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
802 EXPECT_EQ(5, callback_count_
);
811 void AfterTest() override
{}
814 base::ThreadChecker main_thread_
;
817 scoped_refptr
<Layer
> root_
;
818 scoped_refptr
<TextureLayer
> layer_
;
821 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
822 TextureLayerImplWithMailboxThreadedCallback
);
825 class TextureLayerMailboxIsActivatedDuringCommit
: public LayerTreeTest
{
827 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
829 static void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {}
831 void SetMailbox(char mailbox_char
) {
832 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
834 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback
));
835 layer_
->SetTextureMailbox(
836 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
840 void BeginTest() override
{
841 gfx::Size
bounds(100, 100);
842 root_
= Layer::Create(layer_settings());
843 root_
->SetBounds(bounds
);
845 layer_
= TextureLayer::CreateForMailbox(layer_settings(), nullptr);
846 layer_
->SetIsDrawable(true);
847 layer_
->SetBounds(bounds
);
849 root_
->AddChild(layer_
);
850 layer_tree_host()->SetRootLayer(root_
);
851 layer_tree_host()->SetViewportSize(bounds
);
854 PostSetNeedsCommitToMainThread();
857 void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
861 void DidCommit() override
{
862 switch (layer_tree_host()->source_frame_number()) {
864 // The first mailbox has been activated. Set a new mailbox, and
865 // expect the next commit to finish *after* it is activated.
869 // The second mailbox has been activated. Remove the layer from
870 // the tree to cause another commit/activation. The commit should
871 // finish *after* the layer is removed from the active tree.
872 layer_
->RemoveFromParent();
880 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
881 switch (host_impl
->active_tree()->source_frame_number()) {
883 // The activate for the 1st mailbox should have happened before now.
884 EXPECT_EQ(1, activate_count_
);
888 // The activate for the 2nd mailbox should have happened before now.
889 EXPECT_EQ(2, activate_count_
);
893 // The activate to remove the layer should have happened before now.
894 EXPECT_EQ(3, activate_count_
);
904 void AfterTest() override
{}
907 scoped_refptr
<Layer
> root_
;
908 scoped_refptr
<TextureLayer
> layer_
;
911 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
912 TextureLayerMailboxIsActivatedDuringCommit
);
914 class TextureLayerImplWithMailboxTest
: public TextureLayerTest
{
916 TextureLayerImplWithMailboxTest()
918 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)) {}
920 void SetUp() override
{
921 TextureLayerTest::SetUp();
922 layer_tree_host_
= MockLayerTreeHost::Create(&fake_client_
);
923 EXPECT_TRUE(host_impl_
.InitializeRenderer(FakeOutputSurface::Create3d()));
926 bool WillDraw(TextureLayerImpl
* layer
, DrawMode mode
) {
927 bool will_draw
= layer
->WillDraw(
928 mode
, host_impl_
.active_tree()->resource_provider());
930 layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
934 FakeLayerTreeHostClient fake_client_
;
937 // Test conditions for results of TextureLayerImpl::WillDraw under
938 // different configurations of different mailbox, texture_id, and draw_mode.
939 TEST_F(TextureLayerImplWithMailboxTest
, TestWillDraw
) {
941 test_data_
.mock_callback_
,
942 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
944 EXPECT_CALL(test_data_
.mock_callback_
,
945 ReleaseImpl2(test_data_
.shared_bitmap_
.get(), 0, false, _
))
949 scoped_ptr
<TextureLayerImpl
> impl_layer
=
950 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
951 impl_layer
->SetTextureMailbox(
952 test_data_
.mailbox1_
,
953 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
954 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
958 scoped_ptr
<TextureLayerImpl
> impl_layer
=
959 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
960 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
961 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
965 // Software resource.
966 scoped_ptr
<TextureLayerImpl
> impl_layer
=
967 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
968 impl_layer
->SetTextureMailbox(
969 test_data_
.mailbox3_
,
970 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
971 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
976 scoped_ptr
<TextureLayerImpl
> impl_layer
=
977 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
978 impl_layer
->SetTextureMailbox(
979 test_data_
.mailbox1_
,
980 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
981 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
985 scoped_ptr
<TextureLayerImpl
> impl_layer
=
986 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
987 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
988 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
992 // Software resource.
993 scoped_ptr
<TextureLayerImpl
> impl_layer
=
994 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
995 impl_layer
->SetTextureMailbox(
996 test_data_
.mailbox3_
,
997 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
998 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
1001 // Resourceless software mode.
1003 scoped_ptr
<TextureLayerImpl
> impl_layer
=
1004 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1005 impl_layer
->SetTextureMailbox(
1006 test_data_
.mailbox1_
,
1007 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1008 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_RESOURCELESS_SOFTWARE
));
1012 TEST_F(TextureLayerImplWithMailboxTest
, TestImplLayerCallbacks
) {
1013 host_impl_
.CreatePendingTree();
1014 scoped_ptr
<TextureLayerImpl
> pending_layer
;
1015 pending_layer
= TextureLayerImpl::Create(host_impl_
.pending_tree(), 1);
1016 ASSERT_TRUE(pending_layer
);
1018 scoped_ptr
<LayerImpl
> active_layer(
1019 pending_layer
->CreateLayerImpl(host_impl_
.active_tree()));
1020 ASSERT_TRUE(active_layer
);
1022 pending_layer
->SetTextureMailbox(
1023 test_data_
.mailbox1_
,
1024 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1026 // Test multiple commits without an activation.
1028 test_data_
.mock_callback_
,
1029 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1031 pending_layer
->SetTextureMailbox(
1032 test_data_
.mailbox2_
,
1033 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox2_impl_
));
1034 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1036 // Test callback after activation.
1037 pending_layer
->PushPropertiesTo(active_layer
.get());
1038 active_layer
->DidBecomeActive();
1040 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1041 pending_layer
->SetTextureMailbox(
1042 test_data_
.mailbox1_
,
1043 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1044 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1046 EXPECT_CALL(test_data_
.mock_callback_
,
1047 ReleaseImpl(test_data_
.mailbox_name2_
, _
, false, _
)).Times(1);
1048 pending_layer
->PushPropertiesTo(active_layer
.get());
1049 active_layer
->DidBecomeActive();
1050 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1052 // Test resetting the mailbox.
1053 EXPECT_CALL(test_data_
.mock_callback_
,
1054 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1055 pending_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1056 pending_layer
->PushPropertiesTo(active_layer
.get());
1057 active_layer
->DidBecomeActive();
1058 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1062 test_data_
.mock_callback_
,
1063 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1065 pending_layer
->SetTextureMailbox(
1066 test_data_
.mailbox1_
,
1067 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1070 TEST_F(TextureLayerImplWithMailboxTest
,
1071 TestDestructorCallbackOnCreatedResource
) {
1072 scoped_ptr
<TextureLayerImpl
> impl_layer
;
1073 impl_layer
= TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1074 ASSERT_TRUE(impl_layer
);
1076 EXPECT_CALL(test_data_
.mock_callback_
,
1077 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1078 impl_layer
->SetTextureMailbox(
1079 test_data_
.mailbox1_
,
1080 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1081 impl_layer
->DidBecomeActive();
1082 EXPECT_TRUE(impl_layer
->WillDraw(
1083 DRAW_MODE_HARDWARE
, host_impl_
.active_tree()->resource_provider()));
1084 impl_layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
1085 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1088 TEST_F(TextureLayerImplWithMailboxTest
, TestCallbackOnInUseResource
) {
1089 ResourceProvider
* provider
= host_impl_
.active_tree()->resource_provider();
1090 ResourceId id
= provider
->CreateResourceFromTextureMailbox(
1091 test_data_
.mailbox1_
,
1092 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1093 provider
->AllocateForTesting(id
);
1095 // Transfer some resources to the parent.
1096 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1097 resource_ids_to_transfer
.push_back(id
);
1098 TransferableResourceArray list
;
1099 provider
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1100 EXPECT_TRUE(provider
->InUseByConsumer(id
));
1101 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1102 provider
->DeleteResource(id
);
1103 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1104 EXPECT_CALL(test_data_
.mock_callback_
,
1105 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1106 ReturnedResourceArray returned
;
1107 TransferableResource::ReturnResources(list
, &returned
);
1108 provider
->ReceiveReturnsFromParent(returned
);
1111 // Checks that TextureLayer::Update does not cause an extra commit when setting
1112 // the texture mailbox.
1113 class TextureLayerNoExtraCommitForMailboxTest
1114 : public LayerTreeTest
,
1115 public TextureLayerClient
{
1117 // TextureLayerClient implementation.
1118 bool PrepareTextureMailbox(
1119 TextureMailbox
* texture_mailbox
,
1120 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1121 bool use_shared_memory
) override
{
1122 if (layer_tree_host()->source_frame_number() == 1) {
1123 // Once this has been committed, the mailbox will be released.
1124 *texture_mailbox
= TextureMailbox();
1128 *texture_mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1129 *release_callback
= SingleReleaseCallback::Create(
1130 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased
,
1131 base::Unretained(this)));
1135 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1136 // Source frame number during callback is the same as the source frame
1137 // on which it was released.
1138 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1142 void SetupTree() override
{
1143 scoped_refptr
<Layer
> root
= Layer::Create(layer_settings());
1144 root
->SetBounds(gfx::Size(10, 10));
1145 root
->SetIsDrawable(true);
1147 texture_layer_
= TextureLayer::CreateForMailbox(layer_settings(), this);
1148 texture_layer_
->SetBounds(gfx::Size(10, 10));
1149 texture_layer_
->SetIsDrawable(true);
1150 root
->AddChild(texture_layer_
);
1152 layer_tree_host()->SetRootLayer(root
);
1153 LayerTreeTest::SetupTree();
1156 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1158 void DidCommitAndDrawFrame() override
{
1159 switch (layer_tree_host()->source_frame_number()) {
1161 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1162 // Invalidate the texture layer to clear the mailbox before
1164 texture_layer_
->SetNeedsDisplay();
1174 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1175 ASSERT_TRUE(result
);
1176 DelegatedFrameData
* delegated_frame_data
=
1177 output_surface()->last_sent_frame().delegated_frame_data
.get();
1178 if (!delegated_frame_data
)
1181 // Return all resources immediately.
1182 TransferableResourceArray resources_to_return
=
1183 output_surface()->resources_held_by_parent();
1185 CompositorFrameAck ack
;
1186 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1187 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1188 host_impl
->ReclaimResources(&ack
);
1191 void AfterTest() override
{}
1194 scoped_refptr
<TextureLayer
> texture_layer_
;
1197 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest
);
1199 // Checks that changing a mailbox in the client for a TextureLayer that's
1200 // invisible correctly works and uses the new mailbox as soon as the layer
1201 // becomes visible (and returns the old one).
1202 class TextureLayerChangeInvisibleMailboxTest
1203 : public LayerTreeTest
,
1204 public TextureLayerClient
{
1206 TextureLayerChangeInvisibleMailboxTest()
1207 : mailbox_changed_(true),
1208 mailbox_returned_(0),
1211 mailbox_
= MakeMailbox('1');
1214 // TextureLayerClient implementation.
1215 bool PrepareTextureMailbox(
1216 TextureMailbox
* mailbox
,
1217 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1218 bool use_shared_memory
) override
{
1220 if (!mailbox_changed_
)
1222 *mailbox
= mailbox_
;
1223 *release_callback
= SingleReleaseCallback::Create(
1224 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased
,
1225 base::Unretained(this)));
1229 TextureMailbox
MakeMailbox(char name
) {
1230 return TextureMailbox(MailboxFromChar(name
), GL_TEXTURE_2D
, 0);
1233 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1234 ++mailbox_returned_
;
1237 void SetupTree() override
{
1238 scoped_refptr
<Layer
> root
= Layer::Create(layer_settings());
1239 root
->SetBounds(gfx::Size(10, 10));
1240 root
->SetIsDrawable(true);
1242 solid_layer_
= SolidColorLayer::Create(layer_settings());
1243 solid_layer_
->SetBounds(gfx::Size(10, 10));
1244 solid_layer_
->SetIsDrawable(true);
1245 solid_layer_
->SetBackgroundColor(SK_ColorWHITE
);
1246 root
->AddChild(solid_layer_
);
1248 parent_layer_
= Layer::Create(layer_settings());
1249 parent_layer_
->SetBounds(gfx::Size(10, 10));
1250 parent_layer_
->SetIsDrawable(true);
1251 root
->AddChild(parent_layer_
);
1253 texture_layer_
= TextureLayer::CreateForMailbox(layer_settings(), this);
1254 texture_layer_
->SetBounds(gfx::Size(10, 10));
1255 texture_layer_
->SetIsDrawable(true);
1256 parent_layer_
->AddChild(texture_layer_
);
1258 layer_tree_host()->SetRootLayer(root
);
1259 LayerTreeTest::SetupTree();
1262 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1264 void DidCommitAndDrawFrame() override
{
1266 switch (commit_count_
) {
1268 // We should have updated the layer, committing the texture.
1269 EXPECT_EQ(1, prepare_called_
);
1270 // Make layer invisible.
1271 parent_layer_
->SetOpacity(0.f
);
1274 // Layer shouldn't have been updated.
1275 EXPECT_EQ(1, prepare_called_
);
1276 // Change the texture.
1277 mailbox_
= MakeMailbox('2');
1278 mailbox_changed_
= true;
1279 texture_layer_
->SetNeedsDisplay();
1280 // Force a change to make sure we draw a frame.
1281 solid_layer_
->SetBackgroundColor(SK_ColorGRAY
);
1284 // Layer shouldn't have been updated.
1285 EXPECT_EQ(1, prepare_called_
);
1286 // So the old mailbox isn't returned yet.
1287 EXPECT_EQ(0, mailbox_returned_
);
1288 // Make layer visible again.
1289 parent_layer_
->SetOpacity(1.f
);
1292 // Layer should have been updated.
1293 EXPECT_EQ(2, prepare_called_
);
1294 // So the old mailbox should have been returned already.
1295 EXPECT_EQ(1, mailbox_returned_
);
1296 texture_layer_
->ClearClient();
1299 EXPECT_EQ(2, mailbox_returned_
);
1308 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1309 ASSERT_TRUE(result
);
1310 DelegatedFrameData
* delegated_frame_data
=
1311 output_surface()->last_sent_frame().delegated_frame_data
.get();
1312 if (!delegated_frame_data
)
1315 // Return all resources immediately.
1316 TransferableResourceArray resources_to_return
=
1317 output_surface()->resources_held_by_parent();
1319 CompositorFrameAck ack
;
1320 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1321 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1322 host_impl
->ReclaimResources(&ack
);
1325 void AfterTest() override
{}
1328 scoped_refptr
<SolidColorLayer
> solid_layer_
;
1329 scoped_refptr
<Layer
> parent_layer_
;
1330 scoped_refptr
<TextureLayer
> texture_layer_
;
1332 // Used on the main thread.
1333 bool mailbox_changed_
;
1334 TextureMailbox mailbox_
;
1335 int mailbox_returned_
;
1336 int prepare_called_
;
1340 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest
);
1342 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1343 // the mailbox back to TextureLayerClient.
1344 class TextureLayerReleaseResourcesBase
1345 : public LayerTreeTest
,
1346 public TextureLayerClient
{
1348 // TextureLayerClient implementation.
1349 bool PrepareTextureMailbox(
1350 TextureMailbox
* mailbox
,
1351 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1352 bool use_shared_memory
) override
{
1353 *mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1354 *release_callback
= SingleReleaseCallback::Create(
1355 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased
,
1356 base::Unretained(this)));
1360 void MailboxReleased(unsigned sync_point
, bool lost_resource
) {
1361 mailbox_released_
= true;
1364 void SetupTree() override
{
1365 LayerTreeTest::SetupTree();
1367 scoped_refptr
<TextureLayer
> texture_layer
=
1368 TextureLayer::CreateForMailbox(layer_settings(), this);
1369 texture_layer
->SetBounds(gfx::Size(10, 10));
1370 texture_layer
->SetIsDrawable(true);
1372 layer_tree_host()->root_layer()->AddChild(texture_layer
);
1375 void BeginTest() override
{
1376 mailbox_released_
= false;
1377 PostSetNeedsCommitToMainThread();
1380 void DidCommitAndDrawFrame() override
{ EndTest(); }
1382 void AfterTest() override
{ EXPECT_TRUE(mailbox_released_
); }
1385 bool mailbox_released_
;
1388 class TextureLayerReleaseResourcesAfterCommit
1389 : public TextureLayerReleaseResourcesBase
{
1391 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
1392 LayerTreeImpl
* tree
= nullptr;
1393 tree
= host_impl
->sync_tree();
1394 tree
->root_layer()->children()[0]->ReleaseResources();
1398 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit
);
1400 class TextureLayerReleaseResourcesAfterActivate
1401 : public TextureLayerReleaseResourcesBase
{
1403 void DidActivateTreeOnThread(LayerTreeHostImpl
* host_impl
) override
{
1404 host_impl
->active_tree()->root_layer()->children()[0]->ReleaseResources();
1408 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate
);
1410 class TextureLayerWithMailboxMainThreadDeleted
: public LayerTreeTest
{
1412 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1413 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1414 EXPECT_FALSE(lost_resource
);
1419 void SetMailbox(char mailbox_char
) {
1420 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1421 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1423 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback
,
1424 base::Unretained(this)));
1425 layer_
->SetTextureMailbox(
1426 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1430 void SetupTree() override
{
1431 gfx::Size
bounds(100, 100);
1432 root_
= Layer::Create(layer_settings());
1433 root_
->SetBounds(bounds
);
1435 layer_
= TextureLayer::CreateForMailbox(layer_settings(), nullptr);
1436 layer_
->SetIsDrawable(true);
1437 layer_
->SetBounds(bounds
);
1439 root_
->AddChild(layer_
);
1440 layer_tree_host()->SetRootLayer(root_
);
1441 layer_tree_host()->SetViewportSize(bounds
);
1444 void BeginTest() override
{
1445 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1447 callback_count_
= 0;
1449 // Set the mailbox on the main thread.
1451 EXPECT_EQ(0, callback_count_
);
1453 PostSetNeedsCommitToMainThread();
1456 void DidCommitAndDrawFrame() override
{
1457 switch (layer_tree_host()->source_frame_number()) {
1459 // Delete the TextureLayer on the main thread while the mailbox is in
1461 layer_
->RemoveFromParent();
1467 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1470 base::ThreadChecker main_thread_
;
1471 int callback_count_
;
1472 scoped_refptr
<Layer
> root_
;
1473 scoped_refptr
<TextureLayer
> layer_
;
1476 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1477 TextureLayerWithMailboxMainThreadDeleted
);
1479 class TextureLayerWithMailboxImplThreadDeleted
: public LayerTreeTest
{
1481 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1482 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1483 EXPECT_FALSE(lost_resource
);
1488 void SetMailbox(char mailbox_char
) {
1489 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1490 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1492 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback
,
1493 base::Unretained(this)));
1494 layer_
->SetTextureMailbox(
1495 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1499 void SetupTree() override
{
1500 gfx::Size
bounds(100, 100);
1501 root_
= Layer::Create(layer_settings());
1502 root_
->SetBounds(bounds
);
1504 layer_
= TextureLayer::CreateForMailbox(layer_settings(), nullptr);
1505 layer_
->SetIsDrawable(true);
1506 layer_
->SetBounds(bounds
);
1508 root_
->AddChild(layer_
);
1509 layer_tree_host()->SetRootLayer(root_
);
1510 layer_tree_host()->SetViewportSize(bounds
);
1513 void BeginTest() override
{
1514 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1516 callback_count_
= 0;
1518 // Set the mailbox on the main thread.
1520 EXPECT_EQ(0, callback_count_
);
1522 PostSetNeedsCommitToMainThread();
1525 void DidCommitAndDrawFrame() override
{
1526 switch (layer_tree_host()->source_frame_number()) {
1528 // Remove the TextureLayer on the main thread while the mailbox is in
1529 // the impl tree, but don't delete the TextureLayer until after the impl
1530 // tree side is deleted.
1531 layer_
->RemoveFromParent();
1539 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1542 base::ThreadChecker main_thread_
;
1543 int callback_count_
;
1544 scoped_refptr
<Layer
> root_
;
1545 scoped_refptr
<TextureLayer
> layer_
;
1548 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1549 TextureLayerWithMailboxImplThreadDeleted
);