1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/layers/texture_layer.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/thread.h"
14 #include "base/time/time.h"
15 #include "cc/layers/solid_color_layer.h"
16 #include "cc/layers/texture_layer_client.h"
17 #include "cc/layers/texture_layer_impl.h"
18 #include "cc/output/compositor_frame_ack.h"
19 #include "cc/output/context_provider.h"
20 #include "cc/resources/returned_resource.h"
21 #include "cc/test/fake_impl_proxy.h"
22 #include "cc/test/fake_layer_tree_host_client.h"
23 #include "cc/test/fake_layer_tree_host_impl.h"
24 #include "cc/test/fake_output_surface.h"
25 #include "cc/test/layer_test_common.h"
26 #include "cc/test/layer_tree_test.h"
27 #include "cc/test/test_web_graphics_context_3d.h"
28 #include "cc/trees/blocking_task_runner.h"
29 #include "cc/trees/layer_tree_host.h"
30 #include "cc/trees/layer_tree_impl.h"
31 #include "cc/trees/single_thread_proxy.h"
32 #include "gpu/GLES2/gl2extchromium.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "testing/gtest/include/gtest/gtest.h"
36 using ::testing::Mock
;
38 using ::testing::AtLeast
;
39 using ::testing::AnyNumber
;
40 using ::testing::InvokeWithoutArgs
;
45 gpu::Mailbox
MailboxFromChar(char value
) {
47 memset(mailbox
.name
, value
, sizeof(mailbox
.name
));
51 class MockLayerTreeHost
: public LayerTreeHost
{
53 explicit MockLayerTreeHost(FakeLayerTreeHostClient
* client
)
54 : LayerTreeHost(client
, NULL
, LayerTreeSettings()) {
55 InitializeSingleThreaded(client
);
58 MOCK_METHOD0(SetNeedsCommit
, void());
59 MOCK_METHOD0(SetNeedsUpdateLayers
, void());
60 MOCK_METHOD0(StartRateLimiter
, void());
61 MOCK_METHOD0(StopRateLimiter
, void());
64 class FakeTextureLayerClient
: public TextureLayerClient
{
66 FakeTextureLayerClient() : mailbox_changed_(true) {}
68 virtual bool PrepareTextureMailbox(
69 TextureMailbox
* mailbox
,
70 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
71 bool use_shared_memory
) OVERRIDE
{
72 if (!mailbox_changed_
)
76 *release_callback
= release_callback_
.Pass();
77 mailbox_changed_
= false;
81 void set_mailbox(const TextureMailbox
& mailbox
,
82 scoped_ptr
<SingleReleaseCallback
> release_callback
) {
84 release_callback_
= release_callback
.Pass();
85 mailbox_changed_
= true;
89 TextureMailbox mailbox_
;
90 scoped_ptr
<SingleReleaseCallback
> release_callback_
;
91 bool mailbox_changed_
;
92 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient
);
95 class MockMailboxCallback
{
98 void(const gpu::Mailbox
& mailbox
,
100 bool lost_resource
));
101 MOCK_METHOD3(Release2
,
102 void(base::SharedMemory
* shared_memory
,
104 bool lost_resource
));
107 struct CommonMailboxObjects
{
108 CommonMailboxObjects()
109 : mailbox_name1_(MailboxFromChar('1')),
110 mailbox_name2_(MailboxFromChar('2')),
113 shared_memory_(new base::SharedMemory
) {
114 release_mailbox1_
= base::Bind(&MockMailboxCallback::Release
,
115 base::Unretained(&mock_callback_
),
117 release_mailbox2_
= base::Bind(&MockMailboxCallback::Release
,
118 base::Unretained(&mock_callback_
),
120 const uint32 arbitrary_target1
= GL_TEXTURE_2D
;
121 const uint32 arbitrary_target2
= GL_TEXTURE_EXTERNAL_OES
;
122 mailbox1_
= TextureMailbox(mailbox_name1_
, arbitrary_target1
, sync_point1_
);
123 mailbox2_
= TextureMailbox(mailbox_name2_
, arbitrary_target2
, sync_point2_
);
124 gfx::Size
size(128, 128);
125 EXPECT_TRUE(shared_memory_
->CreateAndMapAnonymous(4 * size
.GetArea()));
126 release_mailbox3_
= base::Bind(&MockMailboxCallback::Release2
,
127 base::Unretained(&mock_callback_
),
128 shared_memory_
.get());
129 mailbox3_
= TextureMailbox(shared_memory_
.get(), size
);
132 gpu::Mailbox mailbox_name1_
;
133 gpu::Mailbox mailbox_name2_
;
134 MockMailboxCallback mock_callback_
;
135 ReleaseCallback release_mailbox1_
;
136 ReleaseCallback release_mailbox2_
;
137 ReleaseCallback release_mailbox3_
;
138 TextureMailbox mailbox1_
;
139 TextureMailbox mailbox2_
;
140 TextureMailbox mailbox3_
;
143 scoped_ptr
<base::SharedMemory
> shared_memory_
;
146 class TextureLayerTest
: public testing::Test
{
150 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)),
151 host_impl_(&proxy_
, &shared_bitmap_manager_
) {}
154 virtual void SetUp() {
155 layer_tree_host_
.reset(new MockLayerTreeHost(&fake_client_
));
156 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
157 layer_tree_host_
->SetViewportSize(gfx::Size(10, 10));
158 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
161 virtual void TearDown() {
162 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
163 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
165 layer_tree_host_
->SetRootLayer(NULL
);
166 layer_tree_host_
.reset();
169 scoped_ptr
<MockLayerTreeHost
> layer_tree_host_
;
170 FakeImplProxy proxy_
;
171 FakeLayerTreeHostClient fake_client_
;
172 TestSharedBitmapManager shared_bitmap_manager_
;
173 FakeLayerTreeHostImpl host_impl_
;
176 TEST_F(TextureLayerTest
, CheckPropertyChangeCausesCorrectBehavior
) {
177 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(NULL
);
178 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_
->SetRootLayer(test_layer
));
180 // Test properties that should call SetNeedsCommit. All properties need to
181 // be set to new values in order for SetNeedsCommit to be called.
182 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetFlipped(false));
183 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetUV(
184 gfx::PointF(0.25f
, 0.25f
), gfx::PointF(0.75f
, 0.75f
)));
185 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetVertexOpacity(
186 0.5f
, 0.5f
, 0.5f
, 0.5f
));
187 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetPremultipliedAlpha(false));
188 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetBlendBackgroundColor(true));
191 TEST_F(TextureLayerTest
, VisibleContentOpaqueRegion
) {
192 const gfx::Size
layer_bounds(100, 100);
193 const gfx::Rect
layer_rect(layer_bounds
);
194 const Region
layer_region(layer_rect
);
196 scoped_refptr
<TextureLayer
> layer
= TextureLayer::CreateForMailbox(NULL
);
197 layer
->SetBounds(layer_bounds
);
198 layer
->draw_properties().visible_content_rect
= layer_rect
;
199 layer
->SetBlendBackgroundColor(true);
201 // Verify initial conditions.
202 EXPECT_FALSE(layer
->contents_opaque());
203 EXPECT_EQ(0u, layer
->background_color());
204 EXPECT_EQ(Region().ToString(),
205 layer
->VisibleContentOpaqueRegion().ToString());
207 // Opaque background.
208 layer
->SetBackgroundColor(SK_ColorWHITE
);
209 EXPECT_EQ(layer_region
.ToString(),
210 layer
->VisibleContentOpaqueRegion().ToString());
212 // Transparent background.
213 layer
->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
214 EXPECT_EQ(Region().ToString(),
215 layer
->VisibleContentOpaqueRegion().ToString());
218 TEST_F(TextureLayerTest
, RateLimiter
) {
219 FakeTextureLayerClient client
;
220 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(
222 test_layer
->SetIsDrawable(true);
223 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
224 layer_tree_host_
->SetRootLayer(test_layer
);
226 // Don't rate limit until we invalidate.
227 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
228 test_layer
->SetRateLimitContext(true);
229 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
231 // Do rate limit after we invalidate.
232 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
233 test_layer
->SetNeedsDisplay();
234 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
236 // Stop rate limiter when we don't want it any more.
237 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
238 test_layer
->SetRateLimitContext(false);
239 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
241 // Or we clear the client.
242 test_layer
->SetRateLimitContext(true);
243 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
244 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
245 test_layer
->ClearClient();
246 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
248 // Reset to a layer with a client, that started the rate limiter.
249 test_layer
= TextureLayer::CreateForMailbox(
251 test_layer
->SetIsDrawable(true);
252 test_layer
->SetRateLimitContext(true);
253 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
254 layer_tree_host_
->SetRootLayer(test_layer
);
255 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter()).Times(0);
256 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
257 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter());
258 test_layer
->SetNeedsDisplay();
259 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
261 // Stop rate limiter when we're removed from the tree.
262 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter());
263 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(1);
264 layer_tree_host_
->SetRootLayer(NULL
);
265 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
268 class TestMailboxHolder
: public TextureLayer::TextureMailboxHolder
{
270 using TextureLayer::TextureMailboxHolder::Create
;
273 virtual ~TestMailboxHolder() {}
276 class TextureLayerWithMailboxTest
: public TextureLayerTest
{
278 virtual void TearDown() {
279 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
280 EXPECT_CALL(test_data_
.mock_callback_
,
281 Release(test_data_
.mailbox_name1_
,
282 test_data_
.sync_point1_
,
284 TextureLayerTest::TearDown();
287 CommonMailboxObjects test_data_
;
290 TEST_F(TextureLayerWithMailboxTest
, ReplaceMailboxOnMainThreadBeforeCommit
) {
291 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(NULL
);
292 ASSERT_TRUE(test_layer
.get());
294 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
295 layer_tree_host_
->SetRootLayer(test_layer
);
296 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
298 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
299 test_layer
->SetTextureMailbox(
300 test_data_
.mailbox1_
,
301 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
302 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
304 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
305 EXPECT_CALL(test_data_
.mock_callback_
,
306 Release(test_data_
.mailbox_name1_
,
307 test_data_
.sync_point1_
,
310 test_layer
->SetTextureMailbox(
311 test_data_
.mailbox2_
,
312 SingleReleaseCallback::Create(test_data_
.release_mailbox2_
));
313 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
314 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
316 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
317 EXPECT_CALL(test_data_
.mock_callback_
,
318 Release(test_data_
.mailbox_name2_
,
319 test_data_
.sync_point2_
,
322 test_layer
->SetTextureMailbox(TextureMailbox(),
323 scoped_ptr
<SingleReleaseCallback
>());
324 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
325 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
327 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
328 test_layer
->SetTextureMailbox(
329 test_data_
.mailbox3_
,
330 SingleReleaseCallback::Create(test_data_
.release_mailbox3_
));
331 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
332 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
334 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
335 EXPECT_CALL(test_data_
.mock_callback_
,
336 Release2(test_data_
.shared_memory_
.get(),
339 test_layer
->SetTextureMailbox(TextureMailbox(),
340 scoped_ptr
<SingleReleaseCallback
>());
341 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
342 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
345 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
346 test_layer
->SetTextureMailbox(
347 test_data_
.mailbox1_
,
348 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
351 TEST_F(TextureLayerTest
, SetTextureMailboxWithoutReleaseCallback
) {
352 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(NULL
);
353 ASSERT_TRUE(test_layer
.get());
355 // These use the same gpu::Mailbox, but different sync points.
356 TextureMailbox
mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D
, 1);
357 TextureMailbox
mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D
, 2);
359 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
360 layer_tree_host_
->SetRootLayer(test_layer
);
361 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
363 // Set the mailbox the first time. It should cause a commit.
364 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
365 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox1
);
366 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
368 // Set the mailbox again with a new sync point, as the backing texture has
369 // been updated. It should cause a new commit.
370 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
371 test_layer
->SetTextureMailboxWithoutReleaseCallback(mailbox2
);
372 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
375 class TextureLayerMailboxHolderTest
: public TextureLayerTest
{
377 TextureLayerMailboxHolderTest()
378 : main_thread_("MAIN") {
379 main_thread_
.Start();
382 void Wait(const base::Thread
& thread
) {
383 bool manual_reset
= false;
384 bool initially_signaled
= false;
385 base::WaitableEvent
event(manual_reset
, initially_signaled
);
386 thread
.message_loop()->PostTask(
388 base::Bind(&base::WaitableEvent::Signal
, base::Unretained(&event
)));
392 void CreateMainRef() {
393 main_ref_
= TestMailboxHolder::Create(
394 test_data_
.mailbox1_
,
395 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
)).Pass();
398 void ReleaseMainRef() {
402 void CreateImplRef(scoped_ptr
<SingleReleaseCallback
>* impl_ref
) {
403 *impl_ref
= main_ref_
->holder()->GetCallbackForImplThread();
406 void CapturePostTasksAndWait(base::WaitableEvent
* begin_capture
,
407 base::WaitableEvent
* wait_for_capture
,
408 base::WaitableEvent
* stop_capture
) {
409 begin_capture
->Wait();
410 BlockingTaskRunner::CapturePostTasks capture
;
411 wait_for_capture
->Signal();
412 stop_capture
->Wait();
416 scoped_ptr
<TestMailboxHolder::MainThreadReference
>
418 base::Thread main_thread_
;
419 CommonMailboxObjects test_data_
;
422 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_BothReleaseThenMain
) {
423 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(NULL
);
424 ASSERT_TRUE(test_layer
.get());
426 main_thread_
.message_loop()->PostTask(
428 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
429 base::Unretained(this)));
433 // The texture layer is attached to compositor1, and passes a reference to its
435 scoped_ptr
<SingleReleaseCallback
> compositor1
;
436 main_thread_
.message_loop()->PostTask(
438 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
439 base::Unretained(this),
442 // Then the texture layer is removed and attached to compositor2, and passes a
443 // reference to its impl tree.
444 scoped_ptr
<SingleReleaseCallback
> compositor2
;
445 main_thread_
.message_loop()->PostTask(
447 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
448 base::Unretained(this),
452 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
454 // The compositors both destroy their impl trees before the main thread layer
456 compositor1
->Run(100, false);
457 compositor2
->Run(200, false);
461 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
462 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
464 // The main thread ref is the last one, so the mailbox is released back to the
465 // embedder, with the last sync point provided by the impl trees.
466 EXPECT_CALL(test_data_
.mock_callback_
,
467 Release(test_data_
.mailbox_name1_
, 200, false)).Times(1);
469 main_thread_
.message_loop()->PostTask(
471 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
472 base::Unretained(this)));
474 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
477 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleaseBetween
) {
478 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(NULL
);
479 ASSERT_TRUE(test_layer
.get());
481 main_thread_
.message_loop()->PostTask(
483 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
484 base::Unretained(this)));
488 // The texture layer is attached to compositor1, and passes a reference to its
490 scoped_ptr
<SingleReleaseCallback
> compositor1
;
491 main_thread_
.message_loop()->PostTask(
493 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
494 base::Unretained(this),
497 // Then the texture layer is removed and attached to compositor2, and passes a
498 // reference to its impl tree.
499 scoped_ptr
<SingleReleaseCallback
> compositor2
;
500 main_thread_
.message_loop()->PostTask(
502 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
503 base::Unretained(this),
507 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
509 // One compositor destroys their impl tree.
510 compositor1
->Run(100, false);
512 // Then the main thread reference is destroyed.
513 main_thread_
.message_loop()->PostTask(
515 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
516 base::Unretained(this)));
520 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
521 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
523 // The second impl reference is destroyed last, causing the mailbox to be
524 // released back to the embedder with the last sync point from the impl tree.
525 EXPECT_CALL(test_data_
.mock_callback_
,
526 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
528 compositor2
->Run(200, true);
530 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
533 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_MainReleasedFirst
) {
534 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(NULL
);
535 ASSERT_TRUE(test_layer
.get());
537 main_thread_
.message_loop()->PostTask(
539 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
540 base::Unretained(this)));
544 // The texture layer is attached to compositor1, and passes a reference to its
546 scoped_ptr
<SingleReleaseCallback
> compositor1
;
547 main_thread_
.message_loop()->PostTask(
549 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
550 base::Unretained(this),
553 // Then the texture layer is removed and attached to compositor2, and passes a
554 // reference to its impl tree.
555 scoped_ptr
<SingleReleaseCallback
> compositor2
;
556 main_thread_
.message_loop()->PostTask(
558 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
559 base::Unretained(this),
563 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
565 // The main thread reference is destroyed first.
566 main_thread_
.message_loop()->PostTask(
568 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
569 base::Unretained(this)));
571 // One compositor destroys their impl tree.
572 compositor2
->Run(200, false);
576 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
577 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
579 // The second impl reference is destroyed last, causing the mailbox to be
580 // released back to the embedder with the last sync point from the impl tree.
581 EXPECT_CALL(test_data_
.mock_callback_
,
582 Release(test_data_
.mailbox_name1_
, 100, true)).Times(1);
584 compositor1
->Run(100, true);
586 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
589 TEST_F(TextureLayerMailboxHolderTest
, TwoCompositors_SecondImplRefShortcut
) {
590 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(NULL
);
591 ASSERT_TRUE(test_layer
.get());
593 main_thread_
.message_loop()->PostTask(
595 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef
,
596 base::Unretained(this)));
600 // The texture layer is attached to compositor1, and passes a reference to its
602 scoped_ptr
<SingleReleaseCallback
> compositor1
;
603 main_thread_
.message_loop()->PostTask(
605 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
606 base::Unretained(this),
609 // Then the texture layer is removed and attached to compositor2, and passes a
610 // reference to its impl tree.
611 scoped_ptr
<SingleReleaseCallback
> compositor2
;
612 main_thread_
.message_loop()->PostTask(
614 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef
,
615 base::Unretained(this),
619 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
621 // The main thread reference is destroyed first.
622 main_thread_
.message_loop()->PostTask(
624 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef
,
625 base::Unretained(this)));
627 EXPECT_CALL(test_data_
.mock_callback_
,
628 Release(test_data_
.mailbox_name1_
, 200, true)).Times(1);
630 bool manual_reset
= false;
631 bool initially_signaled
= false;
632 base::WaitableEvent
begin_capture(manual_reset
, initially_signaled
);
633 base::WaitableEvent
wait_for_capture(manual_reset
, initially_signaled
);
634 base::WaitableEvent
stop_capture(manual_reset
, initially_signaled
);
636 // Post a task to start capturing tasks on the main thread. This will block
637 // the main thread until we signal the |stop_capture| event.
638 main_thread_
.message_loop()->PostTask(
640 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait
,
641 base::Unretained(this),
646 // Before the main thread capturing starts, one compositor destroys their
647 // impl reference. Since capturing did not start, this gets post-tasked to
649 compositor1
->Run(100, false);
651 // Start capturing on the main thread.
652 begin_capture
.Signal();
653 wait_for_capture
.Wait();
655 // Meanwhile, the second compositor released its impl reference, but this task
656 // gets shortcutted directly to the main thread. This means the reference is
657 // released before compositor1, whose reference will be released later when
658 // the post-task is serviced. But since it was destroyed _on the impl thread_
659 // last, its sync point values should be used.
660 compositor2
->Run(200, true);
662 stop_capture
.Signal();
665 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
668 class TextureLayerImplWithMailboxThreadedCallback
: public LayerTreeTest
{
670 TextureLayerImplWithMailboxThreadedCallback()
671 : callback_count_(0),
674 // Make sure callback is received on main and doesn't block the impl thread.
675 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
676 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
677 EXPECT_FALSE(lost_resource
);
681 void SetMailbox(char mailbox_char
) {
682 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
683 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
685 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback
,
686 base::Unretained(this)));
687 layer_
->SetTextureMailbox(
688 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
692 virtual void BeginTest() OVERRIDE
{
693 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
695 gfx::Size
bounds(100, 100);
696 root_
= Layer::Create();
697 root_
->SetBounds(bounds
);
699 layer_
= TextureLayer::CreateForMailbox(NULL
);
700 layer_
->SetIsDrawable(true);
701 layer_
->SetBounds(bounds
);
703 root_
->AddChild(layer_
);
704 layer_tree_host()->SetRootLayer(root_
);
705 layer_tree_host()->SetViewportSize(bounds
);
707 EXPECT_EQ(0, callback_count_
);
709 // Case #1: change mailbox before the commit. The old mailbox should be
710 // released immediately.
712 EXPECT_EQ(1, callback_count_
);
713 PostSetNeedsCommitToMainThread();
716 virtual void DidCommit() OVERRIDE
{
718 switch (commit_count_
) {
720 // Case #2: change mailbox after the commit (and draw), where the
721 // layer draws. The old mailbox should be released during the next
724 EXPECT_EQ(1, callback_count_
);
727 EXPECT_EQ(2, callback_count_
);
728 // Case #3: change mailbox when the layer doesn't draw. The old
729 // mailbox should be released during the next commit.
730 layer_
->SetBounds(gfx::Size());
734 EXPECT_EQ(3, callback_count_
);
735 // Case #4: release mailbox that was committed but never drawn. The
736 // old mailbox should be released during the next commit.
737 layer_
->SetTextureMailbox(TextureMailbox(),
738 scoped_ptr
<SingleReleaseCallback
>());
741 if (layer_tree_host()->settings().impl_side_painting
) {
742 // With impl painting, the texture mailbox will still be on the impl
743 // thread when the commit finishes, because the layer is not drawble
744 // when it has no texture mailbox, and thus does not block the commit
745 // on activation. So, we wait for activation.
746 // TODO(danakj): fix this. crbug.com/277953
747 layer_tree_host()->SetNeedsCommit();
753 EXPECT_EQ(4, callback_count_
);
754 // Restore a mailbox for the next step.
758 // Case #5: remove layer from tree. Callback should *not* be called, the
759 // mailbox is returned to the main thread.
760 EXPECT_EQ(4, callback_count_
);
761 layer_
->RemoveFromParent();
764 if (layer_tree_host()->settings().impl_side_painting
) {
765 // With impl painting, the texture mailbox will still be on the impl
766 // thread when the commit finishes, because the layer is not around to
767 // block the commit on activation anymore. So, we wait for activation.
768 // TODO(danakj): fix this. crbug.com/277953
769 layer_tree_host()->SetNeedsCommit();
775 EXPECT_EQ(4, callback_count_
);
776 // Resetting the mailbox will call the callback now.
777 layer_
->SetTextureMailbox(TextureMailbox(),
778 scoped_ptr
<SingleReleaseCallback
>());
779 EXPECT_EQ(5, callback_count_
);
788 virtual void AfterTest() OVERRIDE
{}
791 base::ThreadChecker main_thread_
;
794 scoped_refptr
<Layer
> root_
;
795 scoped_refptr
<TextureLayer
> layer_
;
798 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
799 TextureLayerImplWithMailboxThreadedCallback
);
802 class TextureLayerMailboxIsActivatedDuringCommit
: public LayerTreeTest
{
804 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
806 static void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {}
808 void SetMailbox(char mailbox_char
) {
809 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
811 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback
));
812 layer_
->SetTextureMailbox(
813 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
817 virtual void BeginTest() OVERRIDE
{
818 gfx::Size
bounds(100, 100);
819 root_
= Layer::Create();
820 root_
->SetBounds(bounds
);
822 layer_
= TextureLayer::CreateForMailbox(NULL
);
823 layer_
->SetIsDrawable(true);
824 layer_
->SetBounds(bounds
);
826 root_
->AddChild(layer_
);
827 layer_tree_host()->SetRootLayer(root_
);
828 layer_tree_host()->SetViewportSize(bounds
);
831 PostSetNeedsCommitToMainThread();
834 virtual void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
838 virtual void DidCommit() OVERRIDE
{
839 switch (layer_tree_host()->source_frame_number()) {
841 // The first mailbox has been activated. Set a new mailbox, and
842 // expect the next commit to finish *after* it is activated.
846 // The second mailbox has been activated. Remove the layer from
847 // the tree to cause another commit/activation. The commit should
848 // finish *after* the layer is removed from the active tree.
849 layer_
->RemoveFromParent();
857 virtual void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) OVERRIDE
{
858 switch (host_impl
->active_tree()->source_frame_number()) {
860 // The activate for the 1st mailbox should have happened before now.
861 EXPECT_EQ(1, activate_count_
);
865 // The activate for the 2nd mailbox should have happened before now.
866 EXPECT_EQ(2, activate_count_
);
870 // The activate to remove the layer should have happened before now.
871 EXPECT_EQ(3, activate_count_
);
882 virtual void AfterTest() OVERRIDE
{}
885 scoped_refptr
<Layer
> root_
;
886 scoped_refptr
<TextureLayer
> layer_
;
889 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
890 TextureLayerMailboxIsActivatedDuringCommit
);
892 class TextureLayerImplWithMailboxTest
: public TextureLayerTest
{
894 TextureLayerImplWithMailboxTest()
896 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)) {}
898 virtual void SetUp() {
899 TextureLayerTest::SetUp();
900 layer_tree_host_
.reset(new MockLayerTreeHost(&fake_client_
));
901 EXPECT_TRUE(host_impl_
.InitializeRenderer(
902 FakeOutputSurface::Create3d().PassAs
<OutputSurface
>()));
905 bool WillDraw(TextureLayerImpl
* layer
, DrawMode mode
) {
906 bool will_draw
= layer
->WillDraw(
907 mode
, host_impl_
.active_tree()->resource_provider());
909 layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
913 CommonMailboxObjects test_data_
;
914 FakeLayerTreeHostClient fake_client_
;
917 // Test conditions for results of TextureLayerImpl::WillDraw under
918 // different configurations of different mailbox, texture_id, and draw_mode.
919 TEST_F(TextureLayerImplWithMailboxTest
, TestWillDraw
) {
920 EXPECT_CALL(test_data_
.mock_callback_
,
921 Release(test_data_
.mailbox_name1_
,
922 test_data_
.sync_point1_
,
925 EXPECT_CALL(test_data_
.mock_callback_
,
926 Release2(test_data_
.shared_memory_
.get(), 0, false))
930 scoped_ptr
<TextureLayerImpl
> impl_layer
=
931 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
932 impl_layer
->SetTextureMailbox(
933 test_data_
.mailbox1_
,
934 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
935 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
939 scoped_ptr
<TextureLayerImpl
> impl_layer
=
940 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
941 impl_layer
->SetTextureMailbox(TextureMailbox(),
942 scoped_ptr
<SingleReleaseCallback
>());
943 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
947 // Software resource.
948 scoped_ptr
<TextureLayerImpl
> impl_layer
=
949 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
950 impl_layer
->SetTextureMailbox(
951 test_data_
.mailbox3_
,
952 SingleReleaseCallback::Create(test_data_
.release_mailbox3_
));
953 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(
961 test_data_
.mailbox1_
,
962 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
963 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
967 scoped_ptr
<TextureLayerImpl
> impl_layer
=
968 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
969 impl_layer
->SetTextureMailbox(TextureMailbox(),
970 scoped_ptr
<SingleReleaseCallback
>());
971 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
975 // Software resource.
976 scoped_ptr
<TextureLayerImpl
> impl_layer
=
977 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
978 impl_layer
->SetTextureMailbox(
979 test_data_
.mailbox3_
,
980 SingleReleaseCallback::Create(test_data_
.release_mailbox3_
));
981 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
984 // Resourceless software mode.
986 scoped_ptr
<TextureLayerImpl
> impl_layer
=
987 TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
988 impl_layer
->SetTextureMailbox(
989 test_data_
.mailbox1_
,
990 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
991 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_RESOURCELESS_SOFTWARE
));
995 TEST_F(TextureLayerImplWithMailboxTest
, TestImplLayerCallbacks
) {
996 host_impl_
.CreatePendingTree();
997 scoped_ptr
<TextureLayerImpl
> pending_layer
;
998 pending_layer
= TextureLayerImpl::Create(host_impl_
.pending_tree(), 1);
999 ASSERT_TRUE(pending_layer
);
1001 scoped_ptr
<LayerImpl
> active_layer(
1002 pending_layer
->CreateLayerImpl(host_impl_
.active_tree()));
1003 ASSERT_TRUE(active_layer
);
1005 pending_layer
->SetTextureMailbox(
1006 test_data_
.mailbox1_
,
1007 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
1009 // Test multiple commits without an activation.
1010 EXPECT_CALL(test_data_
.mock_callback_
,
1011 Release(test_data_
.mailbox_name1_
,
1012 test_data_
.sync_point1_
,
1015 pending_layer
->SetTextureMailbox(
1016 test_data_
.mailbox2_
,
1017 SingleReleaseCallback::Create(test_data_
.release_mailbox2_
));
1018 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1020 // Test callback after activation.
1021 pending_layer
->PushPropertiesTo(active_layer
.get());
1022 active_layer
->DidBecomeActive();
1024 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
1025 pending_layer
->SetTextureMailbox(
1026 test_data_
.mailbox1_
,
1027 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
1028 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1030 EXPECT_CALL(test_data_
.mock_callback_
,
1031 Release(test_data_
.mailbox_name2_
, _
, false))
1033 pending_layer
->PushPropertiesTo(active_layer
.get());
1034 active_layer
->DidBecomeActive();
1035 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1037 // Test resetting the mailbox.
1038 EXPECT_CALL(test_data_
.mock_callback_
,
1039 Release(test_data_
.mailbox_name1_
, _
, false))
1041 pending_layer
->SetTextureMailbox(TextureMailbox(),
1042 scoped_ptr
<SingleReleaseCallback
>());
1043 pending_layer
->PushPropertiesTo(active_layer
.get());
1044 active_layer
->DidBecomeActive();
1045 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1048 EXPECT_CALL(test_data_
.mock_callback_
,
1049 Release(test_data_
.mailbox_name1_
,
1050 test_data_
.sync_point1_
,
1053 pending_layer
->SetTextureMailbox(
1054 test_data_
.mailbox1_
,
1055 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
1058 TEST_F(TextureLayerImplWithMailboxTest
,
1059 TestDestructorCallbackOnCreatedResource
) {
1060 scoped_ptr
<TextureLayerImpl
> impl_layer
;
1061 impl_layer
= TextureLayerImpl::Create(host_impl_
.active_tree(), 1);
1062 ASSERT_TRUE(impl_layer
);
1064 EXPECT_CALL(test_data_
.mock_callback_
,
1065 Release(test_data_
.mailbox_name1_
, _
, false))
1067 impl_layer
->SetTextureMailbox(
1068 test_data_
.mailbox1_
,
1069 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
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(),
1075 scoped_ptr
<SingleReleaseCallback
>());
1078 TEST_F(TextureLayerImplWithMailboxTest
, TestCallbackOnInUseResource
) {
1079 ResourceProvider
* provider
= host_impl_
.active_tree()->resource_provider();
1080 ResourceProvider::ResourceId id
=
1081 provider
->CreateResourceFromTextureMailbox(
1082 test_data_
.mailbox1_
,
1083 SingleReleaseCallback::Create(test_data_
.release_mailbox1_
));
1084 provider
->AllocateForTesting(id
);
1086 // Transfer some resources to the parent.
1087 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1088 resource_ids_to_transfer
.push_back(id
);
1089 TransferableResourceArray list
;
1090 provider
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1091 EXPECT_TRUE(provider
->InUseByConsumer(id
));
1092 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
1093 provider
->DeleteResource(id
);
1094 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
1095 EXPECT_CALL(test_data_
.mock_callback_
,
1096 Release(test_data_
.mailbox_name1_
, _
, false))
1098 ReturnedResourceArray returned
;
1099 TransferableResource::ReturnResources(list
, &returned
);
1100 provider
->ReceiveReturnsFromParent(returned
);
1103 // Checks that TextureLayer::Update does not cause an extra commit when setting
1104 // the texture mailbox.
1105 class TextureLayerNoExtraCommitForMailboxTest
1106 : public LayerTreeTest
,
1107 public TextureLayerClient
{
1109 // TextureLayerClient implementation.
1110 virtual bool PrepareTextureMailbox(
1111 TextureMailbox
* texture_mailbox
,
1112 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1113 bool use_shared_memory
) OVERRIDE
{
1114 if (layer_tree_host()->source_frame_number() == 1) {
1115 // Once this has been committed, the mailbox will be released.
1116 *texture_mailbox
= TextureMailbox();
1120 *texture_mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1121 *release_callback
= SingleReleaseCallback::Create(
1122 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased
,
1123 base::Unretained(this)));
1127 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1128 // Source frame number during callback is the same as the source frame
1129 // on which it was released.
1130 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1134 virtual void SetupTree() OVERRIDE
{
1135 scoped_refptr
<Layer
> root
= Layer::Create();
1136 root
->SetBounds(gfx::Size(10, 10));
1137 root
->SetIsDrawable(true);
1139 texture_layer_
= TextureLayer::CreateForMailbox(this);
1140 texture_layer_
->SetBounds(gfx::Size(10, 10));
1141 texture_layer_
->SetIsDrawable(true);
1142 root
->AddChild(texture_layer_
);
1144 layer_tree_host()->SetRootLayer(root
);
1145 LayerTreeTest::SetupTree();
1148 virtual void BeginTest() OVERRIDE
{
1149 PostSetNeedsCommitToMainThread();
1152 virtual void DidCommitAndDrawFrame() OVERRIDE
{
1153 switch (layer_tree_host()->source_frame_number()) {
1155 EXPECT_FALSE(proxy()->CommitPendingForTesting());
1156 // Invalidate the texture layer to clear the mailbox before
1158 texture_layer_
->SetNeedsDisplay();
1168 virtual void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
,
1169 bool result
) OVERRIDE
{
1170 ASSERT_TRUE(result
);
1171 DelegatedFrameData
* delegated_frame_data
=
1172 output_surface()->last_sent_frame().delegated_frame_data
.get();
1173 if (!delegated_frame_data
)
1176 // Return all resources immediately.
1177 TransferableResourceArray resources_to_return
=
1178 output_surface()->resources_held_by_parent();
1180 CompositorFrameAck ack
;
1181 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1182 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1183 host_impl
->ReclaimResources(&ack
);
1186 virtual void AfterTest() OVERRIDE
{}
1189 scoped_refptr
<TextureLayer
> texture_layer_
;
1192 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest
);
1194 // Checks that changing a mailbox in the client for a TextureLayer that's
1195 // invisible correctly works and uses the new mailbox as soon as the layer
1196 // becomes visible (and returns the old one).
1197 class TextureLayerChangeInvisibleMailboxTest
1198 : public LayerTreeTest
,
1199 public TextureLayerClient
{
1201 TextureLayerChangeInvisibleMailboxTest()
1202 : mailbox_changed_(true),
1203 mailbox_returned_(0),
1206 mailbox_
= MakeMailbox('1');
1209 // TextureLayerClient implementation.
1210 virtual bool PrepareTextureMailbox(
1211 TextureMailbox
* mailbox
,
1212 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1213 bool use_shared_memory
) OVERRIDE
{
1215 if (!mailbox_changed_
)
1217 *mailbox
= mailbox_
;
1218 *release_callback
= SingleReleaseCallback::Create(
1219 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased
,
1220 base::Unretained(this)));
1224 TextureMailbox
MakeMailbox(char name
) {
1225 return TextureMailbox(MailboxFromChar(name
), GL_TEXTURE_2D
, 0);
1228 void MailboxReleased(uint32 sync_point
, bool lost_resource
) {
1229 ++mailbox_returned_
;
1232 virtual void SetupTree() OVERRIDE
{
1233 scoped_refptr
<Layer
> root
= Layer::Create();
1234 root
->SetBounds(gfx::Size(10, 10));
1235 root
->SetIsDrawable(true);
1237 solid_layer_
= SolidColorLayer::Create();
1238 solid_layer_
->SetBounds(gfx::Size(10, 10));
1239 solid_layer_
->SetIsDrawable(true);
1240 solid_layer_
->SetBackgroundColor(SK_ColorWHITE
);
1241 root
->AddChild(solid_layer_
);
1243 parent_layer_
= Layer::Create();
1244 parent_layer_
->SetBounds(gfx::Size(10, 10));
1245 parent_layer_
->SetIsDrawable(true);
1246 root
->AddChild(parent_layer_
);
1248 texture_layer_
= TextureLayer::CreateForMailbox(this);
1249 texture_layer_
->SetBounds(gfx::Size(10, 10));
1250 texture_layer_
->SetIsDrawable(true);
1251 parent_layer_
->AddChild(texture_layer_
);
1253 layer_tree_host()->SetRootLayer(root
);
1254 LayerTreeTest::SetupTree();
1257 virtual void BeginTest() OVERRIDE
{
1258 PostSetNeedsCommitToMainThread();
1261 virtual void DidCommitAndDrawFrame() OVERRIDE
{
1263 switch (commit_count_
) {
1265 // We should have updated the layer, committing the texture.
1266 EXPECT_EQ(1, prepare_called_
);
1267 // Make layer invisible.
1268 parent_layer_
->SetOpacity(0.f
);
1271 // Layer shouldn't have been updated.
1272 EXPECT_EQ(1, prepare_called_
);
1273 // Change the texture.
1274 mailbox_
= MakeMailbox('2');
1275 mailbox_changed_
= true;
1276 texture_layer_
->SetNeedsDisplay();
1277 // Force a change to make sure we draw a frame.
1278 solid_layer_
->SetBackgroundColor(SK_ColorGRAY
);
1281 // Layer shouldn't have been updated.
1282 EXPECT_EQ(1, prepare_called_
);
1283 // So the old mailbox isn't returned yet.
1284 EXPECT_EQ(0, mailbox_returned_
);
1285 // Make layer visible again.
1286 parent_layer_
->SetOpacity(1.f
);
1289 // Layer should have been updated.
1290 EXPECT_EQ(2, prepare_called_
);
1291 // So the old mailbox should have been returned already.
1292 EXPECT_EQ(1, mailbox_returned_
);
1293 texture_layer_
->ClearClient();
1296 EXPECT_EQ(2, mailbox_returned_
);
1305 virtual void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
,
1306 bool result
) OVERRIDE
{
1307 ASSERT_TRUE(result
);
1308 DelegatedFrameData
* delegated_frame_data
=
1309 output_surface()->last_sent_frame().delegated_frame_data
.get();
1310 if (!delegated_frame_data
)
1313 // Return all resources immediately.
1314 TransferableResourceArray resources_to_return
=
1315 output_surface()->resources_held_by_parent();
1317 CompositorFrameAck ack
;
1318 for (size_t i
= 0; i
< resources_to_return
.size(); ++i
)
1319 output_surface()->ReturnResource(resources_to_return
[i
].id
, &ack
);
1320 host_impl
->ReclaimResources(&ack
);
1323 virtual void AfterTest() OVERRIDE
{}
1326 scoped_refptr
<SolidColorLayer
> solid_layer_
;
1327 scoped_refptr
<Layer
> parent_layer_
;
1328 scoped_refptr
<TextureLayer
> texture_layer_
;
1330 // Used on the main thread.
1331 bool mailbox_changed_
;
1332 TextureMailbox mailbox_
;
1333 int mailbox_returned_
;
1334 int prepare_called_
;
1338 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest
);
1340 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1341 // the mailbox back to TextureLayerClient.
1342 class TextureLayerReleaseResourcesBase
1343 : public LayerTreeTest
,
1344 public TextureLayerClient
{
1346 // TextureLayerClient implementation.
1347 virtual bool PrepareTextureMailbox(
1348 TextureMailbox
* mailbox
,
1349 scoped_ptr
<SingleReleaseCallback
>* release_callback
,
1350 bool use_shared_memory
) OVERRIDE
{
1351 *mailbox
= TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D
, 0);
1352 *release_callback
= SingleReleaseCallback::Create(
1353 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased
,
1354 base::Unretained(this)));
1358 void MailboxReleased(unsigned sync_point
, bool lost_resource
) {
1359 mailbox_released_
= true;
1362 virtual void SetupTree() OVERRIDE
{
1363 LayerTreeTest::SetupTree();
1365 scoped_refptr
<TextureLayer
> texture_layer
=
1366 TextureLayer::CreateForMailbox(this);
1367 texture_layer
->SetBounds(gfx::Size(10, 10));
1368 texture_layer
->SetIsDrawable(true);
1370 layer_tree_host()->root_layer()->AddChild(texture_layer
);
1373 virtual void BeginTest() OVERRIDE
{
1374 mailbox_released_
= false;
1375 PostSetNeedsCommitToMainThread();
1378 virtual void DidCommitAndDrawFrame() OVERRIDE
{
1382 virtual void AfterTest() OVERRIDE
{
1383 EXPECT_TRUE(mailbox_released_
);
1387 bool mailbox_released_
;
1390 class TextureLayerReleaseResourcesAfterCommit
1391 : public TextureLayerReleaseResourcesBase
{
1393 virtual void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) OVERRIDE
{
1394 LayerTreeImpl
* tree
= NULL
;
1395 if (host_impl
->settings().impl_side_painting
)
1396 tree
= host_impl
->pending_tree();
1398 tree
= host_impl
->active_tree();
1399 tree
->root_layer()->children()[0]->ReleaseResources();
1403 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit
);
1405 class TextureLayerReleaseResourcesAfterActivate
1406 : public TextureLayerReleaseResourcesBase
{
1408 virtual void DidActivateTreeOnThread(LayerTreeHostImpl
* host_impl
) OVERRIDE
{
1409 host_impl
->active_tree()->root_layer()->children()[0]->ReleaseResources();
1413 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate
);
1415 class TextureLayerWithMailboxMainThreadDeleted
: public LayerTreeTest
{
1417 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1418 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1419 EXPECT_FALSE(lost_resource
);
1424 void SetMailbox(char mailbox_char
) {
1425 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1426 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1428 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback
,
1429 base::Unretained(this)));
1430 layer_
->SetTextureMailbox(
1431 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1435 virtual void SetupTree() OVERRIDE
{
1436 gfx::Size
bounds(100, 100);
1437 root_
= Layer::Create();
1438 root_
->SetBounds(bounds
);
1440 layer_
= TextureLayer::CreateForMailbox(NULL
);
1441 layer_
->SetIsDrawable(true);
1442 layer_
->SetBounds(bounds
);
1444 root_
->AddChild(layer_
);
1445 layer_tree_host()->SetRootLayer(root_
);
1446 layer_tree_host()->SetViewportSize(bounds
);
1449 virtual void BeginTest() OVERRIDE
{
1450 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1452 callback_count_
= 0;
1454 // Set the mailbox on the main thread.
1456 EXPECT_EQ(0, callback_count_
);
1458 PostSetNeedsCommitToMainThread();
1461 virtual void DidCommitAndDrawFrame() OVERRIDE
{
1462 switch (layer_tree_host()->source_frame_number()) {
1464 // Delete the TextureLayer on the main thread while the mailbox is in
1466 layer_
->RemoveFromParent();
1472 virtual void AfterTest() OVERRIDE
{
1473 EXPECT_EQ(1, callback_count_
);
1477 base::ThreadChecker main_thread_
;
1478 int callback_count_
;
1479 scoped_refptr
<Layer
> root_
;
1480 scoped_refptr
<TextureLayer
> layer_
;
1483 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1484 TextureLayerWithMailboxMainThreadDeleted
);
1486 class TextureLayerWithMailboxImplThreadDeleted
: public LayerTreeTest
{
1488 void ReleaseCallback(uint32 sync_point
, bool lost_resource
) {
1489 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1490 EXPECT_FALSE(lost_resource
);
1495 void SetMailbox(char mailbox_char
) {
1496 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1497 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
1499 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback
,
1500 base::Unretained(this)));
1501 layer_
->SetTextureMailbox(
1502 TextureMailbox(MailboxFromChar(mailbox_char
), GL_TEXTURE_2D
, 0),
1506 virtual void SetupTree() OVERRIDE
{
1507 gfx::Size
bounds(100, 100);
1508 root_
= Layer::Create();
1509 root_
->SetBounds(bounds
);
1511 layer_
= TextureLayer::CreateForMailbox(NULL
);
1512 layer_
->SetIsDrawable(true);
1513 layer_
->SetBounds(bounds
);
1515 root_
->AddChild(layer_
);
1516 layer_tree_host()->SetRootLayer(root_
);
1517 layer_tree_host()->SetViewportSize(bounds
);
1520 virtual void BeginTest() OVERRIDE
{
1521 EXPECT_EQ(true, main_thread_
.CalledOnValidThread());
1523 callback_count_
= 0;
1525 // Set the mailbox on the main thread.
1527 EXPECT_EQ(0, callback_count_
);
1529 PostSetNeedsCommitToMainThread();
1532 virtual void DidCommitAndDrawFrame() OVERRIDE
{
1533 switch (layer_tree_host()->source_frame_number()) {
1535 // Remove the TextureLayer on the main thread while the mailbox is in
1536 // the impl tree, but don't delete the TextureLayer until after the impl
1537 // tree side is deleted.
1538 layer_
->RemoveFromParent();
1546 virtual void AfterTest() OVERRIDE
{
1547 EXPECT_EQ(1, callback_count_
);
1551 base::ThreadChecker main_thread_
;
1552 int callback_count_
;
1553 scoped_refptr
<Layer
> root_
;
1554 scoped_refptr
<TextureLayer
> layer_
;
1557 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1558 TextureLayerWithMailboxImplThreadDeleted
);