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_->SetAnchorPoint(gfx::PointF());
698 root_->SetBounds(bounds);
700 layer_ = TextureLayer::CreateForMailbox(NULL);
701 layer_->SetIsDrawable(true);
702 layer_->SetAnchorPoint(gfx::PointF());
703 layer_->SetBounds(bounds);
705 root_->AddChild(layer_);
706 layer_tree_host()->SetRootLayer(root_);
707 layer_tree_host()->SetViewportSize(bounds);
709 EXPECT_EQ(0, callback_count_);
711 // Case #1: change mailbox before the commit. The old mailbox should be
712 // released immediately.
714 EXPECT_EQ(1, callback_count_);
715 PostSetNeedsCommitToMainThread();
718 virtual void DidCommit() OVERRIDE {
720 switch (commit_count_) {
722 // Case #2: change mailbox after the commit (and draw), where the
723 // layer draws. The old mailbox should be released during the next
726 EXPECT_EQ(1, callback_count_);
729 EXPECT_EQ(2, callback_count_);
730 // Case #3: change mailbox when the layer doesn't draw. The old
731 // mailbox should be released during the next commit.
732 layer_->SetBounds(gfx::Size());
736 EXPECT_EQ(3, callback_count_);
737 // Case #4: release mailbox that was committed but never drawn. The
738 // old mailbox should be released during the next commit.
739 layer_->SetTextureMailbox(TextureMailbox(),
740 scoped_ptr<SingleReleaseCallback>());
743 if (layer_tree_host()->settings().impl_side_painting) {
744 // With impl painting, the texture mailbox will still be on the impl
745 // thread when the commit finishes, because the layer is not drawble
746 // when it has no texture mailbox, and thus does not block the commit
747 // on activation. So, we wait for activation.
748 // TODO(danakj): fix this. crbug.com/277953
749 layer_tree_host()->SetNeedsCommit();
755 EXPECT_EQ(4, callback_count_);
756 // Restore a mailbox for the next step.
760 // Case #5: remove layer from tree. Callback should *not* be called, the
761 // mailbox is returned to the main thread.
762 EXPECT_EQ(4, callback_count_);
763 layer_->RemoveFromParent();
766 if (layer_tree_host()->settings().impl_side_painting) {
767 // With impl painting, the texture mailbox will still be on the impl
768 // thread when the commit finishes, because the layer is not around to
769 // block the commit on activation anymore. So, we wait for activation.
770 // TODO(danakj): fix this. crbug.com/277953
771 layer_tree_host()->SetNeedsCommit();
777 EXPECT_EQ(4, callback_count_);
778 // Resetting the mailbox will call the callback now.
779 layer_->SetTextureMailbox(TextureMailbox(),
780 scoped_ptr<SingleReleaseCallback>());
781 EXPECT_EQ(5, callback_count_);
790 virtual void AfterTest() OVERRIDE {}
793 base::ThreadChecker main_thread_;
796 scoped_refptr<Layer> root_;
797 scoped_refptr<TextureLayer> layer_;
800 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
801 TextureLayerImplWithMailboxThreadedCallback);
804 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
806 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
808 static void ReleaseCallback(uint32 sync_point, bool lost_resource) {}
810 void SetMailbox(char mailbox_char) {
811 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
813 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
814 layer_->SetTextureMailbox(
815 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
819 virtual void BeginTest() OVERRIDE {
820 gfx::Size bounds(100, 100);
821 root_ = Layer::Create();
822 root_->SetAnchorPoint(gfx::PointF());
823 root_->SetBounds(bounds);
825 layer_ = TextureLayer::CreateForMailbox(NULL);
826 layer_->SetIsDrawable(true);
827 layer_->SetAnchorPoint(gfx::PointF());
828 layer_->SetBounds(bounds);
830 root_->AddChild(layer_);
831 layer_tree_host()->SetRootLayer(root_);
832 layer_tree_host()->SetViewportSize(bounds);
835 PostSetNeedsCommitToMainThread();
838 virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
842 virtual void DidCommit() OVERRIDE {
843 switch (layer_tree_host()->source_frame_number()) {
845 // The first mailbox has been activated. Set a new mailbox, and
846 // expect the next commit to finish *after* it is activated.
850 // The second mailbox has been activated. Remove the layer from
851 // the tree to cause another commit/activation. The commit should
852 // finish *after* the layer is removed from the active tree.
853 layer_->RemoveFromParent();
861 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
862 switch (host_impl->active_tree()->source_frame_number()) {
864 // The activate for the 2nd mailbox should have happened before now.
865 EXPECT_EQ(2, activate_count_);
869 // The activate to remove the layer should have happened before now.
870 EXPECT_EQ(3, activate_count_);
877 virtual void AfterTest() OVERRIDE {}
880 scoped_refptr<Layer> root_;
881 scoped_refptr<TextureLayer> layer_;
884 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
885 TextureLayerMailboxIsActivatedDuringCommit);
887 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
889 TextureLayerImplWithMailboxTest()
891 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
893 virtual void SetUp() {
894 TextureLayerTest::SetUp();
895 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
896 EXPECT_TRUE(host_impl_.InitializeRenderer(
897 FakeOutputSurface::Create3d().PassAs<OutputSurface>()));
900 bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
901 bool will_draw = layer->WillDraw(
902 mode, host_impl_.active_tree()->resource_provider());
904 layer->DidDraw(host_impl_.active_tree()->resource_provider());
908 CommonMailboxObjects test_data_;
909 FakeLayerTreeHostClient fake_client_;
912 // Test conditions for results of TextureLayerImpl::WillDraw under
913 // different configurations of different mailbox, texture_id, and draw_mode.
914 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
915 EXPECT_CALL(test_data_.mock_callback_,
916 Release(test_data_.mailbox_name1_,
917 test_data_.sync_point1_,
920 EXPECT_CALL(test_data_.mock_callback_,
921 Release2(test_data_.shared_memory_.get(), 0, false))
925 scoped_ptr<TextureLayerImpl> impl_layer =
926 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
927 impl_layer->SetDrawsContent(true);
928 impl_layer->SetTextureMailbox(
929 test_data_.mailbox1_,
930 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
931 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
935 scoped_ptr<TextureLayerImpl> impl_layer =
936 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
937 impl_layer->SetDrawsContent(true);
938 impl_layer->SetTextureMailbox(TextureMailbox(),
939 scoped_ptr<SingleReleaseCallback>());
940 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
944 // Software resource.
945 scoped_ptr<TextureLayerImpl> impl_layer =
946 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
947 impl_layer->SetDrawsContent(true);
948 impl_layer->SetTextureMailbox(
949 test_data_.mailbox3_,
950 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
951 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
956 scoped_ptr<TextureLayerImpl> impl_layer =
957 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
958 impl_layer->SetDrawsContent(true);
959 impl_layer->SetTextureMailbox(
960 test_data_.mailbox1_,
961 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
962 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
966 scoped_ptr<TextureLayerImpl> impl_layer =
967 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
968 impl_layer->SetDrawsContent(true);
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->SetDrawsContent(true);
979 impl_layer->SetTextureMailbox(
980 test_data_.mailbox3_,
981 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
982 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
985 // Resourceless software mode.
987 scoped_ptr<TextureLayerImpl> impl_layer =
988 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
989 impl_layer->SetDrawsContent(true);
990 impl_layer->SetTextureMailbox(
991 test_data_.mailbox1_,
992 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
993 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
997 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
998 host_impl_.CreatePendingTree();
999 scoped_ptr<TextureLayerImpl> pending_layer;
1000 pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1);
1001 ASSERT_TRUE(pending_layer);
1003 scoped_ptr<LayerImpl> active_layer(
1004 pending_layer->CreateLayerImpl(host_impl_.active_tree()));
1005 ASSERT_TRUE(active_layer);
1007 pending_layer->SetTextureMailbox(
1008 test_data_.mailbox1_,
1009 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1011 // Test multiple commits without an activation.
1012 EXPECT_CALL(test_data_.mock_callback_,
1013 Release(test_data_.mailbox_name1_,
1014 test_data_.sync_point1_,
1017 pending_layer->SetTextureMailbox(
1018 test_data_.mailbox2_,
1019 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
1020 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1022 // Test callback after activation.
1023 pending_layer->PushPropertiesTo(active_layer.get());
1024 active_layer->DidBecomeActive();
1026 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1027 pending_layer->SetTextureMailbox(
1028 test_data_.mailbox1_,
1029 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1030 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1032 EXPECT_CALL(test_data_.mock_callback_,
1033 Release(test_data_.mailbox_name2_, _, false))
1035 pending_layer->PushPropertiesTo(active_layer.get());
1036 active_layer->DidBecomeActive();
1037 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1039 // Test resetting the mailbox.
1040 EXPECT_CALL(test_data_.mock_callback_,
1041 Release(test_data_.mailbox_name1_, _, false))
1043 pending_layer->SetTextureMailbox(TextureMailbox(),
1044 scoped_ptr<SingleReleaseCallback>());
1045 pending_layer->PushPropertiesTo(active_layer.get());
1046 active_layer->DidBecomeActive();
1047 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1050 EXPECT_CALL(test_data_.mock_callback_,
1051 Release(test_data_.mailbox_name1_,
1052 test_data_.sync_point1_,
1055 pending_layer->SetTextureMailbox(
1056 test_data_.mailbox1_,
1057 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1060 TEST_F(TextureLayerImplWithMailboxTest,
1061 TestDestructorCallbackOnCreatedResource) {
1062 scoped_ptr<TextureLayerImpl> impl_layer;
1063 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1064 ASSERT_TRUE(impl_layer);
1066 EXPECT_CALL(test_data_.mock_callback_,
1067 Release(test_data_.mailbox_name1_, _, false))
1069 impl_layer->SetTextureMailbox(
1070 test_data_.mailbox1_,
1071 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1072 impl_layer->SetDrawsContent(true);
1073 impl_layer->DidBecomeActive();
1074 EXPECT_TRUE(impl_layer->WillDraw(
1075 DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1076 impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1077 impl_layer->SetTextureMailbox(TextureMailbox(),
1078 scoped_ptr<SingleReleaseCallback>());
1081 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1082 ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1083 ResourceProvider::ResourceId id =
1084 provider->CreateResourceFromTextureMailbox(
1085 test_data_.mailbox1_,
1086 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1087 provider->AllocateForTesting(id);
1089 // Transfer some resources to the parent.
1090 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1091 resource_ids_to_transfer.push_back(id);
1092 TransferableResourceArray list;
1093 provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1094 EXPECT_TRUE(provider->InUseByConsumer(id));
1095 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1096 provider->DeleteResource(id);
1097 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1098 EXPECT_CALL(test_data_.mock_callback_,
1099 Release(test_data_.mailbox_name1_, _, false))
1101 ReturnedResourceArray returned;
1102 TransferableResource::ReturnResources(list, &returned);
1103 provider->ReceiveReturnsFromParent(returned);
1106 // Checks that TextureLayer::Update does not cause an extra commit when setting
1107 // the texture mailbox.
1108 class TextureLayerNoExtraCommitForMailboxTest
1109 : public LayerTreeTest,
1110 public TextureLayerClient {
1112 // TextureLayerClient implementation.
1113 virtual bool PrepareTextureMailbox(
1114 TextureMailbox* texture_mailbox,
1115 scoped_ptr<SingleReleaseCallback>* release_callback,
1116 bool use_shared_memory) OVERRIDE {
1117 if (layer_tree_host()->source_frame_number() == 1) {
1118 *texture_mailbox = TextureMailbox();
1122 *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1123 *release_callback = SingleReleaseCallback::Create(
1124 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1125 base::Unretained(this)));
1129 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1130 EXPECT_EQ(2, 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->SetAnchorPoint(gfx::PointF());
1138 root->SetIsDrawable(true);
1140 texture_layer_ = TextureLayer::CreateForMailbox(this);
1141 texture_layer_->SetBounds(gfx::Size(10, 10));
1142 texture_layer_->SetAnchorPoint(gfx::PointF());
1143 texture_layer_->SetIsDrawable(true);
1144 root->AddChild(texture_layer_);
1146 layer_tree_host()->SetRootLayer(root);
1147 LayerTreeTest::SetupTree();
1150 virtual void BeginTest() OVERRIDE {
1151 PostSetNeedsCommitToMainThread();
1154 virtual void DidCommitAndDrawFrame() OVERRIDE {
1155 switch (layer_tree_host()->source_frame_number()) {
1157 EXPECT_FALSE(proxy()->CommitPendingForTesting());
1158 // Invalidate the texture layer to clear the mailbox before
1160 texture_layer_->SetNeedsDisplay();
1170 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1171 bool result) OVERRIDE {
1172 ASSERT_TRUE(result);
1173 DelegatedFrameData* delegated_frame_data =
1174 output_surface()->last_sent_frame().delegated_frame_data.get();
1175 if (!delegated_frame_data)
1178 // Return all resources immediately.
1179 TransferableResourceArray resources_to_return =
1180 output_surface()->resources_held_by_parent();
1182 CompositorFrameAck ack;
1183 for (size_t i = 0; i < resources_to_return.size(); ++i)
1184 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1185 host_impl->ReclaimResources(&ack);
1188 virtual void AfterTest() OVERRIDE {}
1191 scoped_refptr<TextureLayer> texture_layer_;
1194 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1196 // Checks that changing a mailbox in the client for a TextureLayer that's
1197 // invisible correctly works and uses the new mailbox as soon as the layer
1198 // becomes visible (and returns the old one).
1199 class TextureLayerChangeInvisibleMailboxTest
1200 : public LayerTreeTest,
1201 public TextureLayerClient {
1203 TextureLayerChangeInvisibleMailboxTest()
1204 : mailbox_changed_(true),
1205 mailbox_returned_(0),
1208 mailbox_ = MakeMailbox('1');
1211 // TextureLayerClient implementation.
1212 virtual bool PrepareTextureMailbox(
1213 TextureMailbox* mailbox,
1214 scoped_ptr<SingleReleaseCallback>* release_callback,
1215 bool use_shared_memory) OVERRIDE {
1217 if (!mailbox_changed_)
1219 *mailbox = mailbox_;
1220 *release_callback = SingleReleaseCallback::Create(
1221 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1222 base::Unretained(this)));
1226 TextureMailbox MakeMailbox(char name) {
1227 return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0);
1230 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1231 ++mailbox_returned_;
1234 virtual void SetupTree() OVERRIDE {
1235 scoped_refptr<Layer> root = Layer::Create();
1236 root->SetBounds(gfx::Size(10, 10));
1237 root->SetAnchorPoint(gfx::PointF());
1238 root->SetIsDrawable(true);
1240 solid_layer_ = SolidColorLayer::Create();
1241 solid_layer_->SetBounds(gfx::Size(10, 10));
1242 solid_layer_->SetIsDrawable(true);
1243 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1244 root->AddChild(solid_layer_);
1246 parent_layer_ = Layer::Create();
1247 parent_layer_->SetBounds(gfx::Size(10, 10));
1248 parent_layer_->SetIsDrawable(true);
1249 root->AddChild(parent_layer_);
1251 texture_layer_ = TextureLayer::CreateForMailbox(this);
1252 texture_layer_->SetBounds(gfx::Size(10, 10));
1253 texture_layer_->SetAnchorPoint(gfx::PointF());
1254 texture_layer_->SetIsDrawable(true);
1255 parent_layer_->AddChild(texture_layer_);
1257 layer_tree_host()->SetRootLayer(root);
1258 LayerTreeTest::SetupTree();
1261 virtual void BeginTest() OVERRIDE {
1262 PostSetNeedsCommitToMainThread();
1265 virtual void DidCommitAndDrawFrame() OVERRIDE {
1267 switch (commit_count_) {
1269 // We should have updated the layer, committing the texture.
1270 EXPECT_EQ(1, prepare_called_);
1271 // Make layer invisible.
1272 parent_layer_->SetOpacity(0.f);
1275 // Layer shouldn't have been updated.
1276 EXPECT_EQ(1, prepare_called_);
1277 // Change the texture.
1278 mailbox_ = MakeMailbox('2');
1279 mailbox_changed_ = true;
1280 texture_layer_->SetNeedsDisplay();
1281 // Force a change to make sure we draw a frame.
1282 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1285 // Layer shouldn't have been updated.
1286 EXPECT_EQ(1, prepare_called_);
1287 // So the old mailbox isn't returned yet.
1288 EXPECT_EQ(0, mailbox_returned_);
1289 // Make layer visible again.
1290 parent_layer_->SetOpacity(1.f);
1293 // Layer should have been updated.
1294 EXPECT_EQ(2, prepare_called_);
1295 // So the old mailbox should have been returned already.
1296 EXPECT_EQ(1, mailbox_returned_);
1297 texture_layer_->ClearClient();
1300 EXPECT_EQ(2, mailbox_returned_);
1309 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1310 bool result) OVERRIDE {
1311 ASSERT_TRUE(result);
1312 DelegatedFrameData* delegated_frame_data =
1313 output_surface()->last_sent_frame().delegated_frame_data.get();
1314 if (!delegated_frame_data)
1317 // Return all resources immediately.
1318 TransferableResourceArray resources_to_return =
1319 output_surface()->resources_held_by_parent();
1321 CompositorFrameAck ack;
1322 for (size_t i = 0; i < resources_to_return.size(); ++i)
1323 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1324 host_impl->ReclaimResources(&ack);
1327 virtual void AfterTest() OVERRIDE {}
1330 scoped_refptr<SolidColorLayer> solid_layer_;
1331 scoped_refptr<Layer> parent_layer_;
1332 scoped_refptr<TextureLayer> texture_layer_;
1334 // Used on the main thread.
1335 bool mailbox_changed_;
1336 TextureMailbox mailbox_;
1337 int mailbox_returned_;
1338 int prepare_called_;
1342 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1344 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1345 // the mailbox back to TextureLayerClient.
1346 class TextureLayerReleaseResourcesBase
1347 : public LayerTreeTest,
1348 public TextureLayerClient {
1350 // TextureLayerClient implementation.
1351 virtual bool PrepareTextureMailbox(
1352 TextureMailbox* mailbox,
1353 scoped_ptr<SingleReleaseCallback>* release_callback,
1354 bool use_shared_memory) OVERRIDE {
1355 *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1356 *release_callback = SingleReleaseCallback::Create(
1357 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1358 base::Unretained(this)));
1362 void MailboxReleased(unsigned sync_point, bool lost_resource) {
1363 mailbox_released_ = true;
1366 virtual void SetupTree() OVERRIDE {
1367 LayerTreeTest::SetupTree();
1369 scoped_refptr<TextureLayer> texture_layer =
1370 TextureLayer::CreateForMailbox(this);
1371 texture_layer->SetBounds(gfx::Size(10, 10));
1372 texture_layer->SetAnchorPoint(gfx::PointF());
1373 texture_layer->SetIsDrawable(true);
1375 layer_tree_host()->root_layer()->AddChild(texture_layer);
1378 virtual void BeginTest() OVERRIDE {
1379 mailbox_released_ = false;
1380 PostSetNeedsCommitToMainThread();
1383 virtual void DidCommitAndDrawFrame() OVERRIDE {
1387 virtual void AfterTest() OVERRIDE {
1388 EXPECT_TRUE(mailbox_released_);
1392 bool mailbox_released_;
1395 class TextureLayerReleaseResourcesAfterCommit
1396 : public TextureLayerReleaseResourcesBase {
1398 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1399 LayerTreeImpl* tree = NULL;
1400 if (host_impl->settings().impl_side_painting)
1401 tree = host_impl->pending_tree();
1403 tree = host_impl->active_tree();
1404 tree->root_layer()->children()[0]->ReleaseResources();
1408 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1410 class TextureLayerReleaseResourcesAfterActivate
1411 : public TextureLayerReleaseResourcesBase {
1413 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1414 host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
1418 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
1420 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
1422 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1423 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1424 EXPECT_FALSE(lost_resource);
1429 void SetMailbox(char mailbox_char) {
1430 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1431 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1433 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
1434 base::Unretained(this)));
1435 layer_->SetTextureMailbox(
1436 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1440 virtual void SetupTree() OVERRIDE {
1441 gfx::Size bounds(100, 100);
1442 root_ = Layer::Create();
1443 root_->SetAnchorPoint(gfx::PointF());
1444 root_->SetBounds(bounds);
1446 layer_ = TextureLayer::CreateForMailbox(NULL);
1447 layer_->SetIsDrawable(true);
1448 layer_->SetAnchorPoint(gfx::PointF());
1449 layer_->SetBounds(bounds);
1451 root_->AddChild(layer_);
1452 layer_tree_host()->SetRootLayer(root_);
1453 layer_tree_host()->SetViewportSize(bounds);
1456 virtual void BeginTest() OVERRIDE {
1457 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1459 callback_count_ = 0;
1461 // Set the mailbox on the main thread.
1463 EXPECT_EQ(0, callback_count_);
1465 PostSetNeedsCommitToMainThread();
1468 virtual void DidCommitAndDrawFrame() OVERRIDE {
1469 switch (layer_tree_host()->source_frame_number()) {
1471 // Delete the TextureLayer on the main thread while the mailbox is in
1473 layer_->RemoveFromParent();
1479 virtual void AfterTest() OVERRIDE {
1480 EXPECT_EQ(1, callback_count_);
1484 base::ThreadChecker main_thread_;
1485 int callback_count_;
1486 scoped_refptr<Layer> root_;
1487 scoped_refptr<TextureLayer> layer_;
1490 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1491 TextureLayerWithMailboxMainThreadDeleted);
1493 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
1495 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1496 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1497 EXPECT_FALSE(lost_resource);
1502 void SetMailbox(char mailbox_char) {
1503 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1504 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1506 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
1507 base::Unretained(this)));
1508 layer_->SetTextureMailbox(
1509 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1513 virtual void SetupTree() OVERRIDE {
1514 gfx::Size bounds(100, 100);
1515 root_ = Layer::Create();
1516 root_->SetAnchorPoint(gfx::PointF());
1517 root_->SetBounds(bounds);
1519 layer_ = TextureLayer::CreateForMailbox(NULL);
1520 layer_->SetIsDrawable(true);
1521 layer_->SetAnchorPoint(gfx::PointF());
1522 layer_->SetBounds(bounds);
1524 root_->AddChild(layer_);
1525 layer_tree_host()->SetRootLayer(root_);
1526 layer_tree_host()->SetViewportSize(bounds);
1529 virtual void BeginTest() OVERRIDE {
1530 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1532 callback_count_ = 0;
1534 // Set the mailbox on the main thread.
1536 EXPECT_EQ(0, callback_count_);
1538 PostSetNeedsCommitToMainThread();
1541 virtual void DidCommitAndDrawFrame() OVERRIDE {
1542 switch (layer_tree_host()->source_frame_number()) {
1544 // Remove the TextureLayer on the main thread while the mailbox is in
1545 // the impl tree, but don't delete the TextureLayer until after the impl
1546 // tree side is deleted.
1547 layer_->RemoveFromParent();
1555 virtual void AfterTest() OVERRIDE {
1556 EXPECT_EQ(1, callback_count_);
1560 base::ThreadChecker main_thread_;
1561 int callback_count_;
1562 scoped_refptr<Layer> root_;
1563 scoped_refptr<TextureLayer> layer_;
1566 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1567 TextureLayerWithMailboxImplThreadDeleted);