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 explicit MockLayerTreeHost(FakeLayerTreeHostClient
* client
)
58 : LayerTreeHost(client
, nullptr, nullptr, nullptr, LayerTreeSettings()) {
59 InitializeSingleThreaded(client
, base::ThreadTaskRunnerHandle::Get(),
63 MOCK_METHOD0(SetNeedsCommit
, void());
64 MOCK_METHOD0(SetNeedsUpdateLayers
, void());
65 MOCK_METHOD0(StartRateLimiter
, void());
66 MOCK_METHOD0(StopRateLimiter
, void());
69 class FakeTextureLayerClient
: public TextureLayerClient
{
71 FakeTextureLayerClient() : mailbox_changed_(true) {}
73 bool PrepareTextureMailbox(
74 TextureMailbox
* mailbox
,
75 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
76 bool use_shared_memory
) override
{
77 if (!mailbox_changed_
)
81 *release_callback
= release_callback_
.Pass();
82 mailbox_changed_
= false;
86 void set_mailbox(const TextureMailbox
& mailbox
,
87 scoped_ptr
<SingleReleaseCallback
> release_callback
) {
89 release_callback_
= release_callback
.Pass();
90 mailbox_changed_
= true;
94 TextureMailbox mailbox_
;
95 scoped_ptr
<SingleReleaseCallback
> release_callback_
;
96 bool mailbox_changed_
;
97 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient
);
100 class MockMailboxCallback
{
102 MOCK_METHOD3(Release
,
103 void(const gpu::Mailbox
& mailbox
,
105 bool lost_resource
));
106 MOCK_METHOD3(Release2
,
107 void(SharedBitmap
* shared_bitmap
,
109 bool lost_resource
));
110 MOCK_METHOD4(ReleaseImpl
,
111 void(const gpu::Mailbox
& mailbox
,
114 BlockingTaskRunner
* main_thread_task_runner
));
115 MOCK_METHOD4(ReleaseImpl2
,
116 void(SharedBitmap
* shared_bitmap
,
119 BlockingTaskRunner
* main_thread_task_runner
));
122 struct CommonMailboxObjects
{
123 explicit CommonMailboxObjects(SharedBitmapManager
* manager
)
124 : mailbox_name1_(MailboxFromChar('1')),
125 mailbox_name2_(MailboxFromChar('2')),
128 release_mailbox1_
= base::Bind(&MockMailboxCallback::Release
,
129 base::Unretained(&mock_callback_
),
131 release_mailbox2_
= base::Bind(&MockMailboxCallback::Release
,
132 base::Unretained(&mock_callback_
),
134 release_mailbox1_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
135 base::Unretained(&mock_callback_
),
137 release_mailbox2_impl_
= base::Bind(&MockMailboxCallback::ReleaseImpl
,
138 base::Unretained(&mock_callback_
),
140 const uint32 arbitrary_target1
= GL_TEXTURE_2D
;
141 const uint32 arbitrary_target2
= GL_TEXTURE_EXTERNAL_OES
;
142 mailbox1_
= TextureMailbox(mailbox_name1_
, arbitrary_target1
, sync_point1_
);
143 mailbox2_
= TextureMailbox(mailbox_name2_
, arbitrary_target2
, sync_point2_
);
144 gfx::Size
size(128, 128);
145 shared_bitmap_
= manager
->AllocateSharedBitmap(size
);
146 DCHECK(shared_bitmap_
);
148 base::Bind(&MockMailboxCallback::Release2
,
149 base::Unretained(&mock_callback_
), shared_bitmap_
.get());
150 release_mailbox3_impl_
=
151 base::Bind(&MockMailboxCallback::ReleaseImpl2
,
152 base::Unretained(&mock_callback_
), shared_bitmap_
.get());
153 mailbox3_
= TextureMailbox(shared_bitmap_
.get(), size
);
156 gpu::Mailbox mailbox_name1_
;
157 gpu::Mailbox mailbox_name2_
;
158 MockMailboxCallback mock_callback_
;
159 ReleaseCallback release_mailbox1_
;
160 ReleaseCallback release_mailbox2_
;
161 ReleaseCallback release_mailbox3_
;
162 ReleaseCallbackImpl release_mailbox1_impl_
;
163 ReleaseCallbackImpl release_mailbox2_impl_
;
164 ReleaseCallbackImpl release_mailbox3_impl_
;
165 TextureMailbox mailbox1_
;
166 TextureMailbox mailbox2_
;
167 TextureMailbox mailbox3_
;
170 scoped_ptr
<SharedBitmap
> shared_bitmap_
;
173 class TextureLayerTest
: public testing::Test
{
177 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)),
178 host_impl_(&proxy_
, &shared_bitmap_manager_
, &task_graph_runner_
),
179 test_data_(&shared_bitmap_manager_
) {}
182 void SetUp() override
{
183 layer_tree_host_
.reset(new MockLayerTreeHost(&fake_client_
));
184 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
185 layer_tree_host_
->SetViewportSize(gfx::Size(10, 10));
186 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
189 void TearDown() override
{
190 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
191 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
193 layer_tree_host_
->SetRootLayer(nullptr);
194 layer_tree_host_
= nullptr;
197 scoped_ptr
<MockLayerTreeHost
> layer_tree_host_
;
198 FakeImplProxy proxy_
;
199 FakeLayerTreeHostClient fake_client_
;
200 TestSharedBitmapManager shared_bitmap_manager_
;
201 TestTaskGraphRunner task_graph_runner_
;
202 FakeLayerTreeHostImpl host_impl_
;
203 CommonMailboxObjects test_data_
;
206 TEST_F(TextureLayerTest
, CheckPropertyChangeCausesCorrectBehavior
) {
207 scoped_refptr
<TextureLayer
> test_layer
=
208 TextureLayer::CreateForMailbox(nullptr);
209 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_
->SetRootLayer(test_layer
));
211 // Test properties that should call SetNeedsCommit. All properties need to
212 // be set to new values in order for SetNeedsCommit to be called.
213 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetFlipped(false));
214 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetNearestNeighbor(true));
215 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetUV(
216 gfx::PointF(0.25f
, 0.25f
), gfx::PointF(0.75f
, 0.75f
)));
217 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetVertexOpacity(
218 0.5f
, 0.5f
, 0.5f
, 0.5f
));
219 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetPremultipliedAlpha(false));
220 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetBlendBackgroundColor(true));
223 TEST_F(TextureLayerTest
, VisibleContentOpaqueRegion
) {
224 const gfx::Size
layer_bounds(100, 100);
225 const gfx::Rect
layer_rect(layer_bounds
);
226 const Region
layer_region(layer_rect
);
228 scoped_refptr
<TextureLayer
> layer
= TextureLayer::CreateForMailbox(nullptr);
229 layer
->SetBounds(layer_bounds
);
230 layer
->draw_properties().visible_content_rect
= layer_rect
;
231 layer
->SetBlendBackgroundColor(true);
233 // Verify initial conditions.
234 EXPECT_FALSE(layer
->contents_opaque());
235 EXPECT_EQ(0u, layer
->background_color());
236 EXPECT_EQ(Region().ToString(),
237 layer
->VisibleContentOpaqueRegion().ToString());
239 // Opaque background.
240 layer
->SetBackgroundColor(SK_ColorWHITE
);
241 EXPECT_EQ(layer_region
.ToString(),
242 layer
->VisibleContentOpaqueRegion().ToString());
244 // Transparent background.
245 layer
->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
246 EXPECT_EQ(Region().ToString(),
247 layer
->VisibleContentOpaqueRegion().ToString());
250 TEST_F(TextureLayerTest
, RateLimiter
) {
251 FakeTextureLayerClient client
;
252 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(
254 test_layer
->SetIsDrawable(true);
255 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
256 layer_tree_host_
->SetRootLayer(test_layer
);
258 // Don't rate limit until we invalidate.
259 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
260 test_layer
->SetRateLimitContext(true);
261 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
263 // Do rate limit after we invalidate.
264 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
265 test_layer
->SetNeedsDisplay();
266 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
268 // Stop rate limiter when we don't want it any more.
269 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
270 test_layer
->SetRateLimitContext(false);
271 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
273 // Or we clear the client.
274 test_layer
->SetRateLimitContext(true);
275 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
276 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
277 test_layer
->ClearClient();
278 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
280 // Reset to a layer with a client, that started the rate limiter.
281 test_layer
= TextureLayer::CreateForMailbox(
283 test_layer
->SetIsDrawable(true);
284 test_layer
->SetRateLimitContext(true);
285 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
286 layer_tree_host_
->SetRootLayer(test_layer
);
287 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
288 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
289 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
290 test_layer
->SetNeedsDisplay();
291 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
293 // Stop rate limiter when we're removed from the tree.
294 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
295 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(1);
296 layer_tree_host_
->SetRootLayer(nullptr);
297 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
300 class TestMailboxHolder
: public TextureLayer::TextureMailboxHolder
{
302 using TextureLayer::TextureMailboxHolder::Create
;
305 ~TestMailboxHolder() override
{}
308 class TextureLayerWithMailboxTest
: public TextureLayerTest
{
310 void TearDown() override
{
311 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
312 EXPECT_CALL(test_data_
.mock_callback_
,
313 Release(test_data_
.mailbox_name1_
,
314 test_data_
.sync_point1_
,
316 TextureLayerTest::TearDown();
320 TEST_F(TextureLayerWithMailboxTest
, ReplaceMailboxOnMainThreadBeforeCommit
) {
321 scoped_refptr
<TextureLayer
> test_layer
=
322 TextureLayer::CreateForMailbox(nullptr);
323 ASSERT_TRUE(test_layer
.get());
325 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
326 layer_tree_host_
->SetRootLayer(test_layer
);
327 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
329 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
330 test_layer
->SetTextureMailbox(
331 test_data_
.mailbox1_
,
332 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
333 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
335 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
336 EXPECT_CALL(test_data_
.mock_callback_
,
337 Release(test_data_
.mailbox_name1_
,
338 test_data_
.sync_point1_
,
341 test_layer
->SetTextureMailbox(
342 test_data_
.mailbox2_
,
343 SingleReleaseCallback::Create(test_data_
.release_mailbox2_
));
344 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
345 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
347 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
348 EXPECT_CALL(test_data_
.mock_callback_
,
349 Release(test_data_
.mailbox_name2_
,
350 test_data_
.sync_point2_
,
353 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
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 test_layer
->SetTextureMailbox(
359 test_data_
.mailbox3_
,
360 SingleReleaseCallback::Create(test_data_
.release_mailbox3_
));
361 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
362 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
364 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
365 EXPECT_CALL(test_data_
.mock_callback_
,
366 Release2(test_data_
.shared_bitmap_
.get(), 0, false)).Times(1);
367 test_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
368 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
369 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
372 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
373 test_layer
->SetTextureMailbox(
374 test_data_
.mailbox1_
,
375 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
378 TEST_F(TextureLayerTest
, SetTextureMailboxWithoutReleaseCallback
) {
379 scoped_refptr
<TextureLayer
> test_layer
=
380 TextureLayer::CreateForMailbox(nullptr);
381 ASSERT_TRUE(test_layer
.get());
383 // These use the same gpu::Mailbox, but different sync points.
384 TextureMailbox
mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D
, 1);
385 TextureMailbox
mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D
, 2);
387 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
388 layer_tree_host_
->SetRootLayer(test_layer
);
389 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
391 // Set the mailbox the first time. It should cause a commit.
392 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
393 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox1
);
394 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
396 // Set the mailbox again with a new sync point, as the backing texture has
397 // been updated. It should cause a new commit.
398 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
399 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox2
);
400 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
403 class TextureLayerMailboxHolderTest
: public TextureLayerTest
{
405 TextureLayerMailboxHolderTest()
406 : main_thread_("MAIN") {
407 main_thread_
.Start();
408 main_thread_
.message_loop()->task_runner()->PostTask(
409 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain
,
410 base::Unretained(this)));
414 void Wait(const base::Thread
& thread
) {
415 bool manual_reset
= false;
416 bool initially_signaled
= false;
417 base::WaitableEvent
event(manual_reset
, initially_signaled
);
418 thread
.message_loop()->task_runner()->PostTask(
420 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
424 void CreateMainRef() {
425 main_ref_
= TestMailboxHolder::Create(
426 test_data_
.mailbox1_
,
427 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
)).Pass();
430 void ReleaseMainRef() { main_ref_
= nullptr; }
432 void CreateImplRef(scoped_ptr
<SingleReleaseCallbackImpl
>* impl_ref
) {
433 *impl_ref
= main_ref_
->holder()->GetCallbackForImplThread();
436 void CapturePostTasksAndWait(base::WaitableEvent
* begin_capture
,
437 base::WaitableEvent
* wait_for_capture
,
438 base::WaitableEvent
* stop_capture
) {
439 begin_capture
->Wait();
440 BlockingTaskRunner::CapturePostTasks
capture(
441 main_thread_task_runner_
.get());
442 wait_for_capture
->Signal();
443 stop_capture
->Wait();
447 void InitializeOnMain() {
448 main_thread_task_runner_
=
449 BlockingTaskRunner::Create(main_thread_
.task_runner());
452 scoped_ptr
<TestMailboxHolder::MainThreadReference
>
454 base::Thread main_thread_
;
455 scoped_ptr
<BlockingTaskRunner
> main_thread_task_runner_
;
458 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_BothReleaseThenMain
) {
459 scoped_refptr
<TextureLayer
> test_layer
=
460 TextureLayer::CreateForMailbox(nullptr);
461 ASSERT_TRUE(test_layer
.get());
463 main_thread_
.message_loop()->task_runner()->PostTask(
464 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
465 base::Unretained(this)));
469 // The texture layer is attached to compositor1, and passes a reference to its
471 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
472 main_thread_
.message_loop()->task_runner()->PostTask(
473 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
474 base::Unretained(this), &compositor1
));
476 // Then the texture layer is removed and attached to compositor2, and passes a
477 // reference to its impl tree.
478 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
479 main_thread_
.message_loop()->task_runner()->PostTask(
480 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
481 base::Unretained(this), &compositor2
));
484 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
486 // The compositors both destroy their impl trees before the main thread layer
488 compositor1
->Run(100, false, main_thread_task_runner_
.get());
489 compositor2
->Run(200, false, main_thread_task_runner_
.get());
493 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
494 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
496 // The main thread ref is the last one, so the mailbox is released back to the
497 // embedder, with the last sync point provided by the impl trees.
498 EXPECT_CALL(test_data_
.mock_callback_
,
499 Release(test_data_
.mailbox_name1_
, 200, false)).Times(1);
501 main_thread_
.message_loop()->task_runner()->PostTask(
502 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
503 base::Unretained(this)));
505 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
508 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleaseBetween
) {
509 scoped_refptr
<TextureLayer
> test_layer
=
510 TextureLayer::CreateForMailbox(nullptr);
511 ASSERT_TRUE(test_layer
.get());
513 main_thread_
.message_loop()->task_runner()->PostTask(
514 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
515 base::Unretained(this)));
519 // The texture layer is attached to compositor1, and passes a reference to its
521 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
522 main_thread_
.message_loop()->task_runner()->PostTask(
523 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
524 base::Unretained(this), &compositor1
));
526 // Then the texture layer is removed and attached to compositor2, and passes a
527 // reference to its impl tree.
528 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
529 main_thread_
.message_loop()->task_runner()->PostTask(
530 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
531 base::Unretained(this), &compositor2
));
534 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
536 // One compositor destroys their impl tree.
537 compositor1
->Run(100, false, main_thread_task_runner_
.get());
539 // Then the main thread reference is destroyed.
540 main_thread_
.message_loop()->task_runner()->PostTask(
541 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
542 base::Unretained(this)));
546 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
547 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
549 // The second impl reference is destroyed last, causing the mailbox to be
550 // released back to the embedder with the last sync point from the impl tree.
551 EXPECT_CALL(test_data_
.mock_callback_
,
552 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
554 compositor2
->Run(200, true, main_thread_task_runner_
.get());
556 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
559 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleasedFirst
) {
560 scoped_refptr
<TextureLayer
> test_layer
=
561 TextureLayer::CreateForMailbox(nullptr);
562 ASSERT_TRUE(test_layer
.get());
564 main_thread_
.message_loop()->task_runner()->PostTask(
565 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
566 base::Unretained(this)));
570 // The texture layer is attached to compositor1, and passes a reference to its
572 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
573 main_thread_
.message_loop()->task_runner()->PostTask(
574 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
575 base::Unretained(this), &compositor1
));
577 // Then the texture layer is removed and attached to compositor2, and passes a
578 // reference to its impl tree.
579 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
580 main_thread_
.message_loop()->task_runner()->PostTask(
581 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
582 base::Unretained(this), &compositor2
));
585 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
587 // The main thread reference is destroyed first.
588 main_thread_
.message_loop()->task_runner()->PostTask(
589 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
590 base::Unretained(this)));
592 // One compositor destroys their impl tree.
593 compositor2
->Run(200, false, main_thread_task_runner_
.get());
597 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
598 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
600 // The second impl reference is destroyed last, causing the mailbox to be
601 // released back to the embedder with the last sync point from the impl tree.
602 EXPECT_CALL(test_data_
.mock_callback_
,
603 Release(test_data_
.mailbox_name1_
, 100, true)).Times(1);
605 compositor1
->Run(100, true, main_thread_task_runner_
.get());
607 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
610 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_SecondImplRefShortcut
) {
611 scoped_refptr
<TextureLayer
> test_layer
=
612 TextureLayer::CreateForMailbox(nullptr);
613 ASSERT_TRUE(test_layer
.get());
615 main_thread_
.message_loop()->task_runner()->PostTask(
616 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
617 base::Unretained(this)));
621 // The texture layer is attached to compositor1, and passes a reference to its
623 scoped_ptr
<SingleReleaseCallbackImpl
> compositor1
;
624 main_thread_
.message_loop()->task_runner()->PostTask(
625 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
626 base::Unretained(this), &compositor1
));
628 // Then the texture layer is removed and attached to compositor2, and passes a
629 // reference to its impl tree.
630 scoped_ptr
<SingleReleaseCallbackImpl
> compositor2
;
631 main_thread_
.message_loop()->task_runner()->PostTask(
632 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
633 base::Unretained(this), &compositor2
));
636 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
638 // The main thread reference is destroyed first.
639 main_thread_
.message_loop()->task_runner()->PostTask(
640 FROM_HERE
, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
641 base::Unretained(this)));
643 EXPECT_CALL(test_data_
.mock_callback_
,
644 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
646 bool manual_reset
= false;
647 bool initially_signaled
= false;
648 base::WaitableEvent
begin_capture(manual_reset
, initially_signaled
);
649 base::WaitableEvent
wait_for_capture(manual_reset
, initially_signaled
);
650 base::WaitableEvent
stop_capture(manual_reset
, initially_signaled
);
652 // Post a task to start capturing tasks on the main thread. This will block
653 // the main thread until we signal the |stop_capture| event.
654 main_thread_
.message_loop()->task_runner()->PostTask(
656 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait
,
657 base::Unretained(this), &begin_capture
, &wait_for_capture
,
660 // Before the main thread capturing starts, one compositor destroys their
661 // impl reference. Since capturing did not start, this gets post-tasked to
663 compositor1
->Run(100, false, main_thread_task_runner_
.get());
665 // Start capturing on the main thread.
666 begin_capture
.Signal();
667 wait_for_capture
.Wait();
669 // Meanwhile, the second compositor released its impl reference, but this task
670 // gets shortcutted directly to the main thread. This means the reference is
671 // released before compositor1, whose reference will be released later when
672 // the post-task is serviced. But since it was destroyed _on the impl thread_
673 // last, its sync point values should be used.
674 compositor2
->Run(200, true, main_thread_task_runner_
.get());
676 stop_capture
.Signal();
679 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
682 class TextureLayerImplWithMailboxThreadedCallback
: public LayerTreeTest
{
684 TextureLayerImplWithMailboxThreadedCallback()
685 : callback_count_(0),
688 // Make sure callback is received on main and doesn't block the impl thread.
689 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
690 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
691 EXPECT_FALSE(lost_resource
);
695 void SetMailbox(char mailbox_char
) {
696 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
697 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
699 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback
,
700 base::Unretained(this)));
701 layer_
->SetTextureMailbox(
702 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
706 void BeginTest() override
{
707 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
709 gfx::Size
bounds(100, 100);
710 root_
= Layer::Create();
711 root_
->SetBounds(bounds
);
713 layer_
= TextureLayer::CreateForMailbox(nullptr);
714 layer_
->SetIsDrawable(true);
715 layer_
->SetBounds(bounds
);
717 root_
->AddChild(layer_
);
718 layer_tree_host()->SetRootLayer(root_
);
719 layer_tree_host()->SetViewportSize(bounds
);
721 EXPECT_EQ(0, callback_count_
);
723 // Case #1: change mailbox before the commit. The old mailbox should be
724 // released immediately.
726 EXPECT_EQ(1, callback_count_
);
727 PostSetNeedsCommitToMainThread();
730 void DidCommit() override
{
732 switch (commit_count_
) {
734 // Case #2: change mailbox after the commit (and draw), where the
735 // layer draws. The old mailbox should be released during the next
738 EXPECT_EQ(1, callback_count_
);
741 EXPECT_EQ(2, callback_count_
);
742 // Case #3: change mailbox when the layer doesn't draw. The old
743 // mailbox should be released during the next commit.
744 layer_
->SetBounds(gfx::Size());
748 EXPECT_EQ(3, callback_count_
);
749 // Case #4: release mailbox that was committed but never drawn. The
750 // old mailbox should be released during the next commit.
751 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
754 if (layer_tree_host()->settings().impl_side_painting
) {
755 // With impl painting, the texture mailbox will still be on the impl
756 // thread when the commit finishes, because the layer is not drawble
757 // when it has no texture mailbox, and thus does not block the commit
758 // on activation. So, we wait for activation.
759 // TODO(danakj): fix this. crbug.com/277953
760 layer_tree_host()->SetNeedsCommit();
766 EXPECT_EQ(4, callback_count_
);
767 // Restore a mailbox for the next step.
771 // Case #5: remove layer from tree. Callback should *not* be called, the
772 // mailbox is returned to the main thread.
773 EXPECT_EQ(4, callback_count_
);
774 layer_
->RemoveFromParent();
777 if (layer_tree_host()->settings().impl_side_painting
) {
778 // With impl painting, the texture mailbox will still be on the impl
779 // thread when the commit finishes, because the layer is not around to
780 // block the commit on activation anymore. So, we wait for activation.
781 // TODO(danakj): fix this. crbug.com/277953
782 layer_tree_host()->SetNeedsCommit();
788 EXPECT_EQ(4, callback_count_
);
789 // Resetting the mailbox will call the callback now.
790 layer_
->SetTextureMailbox(TextureMailbox(), nullptr);
791 EXPECT_EQ(5, callback_count_
);
800 void AfterTest() override
{}
803 base::ThreadChecker main_thread_
;
806 scoped_refptr
<Layer
> root_
;
807 scoped_refptr
<TextureLayer
> layer_
;
810 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
811 TextureLayerImplWithMailboxThreadedCallback
);
814 class TextureLayerMailboxIsActivatedDuringCommit
: public LayerTreeTest
{
816 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
818 static void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {}
820 void SetMailbox(char mailbox_char
) {
821 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
823 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback
));
824 layer_
->SetTextureMailbox(
825 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
829 void BeginTest() override
{
830 gfx::Size
bounds(100, 100);
831 root_
= Layer::Create();
832 root_
->SetBounds(bounds
);
834 layer_
= TextureLayer::CreateForMailbox(nullptr);
835 layer_
->SetIsDrawable(true);
836 layer_
->SetBounds(bounds
);
838 root_
->AddChild(layer_
);
839 layer_tree_host()->SetRootLayer(root_
);
840 layer_tree_host()->SetViewportSize(bounds
);
843 PostSetNeedsCommitToMainThread();
846 void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
850 void DidCommit() override
{
851 switch (layer_tree_host()->source_frame_number()) {
853 // The first mailbox has been activated. Set a new mailbox, and
854 // expect the next commit to finish *after* it is activated.
858 // The second mailbox has been activated. Remove the layer from
859 // the tree to cause another commit/activation. The commit should
860 // finish *after* the layer is removed from the active tree.
861 layer_
->RemoveFromParent();
869 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
870 switch (host_impl
->active_tree()->source_frame_number()) {
872 // The activate for the 1st mailbox should have happened before now.
873 EXPECT_EQ(1, activate_count_
);
877 // The activate for the 2nd mailbox should have happened before now.
878 EXPECT_EQ(2, activate_count_
);
882 // The activate to remove the layer should have happened before now.
883 EXPECT_EQ(3, activate_count_
);
893 void AfterTest() override
{}
896 scoped_refptr
<Layer
> root_
;
897 scoped_refptr
<TextureLayer
> layer_
;
900 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
901 TextureLayerMailboxIsActivatedDuringCommit
);
903 class TextureLayerImplWithMailboxTest
: public TextureLayerTest
{
905 TextureLayerImplWithMailboxTest()
907 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)) {}
909 void SetUp() override
{
910 TextureLayerTest::SetUp();
911 layer_tree_host_
.reset(new MockLayerTreeHost(&fake_client_
));
912 EXPECT_TRUE(host_impl_
.InitializeRenderer(FakeOutputSurface::Create3d()));
915 bool WillDraw(TextureLayerImpl
* layer
, DrawMode mode
) {
916 bool will_draw
= layer
->WillDraw(
917 mode
, host_impl_
.active_tree()->resource_provider());
919 layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
923 FakeLayerTreeHostClient fake_client_
;
926 // Test conditions for results of TextureLayerImpl::WillDraw under
927 // different configurations of different mailbox, texture_id, and draw_mode.
928 TEST_F(TextureLayerImplWithMailboxTest
, TestWillDraw
) {
930 test_data_
.mock_callback_
,
931 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
933 EXPECT_CALL(test_data_
.mock_callback_
,
934 ReleaseImpl2(test_data_
.shared_bitmap_
.get(), 0, false, _
))
938 scoped_ptr
<TextureLayerImpl
> impl_layer
=
939 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
940 impl_layer
->SetTextureMailbox(
941 test_data_
.mailbox1_
,
942 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
943 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
947 scoped_ptr
<TextureLayerImpl
> impl_layer
=
948 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
949 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
950 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
954 // Software resource.
955 scoped_ptr
<TextureLayerImpl
> impl_layer
=
956 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
957 impl_layer
->SetTextureMailbox(
958 test_data_
.mailbox3_
,
959 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
960 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
965 scoped_ptr
<TextureLayerImpl
> impl_layer
=
966 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
967 impl_layer
->SetTextureMailbox(
968 test_data_
.mailbox1_
,
969 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
970 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
974 scoped_ptr
<TextureLayerImpl
> impl_layer
=
975 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
976 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
977 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
981 // Software resource.
982 scoped_ptr
<TextureLayerImpl
> impl_layer
=
983 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
984 impl_layer
->SetTextureMailbox(
985 test_data_
.mailbox3_
,
986 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox3_impl_
));
987 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
990 // Resourceless software mode.
992 scoped_ptr
<TextureLayerImpl
> impl_layer
=
993 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
994 impl_layer
->SetTextureMailbox(
995 test_data_
.mailbox1_
,
996 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
997 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_RESOURCELESS_SOFTWARE
));
1001 TEST_F(TextureLayerImplWithMailboxTest
, TestImplLayerCallbacks
) {
1002 host_impl_
.CreatePendingTree();
1003 scoped_ptr
<TextureLayerImpl
> pending_layer
;
1004 pending_layer
= TextureLayerImpl::Create(host_impl_
.pending_tree(), 1);
1005 ASSERT_TRUE(pending_layer
);
1007 scoped_ptr
<LayerImpl
> active_layer(
1008 pending_layer
->CreateLayerImpl(host_impl_
.active_tree()));
1009 ASSERT_TRUE(active_layer
);
1011 pending_layer
->SetTextureMailbox(
1012 test_data_
.mailbox1_
,
1013 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1015 // Test multiple commits without an activation.
1017 test_data_
.mock_callback_
,
1018 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1020 pending_layer
->SetTextureMailbox(
1021 test_data_
.mailbox2_
,
1022 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox2_impl_
));
1023 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1025 // Test callback after activation.
1026 pending_layer
->PushPropertiesTo(active_layer
.get());
1027 active_layer
->DidBecomeActive();
1029 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1030 pending_layer
->SetTextureMailbox(
1031 test_data_
.mailbox1_
,
1032 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1033 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1035 EXPECT_CALL(test_data_
.mock_callback_
,
1036 ReleaseImpl(test_data_
.mailbox_name2_
, _
, false, _
)).Times(1);
1037 pending_layer
->PushPropertiesTo(active_layer
.get());
1038 active_layer
->DidBecomeActive();
1039 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1041 // Test resetting the mailbox.
1042 EXPECT_CALL(test_data_
.mock_callback_
,
1043 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1044 pending_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1045 pending_layer
->PushPropertiesTo(active_layer
.get());
1046 active_layer
->DidBecomeActive();
1047 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1051 test_data_
.mock_callback_
,
1052 ReleaseImpl(test_data_
.mailbox_name1_
, test_data_
.sync_point1_
, false, _
))
1054 pending_layer
->SetTextureMailbox(
1055 test_data_
.mailbox1_
,
1056 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1059 TEST_F(TextureLayerImplWithMailboxTest
,
1060 TestDestructorCallbackOnCreatedResource
) {
1061 scoped_ptr
<TextureLayerImpl
> impl_layer
;
1062 impl_layer
= TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1063 ASSERT_TRUE(impl_layer
);
1065 EXPECT_CALL(test_data_
.mock_callback_
,
1066 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1067 impl_layer
->SetTextureMailbox(
1068 test_data_
.mailbox1_
,
1069 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1070 impl_layer
->DidBecomeActive();
1071 EXPECT_TRUE(impl_layer
->WillDraw(
1072 DRAW_MODE_HARDWARE
, host_impl_
.active_tree()->resource_provider()));
1073 impl_layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
1074 impl_layer
->SetTextureMailbox(TextureMailbox(), nullptr);
1077 TEST_F(TextureLayerImplWithMailboxTest
, TestCallbackOnInUseResource
) {
1078 ResourceProvider
* provider
= host_impl_
.active_tree()->resource_provider();
1079 ResourceProvider::ResourceId id
= provider
->CreateResourceFromTextureMailbox(
1080 test_data_
.mailbox1_
,
1081 SingleReleaseCallbackImpl::Create(test_data_
.release_mailbox1_impl_
));
1082 provider
->AllocateForTesting(id
);
1084 // Transfer some resources to the parent.
1085 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1086 resource_ids_to_transfer
.push_back(id
);
1087 TransferableResourceArray list
;
1088 provider
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1089 EXPECT_TRUE(provider
->InUseByConsumer(id
));
1090 EXPECT_CALL(test_data_
.mock_callback_
, ReleaseImpl(_
, _
, _
, _
)).Times(0);
1091 provider
->DeleteResource(id
);
1092 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1093 EXPECT_CALL(test_data_
.mock_callback_
,
1094 ReleaseImpl(test_data_
.mailbox_name1_
, _
, false, _
)).Times(1);
1095 ReturnedResourceArray returned
;
1096 TransferableResource::ReturnResources(list
, &returned
);
1097 provider
->ReceiveReturnsFromParent(returned
);
1100 // Checks that TextureLayer::Update does not cause an extra commit when setting
1101 // the texture mailbox.
1102 class TextureLayerNoExtraCommitForMailboxTest
1103 : public LayerTreeTest
,
1104 public TextureLayerClient
{
1106 // TextureLayerClient implementation.
1107 bool PrepareTextureMailbox(
1108 TextureMailbox
* texture_mailbox
,
1109 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1110 bool use_shared_memory
) override
{
1111 if (layer_tree_host()->source_frame_number() == 1) {
1112 // Once this has been committed, the mailbox will be released.
1113 *texture_mailbox
= TextureMailbox();
1117 *texture_mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1118 *release_callback
= SingleReleaseCallback::Create(
1119 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased
,
1120 base::Unretained(this)));
1124 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1125 // Source frame number during callback is the same as the source frame
1126 // on which it was released.
1127 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1131 void SetupTree() override
{
1132 scoped_refptr
<Layer
> root
= Layer::Create();
1133 root
->SetBounds(gfx::Size(10, 10));
1134 root
->SetIsDrawable(true);
1136 texture_layer_
= TextureLayer::CreateForMailbox(this);
1137 texture_layer_
->SetBounds(gfx::Size(10, 10));
1138 texture_layer_
->SetIsDrawable(true);
1139 root
->AddChild(texture_layer_
);
1141 layer_tree_host()->SetRootLayer(root
);
1142 LayerTreeTest::SetupTree();
1145 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1147 void DidCommitAndDrawFrame() override
{
1148 switch (layer_tree_host()->source_frame_number()) {
1150 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1151 // Invalidate the texture layer to clear the mailbox before
1153 texture_layer_
->SetNeedsDisplay();
1163 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1164 ASSERT_TRUE(result
);
1165 DelegatedFrameData
* delegated_frame_data
=
1166 output_surface()->last_sent_frame().delegated_frame_data
.get();
1167 if (!delegated_frame_data
)
1170 // Return all resources immediately.
1171 TransferableResourceArray resources_to_return
=
1172 output_surface()->resources_held_by_parent();
1174 CompositorFrameAck ack
;
1175 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1176 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1177 host_impl
->ReclaimResources(&ack
);
1180 void AfterTest() override
{}
1183 scoped_refptr
<TextureLayer
> texture_layer_
;
1186 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest
);
1188 // Checks that changing a mailbox in the client for a TextureLayer that's
1189 // invisible correctly works and uses the new mailbox as soon as the layer
1190 // becomes visible (and returns the old one).
1191 class TextureLayerChangeInvisibleMailboxTest
1192 : public LayerTreeTest
,
1193 public TextureLayerClient
{
1195 TextureLayerChangeInvisibleMailboxTest()
1196 : mailbox_changed_(true),
1197 mailbox_returned_(0),
1200 mailbox_
= MakeMailbox('1');
1203 // TextureLayerClient implementation.
1204 bool PrepareTextureMailbox(
1205 TextureMailbox
* mailbox
,
1206 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1207 bool use_shared_memory
) override
{
1209 if (!mailbox_changed_
)
1211 *mailbox
= mailbox_
;
1212 *release_callback
= SingleReleaseCallback::Create(
1213 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased
,
1214 base::Unretained(this)));
1218 TextureMailbox
MakeMailbox(char name
) {
1219 return TextureMailbox(MailboxFromChar(name
), GL_TEXTURE_2D
, 0);
1222 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1223 ++mailbox_returned_
;
1226 void SetupTree() override
{
1227 scoped_refptr
<Layer
> root
= Layer::Create();
1228 root
->SetBounds(gfx::Size(10, 10));
1229 root
->SetIsDrawable(true);
1231 solid_layer_
= SolidColorLayer::Create();
1232 solid_layer_
->SetBounds(gfx::Size(10, 10));
1233 solid_layer_
->SetIsDrawable(true);
1234 solid_layer_
->SetBackgroundColor(SK_ColorWHITE
);
1235 root
->AddChild(solid_layer_
);
1237 parent_layer_
= Layer::Create();
1238 parent_layer_
->SetBounds(gfx::Size(10, 10));
1239 parent_layer_
->SetIsDrawable(true);
1240 root
->AddChild(parent_layer_
);
1242 texture_layer_
= TextureLayer::CreateForMailbox(this);
1243 texture_layer_
->SetBounds(gfx::Size(10, 10));
1244 texture_layer_
->SetIsDrawable(true);
1245 parent_layer_
->AddChild(texture_layer_
);
1247 layer_tree_host()->SetRootLayer(root
);
1248 LayerTreeTest::SetupTree();
1251 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1253 void DidCommitAndDrawFrame() override
{
1255 switch (commit_count_
) {
1257 // We should have updated the layer, committing the texture.
1258 EXPECT_EQ(1, prepare_called_
);
1259 // Make layer invisible.
1260 parent_layer_
->SetOpacity(0.f
);
1263 // Layer shouldn't have been updated.
1264 EXPECT_EQ(1, prepare_called_
);
1265 // Change the texture.
1266 mailbox_
= MakeMailbox('2');
1267 mailbox_changed_
= true;
1268 texture_layer_
->SetNeedsDisplay();
1269 // Force a change to make sure we draw a frame.
1270 solid_layer_
->SetBackgroundColor(SK_ColorGRAY
);
1273 // Layer shouldn't have been updated.
1274 EXPECT_EQ(1, prepare_called_
);
1275 // So the old mailbox isn't returned yet.
1276 EXPECT_EQ(0, mailbox_returned_
);
1277 // Make layer visible again.
1278 parent_layer_
->SetOpacity(1.f
);
1281 // Layer should have been updated.
1282 EXPECT_EQ(2, prepare_called_
);
1283 // So the old mailbox should have been returned already.
1284 EXPECT_EQ(1, mailbox_returned_
);
1285 texture_layer_
->ClearClient();
1288 EXPECT_EQ(2, mailbox_returned_
);
1297 void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
, bool result
) override
{
1298 ASSERT_TRUE(result
);
1299 DelegatedFrameData
* delegated_frame_data
=
1300 output_surface()->last_sent_frame().delegated_frame_data
.get();
1301 if (!delegated_frame_data
)
1304 // Return all resources immediately.
1305 TransferableResourceArray resources_to_return
=
1306 output_surface()->resources_held_by_parent();
1308 CompositorFrameAck ack
;
1309 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1310 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1311 host_impl
->ReclaimResources(&ack
);
1314 void AfterTest() override
{}
1317 scoped_refptr
<SolidColorLayer
> solid_layer_
;
1318 scoped_refptr
<Layer
> parent_layer_
;
1319 scoped_refptr
<TextureLayer
> texture_layer_
;
1321 // Used on the main thread.
1322 bool mailbox_changed_
;
1323 TextureMailbox mailbox_
;
1324 int mailbox_returned_
;
1325 int prepare_called_
;
1329 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest
);
1331 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1332 // the mailbox back to TextureLayerClient.
1333 class TextureLayerReleaseResourcesBase
1334 : public LayerTreeTest
,
1335 public TextureLayerClient
{
1337 // TextureLayerClient implementation.
1338 bool PrepareTextureMailbox(
1339 TextureMailbox
* mailbox
,
1340 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1341 bool use_shared_memory
) override
{
1342 *mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1343 *release_callback
= SingleReleaseCallback::Create(
1344 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased
,
1345 base::Unretained(this)));
1349 void MailboxReleased(unsigned sync_point
, bool lost_resource
) {
1350 mailbox_released_
= true;
1353 void SetupTree() override
{
1354 LayerTreeTest::SetupTree();
1356 scoped_refptr
<TextureLayer
> texture_layer
=
1357 TextureLayer::CreateForMailbox(this);
1358 texture_layer
->SetBounds(gfx::Size(10, 10));
1359 texture_layer
->SetIsDrawable(true);
1361 layer_tree_host()->root_layer()->AddChild(texture_layer
);
1364 void BeginTest() override
{
1365 mailbox_released_
= false;
1366 PostSetNeedsCommitToMainThread();
1369 void DidCommitAndDrawFrame() override
{ EndTest(); }
1371 void AfterTest() override
{ EXPECT_TRUE(mailbox_released_
); }
1374 bool mailbox_released_
;
1377 class TextureLayerReleaseResourcesAfterCommit
1378 : public TextureLayerReleaseResourcesBase
{
1380 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
1381 LayerTreeImpl
* tree
= nullptr;
1382 tree
= host_impl
->sync_tree();
1383 tree
->root_layer()->children()[0]->ReleaseResources();
1387 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit
);
1389 class TextureLayerReleaseResourcesAfterActivate
1390 : public TextureLayerReleaseResourcesBase
{
1392 void DidActivateTreeOnThread(LayerTreeHostImpl
* host_impl
) override
{
1393 host_impl
->active_tree()->root_layer()->children()[0]->ReleaseResources();
1397 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate
);
1399 class TextureLayerWithMailboxMainThreadDeleted
: public LayerTreeTest
{
1401 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1402 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1403 EXPECT_FALSE(lost_resource
);
1408 void SetMailbox(char mailbox_char
) {
1409 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1410 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1412 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback
,
1413 base::Unretained(this)));
1414 layer_
->SetTextureMailbox(
1415 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1419 void SetupTree() override
{
1420 gfx::Size
bounds(100, 100);
1421 root_
= Layer::Create();
1422 root_
->SetBounds(bounds
);
1424 layer_
= TextureLayer::CreateForMailbox(nullptr);
1425 layer_
->SetIsDrawable(true);
1426 layer_
->SetBounds(bounds
);
1428 root_
->AddChild(layer_
);
1429 layer_tree_host()->SetRootLayer(root_
);
1430 layer_tree_host()->SetViewportSize(bounds
);
1433 void BeginTest() override
{
1434 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1436 callback_count_
= 0;
1438 // Set the mailbox on the main thread.
1440 EXPECT_EQ(0, callback_count_
);
1442 PostSetNeedsCommitToMainThread();
1445 void DidCommitAndDrawFrame() override
{
1446 switch (layer_tree_host()->source_frame_number()) {
1448 // Delete the TextureLayer on the main thread while the mailbox is in
1450 layer_
->RemoveFromParent();
1456 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1459 base::ThreadChecker main_thread_
;
1460 int callback_count_
;
1461 scoped_refptr
<Layer
> root_
;
1462 scoped_refptr
<TextureLayer
> layer_
;
1465 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1466 TextureLayerWithMailboxMainThreadDeleted
);
1468 class TextureLayerWithMailboxImplThreadDeleted
: public LayerTreeTest
{
1470 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1471 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1472 EXPECT_FALSE(lost_resource
);
1477 void SetMailbox(char mailbox_char
) {
1478 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1479 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1481 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback
,
1482 base::Unretained(this)));
1483 layer_
->SetTextureMailbox(
1484 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1488 void SetupTree() override
{
1489 gfx::Size
bounds(100, 100);
1490 root_
= Layer::Create();
1491 root_
->SetBounds(bounds
);
1493 layer_
= TextureLayer::CreateForMailbox(nullptr);
1494 layer_
->SetIsDrawable(true);
1495 layer_
->SetBounds(bounds
);
1497 root_
->AddChild(layer_
);
1498 layer_tree_host()->SetRootLayer(root_
);
1499 layer_tree_host()->SetViewportSize(bounds
);
1502 void BeginTest() override
{
1503 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1505 callback_count_
= 0;
1507 // Set the mailbox on the main thread.
1509 EXPECT_EQ(0, callback_count_
);
1511 PostSetNeedsCommitToMainThread();
1514 void DidCommitAndDrawFrame() override
{
1515 switch (layer_tree_host()->source_frame_number()) {
1517 // Remove the TextureLayer on the main thread while the mailbox is in
1518 // the impl tree, but don't delete the TextureLayer until after the impl
1519 // tree side is deleted.
1520 layer_
->RemoveFromParent();
1528 void AfterTest() override
{ EXPECT_EQ(1, callback_count_
); }
1531 base::ThreadChecker main_thread_
;
1532 int callback_count_
;
1533 scoped_refptr
<Layer
> root_
;
1534 scoped_refptr
<TextureLayer
> layer_
;
1537 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1538 TextureLayerWithMailboxImplThreadDeleted
);