Implements RLZTrackerDelegate on iOS.
[chromium-blink-merge.git] / cc / layers / texture_layer_unittest.cc
blob97bb7a15b20bf9fb4bfc67279e024369cdecc858
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"
7 #include <algorithm>
8 #include <string>
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/location.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/threading/thread.h"
17 #include "base/time/time.h"
18 #include "cc/layers/solid_color_layer.h"
19 #include "cc/layers/texture_layer_client.h"
20 #include "cc/layers/texture_layer_impl.h"
21 #include "cc/output/compositor_frame_ack.h"
22 #include "cc/output/context_provider.h"
23 #include "cc/resources/returned_resource.h"
24 #include "cc/test/fake_impl_proxy.h"
25 #include "cc/test/fake_layer_tree_host_client.h"
26 #include "cc/test/fake_layer_tree_host_impl.h"
27 #include "cc/test/fake_output_surface.h"
28 #include "cc/test/layer_test_common.h"
29 #include "cc/test/layer_tree_test.h"
30 #include "cc/test/test_task_graph_runner.h"
31 #include "cc/test/test_web_graphics_context_3d.h"
32 #include "cc/trees/blocking_task_runner.h"
33 #include "cc/trees/layer_tree_host.h"
34 #include "cc/trees/layer_tree_impl.h"
35 #include "cc/trees/single_thread_proxy.h"
36 #include "gpu/GLES2/gl2extchromium.h"
37 #include "testing/gmock/include/gmock/gmock.h"
38 #include "testing/gtest/include/gtest/gtest.h"
40 using ::testing::Mock;
41 using ::testing::_;
42 using ::testing::AtLeast;
43 using ::testing::AnyNumber;
44 using ::testing::InvokeWithoutArgs;
46 namespace cc {
47 namespace {
49 gpu::Mailbox MailboxFromChar(char value) {
50 gpu::Mailbox mailbox;
51 memset(mailbox.name, value, sizeof(mailbox.name));
52 return mailbox;
55 class MockLayerTreeHost : public LayerTreeHost {
56 public:
57 static scoped_ptr<MockLayerTreeHost> Create(
58 FakeLayerTreeHostClient* client,
59 TaskGraphRunner* task_graph_runner) {
60 LayerTreeHost::InitParams params;
61 params.client = client;
62 params.task_graph_runner = task_graph_runner;
63 LayerTreeSettings settings;
64 params.settings = &settings;
65 return make_scoped_ptr(new MockLayerTreeHost(client, &params));
68 MOCK_METHOD0(SetNeedsCommit, void());
69 MOCK_METHOD0(SetNeedsUpdateLayers, void());
70 MOCK_METHOD0(StartRateLimiter, void());
71 MOCK_METHOD0(StopRateLimiter, void());
73 private:
74 MockLayerTreeHost(FakeLayerTreeHostClient* client,
75 LayerTreeHost::InitParams* params)
76 : LayerTreeHost(params) {
77 InitializeSingleThreaded(client, base::ThreadTaskRunnerHandle::Get(),
78 nullptr);
82 class FakeTextureLayerClient : public TextureLayerClient {
83 public:
84 FakeTextureLayerClient() : mailbox_changed_(true) {}
86 bool PrepareTextureMailbox(
87 TextureMailbox* mailbox,
88 scoped_ptr<SingleReleaseCallback>* release_callback,
89 bool use_shared_memory) override {
90 if (!mailbox_changed_)
91 return false;
93 *mailbox = mailbox_;
94 *release_callback = release_callback_.Pass();
95 mailbox_changed_ = false;
96 return true;
99 void set_mailbox(const TextureMailbox& mailbox,
100 scoped_ptr<SingleReleaseCallback> release_callback) {
101 mailbox_ = mailbox;
102 release_callback_ = release_callback.Pass();
103 mailbox_changed_ = true;
106 private:
107 TextureMailbox mailbox_;
108 scoped_ptr<SingleReleaseCallback> release_callback_;
109 bool mailbox_changed_;
110 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient);
113 class MockMailboxCallback {
114 public:
115 MOCK_METHOD3(Release,
116 void(const gpu::Mailbox& mailbox,
117 uint32 sync_point,
118 bool lost_resource));
119 MOCK_METHOD3(Release2,
120 void(SharedBitmap* shared_bitmap,
121 uint32 sync_point,
122 bool lost_resource));
123 MOCK_METHOD4(ReleaseImpl,
124 void(const gpu::Mailbox& mailbox,
125 uint32 sync_point,
126 bool lost_resource,
127 BlockingTaskRunner* main_thread_task_runner));
128 MOCK_METHOD4(ReleaseImpl2,
129 void(SharedBitmap* shared_bitmap,
130 uint32 sync_point,
131 bool lost_resource,
132 BlockingTaskRunner* main_thread_task_runner));
135 struct CommonMailboxObjects {
136 explicit CommonMailboxObjects(SharedBitmapManager* manager)
137 : mailbox_name1_(MailboxFromChar('1')),
138 mailbox_name2_(MailboxFromChar('2')),
139 sync_point1_(1),
140 sync_point2_(2) {
141 release_mailbox1_ = base::Bind(&MockMailboxCallback::Release,
142 base::Unretained(&mock_callback_),
143 mailbox_name1_);
144 release_mailbox2_ = base::Bind(&MockMailboxCallback::Release,
145 base::Unretained(&mock_callback_),
146 mailbox_name2_);
147 release_mailbox1_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl,
148 base::Unretained(&mock_callback_),
149 mailbox_name1_);
150 release_mailbox2_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl,
151 base::Unretained(&mock_callback_),
152 mailbox_name2_);
153 const uint32 arbitrary_target1 = GL_TEXTURE_2D;
154 const uint32 arbitrary_target2 = GL_TEXTURE_EXTERNAL_OES;
155 mailbox1_ = TextureMailbox(mailbox_name1_, arbitrary_target1, sync_point1_);
156 mailbox2_ = TextureMailbox(mailbox_name2_, arbitrary_target2, sync_point2_);
157 gfx::Size size(128, 128);
158 shared_bitmap_ = manager->AllocateSharedBitmap(size);
159 DCHECK(shared_bitmap_);
160 release_mailbox3_ =
161 base::Bind(&MockMailboxCallback::Release2,
162 base::Unretained(&mock_callback_), shared_bitmap_.get());
163 release_mailbox3_impl_ =
164 base::Bind(&MockMailboxCallback::ReleaseImpl2,
165 base::Unretained(&mock_callback_), shared_bitmap_.get());
166 mailbox3_ = TextureMailbox(shared_bitmap_.get(), size);
169 gpu::Mailbox mailbox_name1_;
170 gpu::Mailbox mailbox_name2_;
171 MockMailboxCallback mock_callback_;
172 ReleaseCallback release_mailbox1_;
173 ReleaseCallback release_mailbox2_;
174 ReleaseCallback release_mailbox3_;
175 ReleaseCallbackImpl release_mailbox1_impl_;
176 ReleaseCallbackImpl release_mailbox2_impl_;
177 ReleaseCallbackImpl release_mailbox3_impl_;
178 TextureMailbox mailbox1_;
179 TextureMailbox mailbox2_;
180 TextureMailbox mailbox3_;
181 uint32 sync_point1_;
182 uint32 sync_point2_;
183 scoped_ptr<SharedBitmap> shared_bitmap_;
186 class TextureLayerTest : public testing::Test {
187 public:
188 TextureLayerTest()
189 : fake_client_(
190 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
191 host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_),
192 test_data_(&shared_bitmap_manager_) {}
194 protected:
195 void SetUp() override {
196 layer_tree_host_ =
197 MockLayerTreeHost::Create(&fake_client_, &task_graph_runner_);
198 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
199 layer_tree_host_->SetViewportSize(gfx::Size(10, 10));
200 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
203 void TearDown() override {
204 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
205 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
207 layer_tree_host_->SetRootLayer(nullptr);
208 layer_tree_host_ = nullptr;
211 scoped_ptr<MockLayerTreeHost> layer_tree_host_;
212 FakeImplProxy proxy_;
213 FakeLayerTreeHostClient fake_client_;
214 TestSharedBitmapManager shared_bitmap_manager_;
215 TestTaskGraphRunner task_graph_runner_;
216 FakeLayerTreeHostImpl host_impl_;
217 CommonMailboxObjects test_data_;
218 LayerSettings layer_settings_;
221 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) {
222 scoped_refptr<TextureLayer> test_layer =
223 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
224 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer));
226 // Test properties that should call SetNeedsCommit. All properties need to
227 // be set to new values in order for SetNeedsCommit to be called.
228 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false));
229 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetNearestNeighbor(true));
230 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV(
231 gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f)));
232 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity(
233 0.5f, 0.5f, 0.5f, 0.5f));
234 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false));
235 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true));
238 TEST_F(TextureLayerTest, RateLimiter) {
239 FakeTextureLayerClient client;
240 scoped_refptr<TextureLayer> test_layer =
241 TextureLayer::CreateForMailbox(layer_settings_, &client);
242 test_layer->SetIsDrawable(true);
243 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
244 layer_tree_host_->SetRootLayer(test_layer);
246 // Don't rate limit until we invalidate.
247 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
248 test_layer->SetRateLimitContext(true);
249 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
251 // Do rate limit after we invalidate.
252 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
253 test_layer->SetNeedsDisplay();
254 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
256 // Stop rate limiter when we don't want it any more.
257 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
258 test_layer->SetRateLimitContext(false);
259 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
261 // Or we clear the client.
262 test_layer->SetRateLimitContext(true);
263 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
264 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
265 test_layer->ClearClient();
266 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
268 // Reset to a layer with a client, that started the rate limiter.
269 test_layer = TextureLayer::CreateForMailbox(layer_settings_, &client);
270 test_layer->SetIsDrawable(true);
271 test_layer->SetRateLimitContext(true);
272 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
273 layer_tree_host_->SetRootLayer(test_layer);
274 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
275 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
276 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
277 test_layer->SetNeedsDisplay();
278 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
280 // Stop rate limiter when we're removed from the tree.
281 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
282 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
283 layer_tree_host_->SetRootLayer(nullptr);
284 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
287 class TestMailboxHolder : public TextureLayer::TextureMailboxHolder {
288 public:
289 using TextureLayer::TextureMailboxHolder::Create;
291 protected:
292 ~TestMailboxHolder() override {}
295 class TextureLayerWithMailboxTest : public TextureLayerTest {
296 protected:
297 void TearDown() override {
298 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
299 EXPECT_CALL(test_data_.mock_callback_,
300 Release(test_data_.mailbox_name1_,
301 test_data_.sync_point1_,
302 false)).Times(1);
303 TextureLayerTest::TearDown();
307 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
308 scoped_refptr<TextureLayer> test_layer =
309 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
310 ASSERT_TRUE(test_layer.get());
312 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
313 layer_tree_host_->SetRootLayer(test_layer);
314 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
316 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
317 test_layer->SetTextureMailbox(
318 test_data_.mailbox1_,
319 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
320 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
322 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
323 EXPECT_CALL(test_data_.mock_callback_,
324 Release(test_data_.mailbox_name1_,
325 test_data_.sync_point1_,
326 false))
327 .Times(1);
328 test_layer->SetTextureMailbox(
329 test_data_.mailbox2_,
330 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
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 Release(test_data_.mailbox_name2_,
337 test_data_.sync_point2_,
338 false))
339 .Times(1);
340 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
341 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
342 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
344 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
345 test_layer->SetTextureMailbox(
346 test_data_.mailbox3_,
347 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
348 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
349 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
351 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
352 EXPECT_CALL(test_data_.mock_callback_,
353 Release2(test_data_.shared_bitmap_.get(), 0, false)).Times(1);
354 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
355 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
356 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
358 // Test destructor.
359 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
360 test_layer->SetTextureMailbox(
361 test_data_.mailbox1_,
362 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
365 TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) {
366 scoped_refptr<TextureLayer> test_layer =
367 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
368 ASSERT_TRUE(test_layer.get());
370 // These use the same gpu::Mailbox, but different sync points.
371 TextureMailbox mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D, 1);
372 TextureMailbox mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D, 2);
374 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
375 layer_tree_host_->SetRootLayer(test_layer);
376 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
378 // Set the mailbox the first time. It should cause a commit.
379 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
380 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox1);
381 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
383 // Set the mailbox again with a new sync point, as the backing texture has
384 // been updated. It should cause a new commit.
385 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
386 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox2);
387 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
390 class TextureLayerMailboxHolderTest : public TextureLayerTest {
391 public:
392 TextureLayerMailboxHolderTest()
393 : main_thread_("MAIN") {
394 main_thread_.Start();
395 main_thread_.message_loop()->task_runner()->PostTask(
396 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain,
397 base::Unretained(this)));
398 Wait(main_thread_);
401 void Wait(const base::Thread& thread) {
402 bool manual_reset = false;
403 bool initially_signaled = false;
404 base::WaitableEvent event(manual_reset, initially_signaled);
405 thread.message_loop()->task_runner()->PostTask(
406 FROM_HERE,
407 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
408 event.Wait();
411 void CreateMainRef() {
412 main_ref_ = TestMailboxHolder::Create(
413 test_data_.mailbox1_,
414 SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass();
417 void ReleaseMainRef() { main_ref_ = nullptr; }
419 void CreateImplRef(scoped_ptr<SingleReleaseCallbackImpl>* impl_ref) {
420 *impl_ref = main_ref_->holder()->GetCallbackForImplThread();
423 void CapturePostTasksAndWait(base::WaitableEvent* begin_capture,
424 base::WaitableEvent* wait_for_capture,
425 base::WaitableEvent* stop_capture) {
426 begin_capture->Wait();
427 BlockingTaskRunner::CapturePostTasks capture(
428 main_thread_task_runner_.get());
429 wait_for_capture->Signal();
430 stop_capture->Wait();
433 protected:
434 void InitializeOnMain() {
435 main_thread_task_runner_ =
436 BlockingTaskRunner::Create(main_thread_.task_runner());
439 scoped_ptr<TestMailboxHolder::MainThreadReference>
440 main_ref_;
441 base::Thread main_thread_;
442 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
445 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) {
446 scoped_refptr<TextureLayer> test_layer =
447 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
448 ASSERT_TRUE(test_layer.get());
450 main_thread_.message_loop()->task_runner()->PostTask(
451 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
452 base::Unretained(this)));
454 Wait(main_thread_);
456 // The texture layer is attached to compositor1, and passes a reference to its
457 // impl tree.
458 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
459 main_thread_.message_loop()->task_runner()->PostTask(
460 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
461 base::Unretained(this), &compositor1));
463 // Then the texture layer is removed and attached to compositor2, and passes a
464 // reference to its impl tree.
465 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
466 main_thread_.message_loop()->task_runner()->PostTask(
467 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
468 base::Unretained(this), &compositor2));
470 Wait(main_thread_);
471 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
473 // The compositors both destroy their impl trees before the main thread layer
474 // is destroyed.
475 compositor1->Run(100, false, main_thread_task_runner_.get());
476 compositor2->Run(200, false, main_thread_task_runner_.get());
478 Wait(main_thread_);
480 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
481 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
483 // The main thread ref is the last one, so the mailbox is released back to the
484 // embedder, with the last sync point provided by the impl trees.
485 EXPECT_CALL(test_data_.mock_callback_,
486 Release(test_data_.mailbox_name1_, 200, false)).Times(1);
488 main_thread_.message_loop()->task_runner()->PostTask(
489 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
490 base::Unretained(this)));
491 Wait(main_thread_);
492 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
495 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) {
496 scoped_refptr<TextureLayer> test_layer =
497 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
498 ASSERT_TRUE(test_layer.get());
500 main_thread_.message_loop()->task_runner()->PostTask(
501 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
502 base::Unretained(this)));
504 Wait(main_thread_);
506 // The texture layer is attached to compositor1, and passes a reference to its
507 // impl tree.
508 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
509 main_thread_.message_loop()->task_runner()->PostTask(
510 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
511 base::Unretained(this), &compositor1));
513 // Then the texture layer is removed and attached to compositor2, and passes a
514 // reference to its impl tree.
515 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
516 main_thread_.message_loop()->task_runner()->PostTask(
517 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
518 base::Unretained(this), &compositor2));
520 Wait(main_thread_);
521 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
523 // One compositor destroys their impl tree.
524 compositor1->Run(100, false, main_thread_task_runner_.get());
526 // Then the main thread reference is destroyed.
527 main_thread_.message_loop()->task_runner()->PostTask(
528 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
529 base::Unretained(this)));
531 Wait(main_thread_);
533 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
534 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
536 // The second impl reference is destroyed last, causing the mailbox to be
537 // released back to the embedder with the last sync point from the impl tree.
538 EXPECT_CALL(test_data_.mock_callback_,
539 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
541 compositor2->Run(200, true, main_thread_task_runner_.get());
542 Wait(main_thread_);
543 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
546 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) {
547 scoped_refptr<TextureLayer> test_layer =
548 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
549 ASSERT_TRUE(test_layer.get());
551 main_thread_.message_loop()->task_runner()->PostTask(
552 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
553 base::Unretained(this)));
555 Wait(main_thread_);
557 // The texture layer is attached to compositor1, and passes a reference to its
558 // impl tree.
559 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
560 main_thread_.message_loop()->task_runner()->PostTask(
561 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
562 base::Unretained(this), &compositor1));
564 // Then the texture layer is removed and attached to compositor2, and passes a
565 // reference to its impl tree.
566 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
567 main_thread_.message_loop()->task_runner()->PostTask(
568 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
569 base::Unretained(this), &compositor2));
571 Wait(main_thread_);
572 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
574 // The main thread reference is destroyed first.
575 main_thread_.message_loop()->task_runner()->PostTask(
576 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
577 base::Unretained(this)));
579 // One compositor destroys their impl tree.
580 compositor2->Run(200, false, main_thread_task_runner_.get());
582 Wait(main_thread_);
584 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
585 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
587 // The second impl reference is destroyed last, causing the mailbox to be
588 // released back to the embedder with the last sync point from the impl tree.
589 EXPECT_CALL(test_data_.mock_callback_,
590 Release(test_data_.mailbox_name1_, 100, true)).Times(1);
592 compositor1->Run(100, true, main_thread_task_runner_.get());
593 Wait(main_thread_);
594 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
597 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) {
598 scoped_refptr<TextureLayer> test_layer =
599 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
600 ASSERT_TRUE(test_layer.get());
602 main_thread_.message_loop()->task_runner()->PostTask(
603 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
604 base::Unretained(this)));
606 Wait(main_thread_);
608 // The texture layer is attached to compositor1, and passes a reference to its
609 // impl tree.
610 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
611 main_thread_.message_loop()->task_runner()->PostTask(
612 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
613 base::Unretained(this), &compositor1));
615 // Then the texture layer is removed and attached to compositor2, and passes a
616 // reference to its impl tree.
617 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
618 main_thread_.message_loop()->task_runner()->PostTask(
619 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
620 base::Unretained(this), &compositor2));
622 Wait(main_thread_);
623 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
625 // The main thread reference is destroyed first.
626 main_thread_.message_loop()->task_runner()->PostTask(
627 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
628 base::Unretained(this)));
630 EXPECT_CALL(test_data_.mock_callback_,
631 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
633 bool manual_reset = false;
634 bool initially_signaled = false;
635 base::WaitableEvent begin_capture(manual_reset, initially_signaled);
636 base::WaitableEvent wait_for_capture(manual_reset, initially_signaled);
637 base::WaitableEvent stop_capture(manual_reset, initially_signaled);
639 // Post a task to start capturing tasks on the main thread. This will block
640 // the main thread until we signal the |stop_capture| event.
641 main_thread_.message_loop()->task_runner()->PostTask(
642 FROM_HERE,
643 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait,
644 base::Unretained(this), &begin_capture, &wait_for_capture,
645 &stop_capture));
647 // Before the main thread capturing starts, one compositor destroys their
648 // impl reference. Since capturing did not start, this gets post-tasked to
649 // the main thread.
650 compositor1->Run(100, false, main_thread_task_runner_.get());
652 // Start capturing on the main thread.
653 begin_capture.Signal();
654 wait_for_capture.Wait();
656 // Meanwhile, the second compositor released its impl reference, but this task
657 // gets shortcutted directly to the main thread. This means the reference is
658 // released before compositor1, whose reference will be released later when
659 // the post-task is serviced. But since it was destroyed _on the impl thread_
660 // last, its sync point values should be used.
661 compositor2->Run(200, true, main_thread_task_runner_.get());
663 stop_capture.Signal();
664 Wait(main_thread_);
666 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
669 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest {
670 public:
671 TextureLayerImplWithMailboxThreadedCallback()
672 : callback_count_(0),
673 commit_count_(0) {}
675 // Make sure callback is received on main and doesn't block the impl thread.
676 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
677 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
678 EXPECT_FALSE(lost_resource);
679 ++callback_count_;
682 void SetMailbox(char mailbox_char) {
683 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
684 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
685 base::Bind(
686 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback,
687 base::Unretained(this)));
688 layer_->SetTextureMailbox(
689 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
690 callback.Pass());
693 void BeginTest() override {
694 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
696 gfx::Size bounds(100, 100);
697 root_ = Layer::Create(layer_settings());
698 root_->SetBounds(bounds);
700 layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr);
701 layer_->SetIsDrawable(true);
702 layer_->SetBounds(bounds);
704 root_->AddChild(layer_);
705 layer_tree_host()->SetRootLayer(root_);
706 layer_tree_host()->SetViewportSize(bounds);
707 SetMailbox('1');
708 EXPECT_EQ(0, callback_count_);
710 // Case #1: change mailbox before the commit. The old mailbox should be
711 // released immediately.
712 SetMailbox('2');
713 EXPECT_EQ(1, callback_count_);
714 PostSetNeedsCommitToMainThread();
717 void DidCommit() override {
718 ++commit_count_;
719 switch (commit_count_) {
720 case 1:
721 // Case #2: change mailbox after the commit (and draw), where the
722 // layer draws. The old mailbox should be released during the next
723 // commit.
724 SetMailbox('3');
725 EXPECT_EQ(1, callback_count_);
726 break;
727 case 2:
728 EXPECT_EQ(2, callback_count_);
729 // Case #3: change mailbox when the layer doesn't draw. The old
730 // mailbox should be released during the next commit.
731 layer_->SetBounds(gfx::Size());
732 SetMailbox('4');
733 break;
734 case 3:
735 EXPECT_EQ(3, callback_count_);
736 // Case #4: release mailbox that was committed but never drawn. The
737 // old mailbox should be released during the next commit.
738 layer_->SetTextureMailbox(TextureMailbox(), nullptr);
739 break;
740 case 4:
741 // With impl painting, the texture mailbox will still be on the impl
742 // thread when the commit finishes, because the layer is not drawble
743 // when it has no texture mailbox, and thus does not block the commit
744 // on activation. So, we wait for activation.
745 // TODO(danakj): fix this. crbug.com/277953
746 layer_tree_host()->SetNeedsCommit();
747 break;
748 case 5:
749 EXPECT_EQ(4, callback_count_);
750 // Restore a mailbox for the next step.
751 SetMailbox('5');
752 break;
753 case 6:
754 // Case #5: remove layer from tree. Callback should *not* be called, the
755 // mailbox is returned to the main thread.
756 EXPECT_EQ(4, callback_count_);
757 layer_->RemoveFromParent();
758 break;
759 case 7:
760 // With impl painting, the texture mailbox will still be on the impl
761 // thread when the commit finishes, because the layer is not around to
762 // block the commit on activation anymore. So, we wait for activation.
763 // TODO(danakj): fix this. crbug.com/277953
764 layer_tree_host()->SetNeedsCommit();
765 break;
766 case 8:
767 EXPECT_EQ(4, callback_count_);
768 // Resetting the mailbox will call the callback now.
769 layer_->SetTextureMailbox(TextureMailbox(), nullptr);
770 EXPECT_EQ(5, callback_count_);
771 EndTest();
772 break;
773 default:
774 NOTREACHED();
775 break;
779 void AfterTest() override {}
781 private:
782 base::ThreadChecker main_thread_;
783 int callback_count_;
784 int commit_count_;
785 scoped_refptr<Layer> root_;
786 scoped_refptr<TextureLayer> layer_;
789 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
790 TextureLayerImplWithMailboxThreadedCallback);
793 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
794 protected:
795 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
797 static void ReleaseCallback(uint32 sync_point, bool lost_resource) {}
799 void SetMailbox(char mailbox_char) {
800 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
801 base::Bind(
802 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
803 layer_->SetTextureMailbox(
804 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
805 callback.Pass());
808 void BeginTest() override {
809 gfx::Size bounds(100, 100);
810 root_ = Layer::Create(layer_settings());
811 root_->SetBounds(bounds);
813 layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr);
814 layer_->SetIsDrawable(true);
815 layer_->SetBounds(bounds);
817 root_->AddChild(layer_);
818 layer_tree_host()->SetRootLayer(root_);
819 layer_tree_host()->SetViewportSize(bounds);
820 SetMailbox('1');
822 PostSetNeedsCommitToMainThread();
825 void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
826 ++activate_count_;
829 void DidCommit() override {
830 switch (layer_tree_host()->source_frame_number()) {
831 case 1:
832 // The first mailbox has been activated. Set a new mailbox, and
833 // expect the next commit to finish *after* it is activated.
834 SetMailbox('2');
835 break;
836 case 2:
837 // The second mailbox has been activated. Remove the layer from
838 // the tree to cause another commit/activation. The commit should
839 // finish *after* the layer is removed from the active tree.
840 layer_->RemoveFromParent();
841 break;
842 case 3:
843 EndTest();
844 break;
848 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
849 switch (host_impl->active_tree()->source_frame_number()) {
850 case 0: {
851 // The activate for the 1st mailbox should have happened before now.
852 EXPECT_EQ(1, activate_count_);
853 break;
855 case 1: {
856 // The activate for the 2nd mailbox should have happened before now.
857 EXPECT_EQ(2, activate_count_);
858 break;
860 case 2: {
861 // The activate to remove the layer should have happened before now.
862 EXPECT_EQ(3, activate_count_);
863 break;
865 case 3: {
866 NOTREACHED();
867 break;
872 void AfterTest() override {}
874 int activate_count_;
875 scoped_refptr<Layer> root_;
876 scoped_refptr<TextureLayer> layer_;
879 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
880 TextureLayerMailboxIsActivatedDuringCommit);
882 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
883 protected:
884 TextureLayerImplWithMailboxTest()
885 : fake_client_(
886 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
888 void SetUp() override {
889 TextureLayerTest::SetUp();
890 layer_tree_host_ =
891 MockLayerTreeHost::Create(&fake_client_, &task_graph_runner_);
892 EXPECT_TRUE(host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()));
895 bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
896 bool will_draw = layer->WillDraw(
897 mode, host_impl_.active_tree()->resource_provider());
898 if (will_draw)
899 layer->DidDraw(host_impl_.active_tree()->resource_provider());
900 return will_draw;
903 FakeLayerTreeHostClient fake_client_;
906 // Test conditions for results of TextureLayerImpl::WillDraw under
907 // different configurations of different mailbox, texture_id, and draw_mode.
908 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
909 EXPECT_CALL(
910 test_data_.mock_callback_,
911 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
912 .Times(AnyNumber());
913 EXPECT_CALL(test_data_.mock_callback_,
914 ReleaseImpl2(test_data_.shared_bitmap_.get(), 0, false, _))
915 .Times(AnyNumber());
916 // Hardware mode.
918 scoped_ptr<TextureLayerImpl> impl_layer =
919 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
920 impl_layer->SetTextureMailbox(
921 test_data_.mailbox1_,
922 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
923 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
927 scoped_ptr<TextureLayerImpl> impl_layer =
928 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
929 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
930 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
934 // Software resource.
935 scoped_ptr<TextureLayerImpl> impl_layer =
936 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
937 impl_layer->SetTextureMailbox(
938 test_data_.mailbox3_,
939 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
940 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
943 // Software mode.
945 scoped_ptr<TextureLayerImpl> impl_layer =
946 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
947 impl_layer->SetTextureMailbox(
948 test_data_.mailbox1_,
949 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
950 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
954 scoped_ptr<TextureLayerImpl> impl_layer =
955 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
956 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
957 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
961 // Software resource.
962 scoped_ptr<TextureLayerImpl> impl_layer =
963 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
964 impl_layer->SetTextureMailbox(
965 test_data_.mailbox3_,
966 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
967 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
970 // Resourceless software mode.
972 scoped_ptr<TextureLayerImpl> impl_layer =
973 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
974 impl_layer->SetTextureMailbox(
975 test_data_.mailbox1_,
976 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
977 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
981 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
982 host_impl_.CreatePendingTree();
983 scoped_ptr<TextureLayerImpl> pending_layer;
984 pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1);
985 ASSERT_TRUE(pending_layer);
987 scoped_ptr<LayerImpl> active_layer(
988 pending_layer->CreateLayerImpl(host_impl_.active_tree()));
989 ASSERT_TRUE(active_layer);
991 pending_layer->SetTextureMailbox(
992 test_data_.mailbox1_,
993 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
995 // Test multiple commits without an activation.
996 EXPECT_CALL(
997 test_data_.mock_callback_,
998 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
999 .Times(1);
1000 pending_layer->SetTextureMailbox(
1001 test_data_.mailbox2_,
1002 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox2_impl_));
1003 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1005 // Test callback after activation.
1006 pending_layer->PushPropertiesTo(active_layer.get());
1007 active_layer->DidBecomeActive();
1009 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1010 pending_layer->SetTextureMailbox(
1011 test_data_.mailbox1_,
1012 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1013 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1015 EXPECT_CALL(test_data_.mock_callback_,
1016 ReleaseImpl(test_data_.mailbox_name2_, _, false, _)).Times(1);
1017 pending_layer->PushPropertiesTo(active_layer.get());
1018 active_layer->DidBecomeActive();
1019 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1021 // Test resetting the mailbox.
1022 EXPECT_CALL(test_data_.mock_callback_,
1023 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1024 pending_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1025 pending_layer->PushPropertiesTo(active_layer.get());
1026 active_layer->DidBecomeActive();
1027 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1029 // Test destructor.
1030 EXPECT_CALL(
1031 test_data_.mock_callback_,
1032 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
1033 .Times(1);
1034 pending_layer->SetTextureMailbox(
1035 test_data_.mailbox1_,
1036 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1039 TEST_F(TextureLayerImplWithMailboxTest,
1040 TestDestructorCallbackOnCreatedResource) {
1041 scoped_ptr<TextureLayerImpl> impl_layer;
1042 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1043 ASSERT_TRUE(impl_layer);
1045 EXPECT_CALL(test_data_.mock_callback_,
1046 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1047 impl_layer->SetTextureMailbox(
1048 test_data_.mailbox1_,
1049 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1050 impl_layer->DidBecomeActive();
1051 EXPECT_TRUE(impl_layer->WillDraw(
1052 DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1053 impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1054 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1057 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1058 ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1059 ResourceId id = provider->CreateResourceFromTextureMailbox(
1060 test_data_.mailbox1_,
1061 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1062 provider->AllocateForTesting(id);
1064 // Transfer some resources to the parent.
1065 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1066 resource_ids_to_transfer.push_back(id);
1067 TransferableResourceArray list;
1068 provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1069 EXPECT_TRUE(provider->InUseByConsumer(id));
1070 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1071 provider->DeleteResource(id);
1072 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1073 EXPECT_CALL(test_data_.mock_callback_,
1074 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1075 ReturnedResourceArray returned;
1076 TransferableResource::ReturnResources(list, &returned);
1077 provider->ReceiveReturnsFromParent(returned);
1080 // Checks that TextureLayer::Update does not cause an extra commit when setting
1081 // the texture mailbox.
1082 class TextureLayerNoExtraCommitForMailboxTest
1083 : public LayerTreeTest,
1084 public TextureLayerClient {
1085 public:
1086 // TextureLayerClient implementation.
1087 bool PrepareTextureMailbox(
1088 TextureMailbox* texture_mailbox,
1089 scoped_ptr<SingleReleaseCallback>* release_callback,
1090 bool use_shared_memory) override {
1091 if (layer_tree_host()->source_frame_number() == 1) {
1092 // Once this has been committed, the mailbox will be released.
1093 *texture_mailbox = TextureMailbox();
1094 return true;
1097 *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1098 *release_callback = SingleReleaseCallback::Create(
1099 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1100 base::Unretained(this)));
1101 return true;
1104 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1105 // Source frame number during callback is the same as the source frame
1106 // on which it was released.
1107 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1108 EndTest();
1111 void SetupTree() override {
1112 scoped_refptr<Layer> root = Layer::Create(layer_settings());
1113 root->SetBounds(gfx::Size(10, 10));
1114 root->SetIsDrawable(true);
1116 texture_layer_ = TextureLayer::CreateForMailbox(layer_settings(), this);
1117 texture_layer_->SetBounds(gfx::Size(10, 10));
1118 texture_layer_->SetIsDrawable(true);
1119 root->AddChild(texture_layer_);
1121 layer_tree_host()->SetRootLayer(root);
1122 LayerTreeTest::SetupTree();
1125 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1127 void DidCommitAndDrawFrame() override {
1128 switch (layer_tree_host()->source_frame_number()) {
1129 case 1:
1130 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1131 // Invalidate the texture layer to clear the mailbox before
1132 // ending the test.
1133 texture_layer_->SetNeedsDisplay();
1134 break;
1135 case 2:
1136 break;
1137 default:
1138 NOTREACHED();
1139 break;
1143 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1144 ASSERT_TRUE(result);
1145 DelegatedFrameData* delegated_frame_data =
1146 output_surface()->last_sent_frame().delegated_frame_data.get();
1147 if (!delegated_frame_data)
1148 return;
1150 // Return all resources immediately.
1151 TransferableResourceArray resources_to_return =
1152 output_surface()->resources_held_by_parent();
1154 CompositorFrameAck ack;
1155 for (size_t i = 0; i < resources_to_return.size(); ++i)
1156 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1157 host_impl->ReclaimResources(&ack);
1160 void AfterTest() override {}
1162 private:
1163 scoped_refptr<TextureLayer> texture_layer_;
1166 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1168 // Checks that changing a mailbox in the client for a TextureLayer that's
1169 // invisible correctly works and uses the new mailbox as soon as the layer
1170 // becomes visible (and returns the old one).
1171 class TextureLayerChangeInvisibleMailboxTest
1172 : public LayerTreeTest,
1173 public TextureLayerClient {
1174 public:
1175 TextureLayerChangeInvisibleMailboxTest()
1176 : mailbox_changed_(true),
1177 mailbox_returned_(0),
1178 prepare_called_(0),
1179 commit_count_(0) {
1180 mailbox_ = MakeMailbox('1');
1183 // TextureLayerClient implementation.
1184 bool PrepareTextureMailbox(
1185 TextureMailbox* mailbox,
1186 scoped_ptr<SingleReleaseCallback>* release_callback,
1187 bool use_shared_memory) override {
1188 ++prepare_called_;
1189 if (!mailbox_changed_)
1190 return false;
1191 *mailbox = mailbox_;
1192 *release_callback = SingleReleaseCallback::Create(
1193 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1194 base::Unretained(this)));
1195 return true;
1198 TextureMailbox MakeMailbox(char name) {
1199 return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0);
1202 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1203 ++mailbox_returned_;
1206 void SetupTree() override {
1207 scoped_refptr<Layer> root = Layer::Create(layer_settings());
1208 root->SetBounds(gfx::Size(10, 10));
1209 root->SetIsDrawable(true);
1211 solid_layer_ = SolidColorLayer::Create(layer_settings());
1212 solid_layer_->SetBounds(gfx::Size(10, 10));
1213 solid_layer_->SetIsDrawable(true);
1214 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1215 root->AddChild(solid_layer_);
1217 parent_layer_ = Layer::Create(layer_settings());
1218 parent_layer_->SetBounds(gfx::Size(10, 10));
1219 parent_layer_->SetIsDrawable(true);
1220 root->AddChild(parent_layer_);
1222 texture_layer_ = TextureLayer::CreateForMailbox(layer_settings(), this);
1223 texture_layer_->SetBounds(gfx::Size(10, 10));
1224 texture_layer_->SetIsDrawable(true);
1225 parent_layer_->AddChild(texture_layer_);
1227 layer_tree_host()->SetRootLayer(root);
1228 LayerTreeTest::SetupTree();
1231 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1233 void DidCommitAndDrawFrame() override {
1234 ++commit_count_;
1235 switch (commit_count_) {
1236 case 1:
1237 // We should have updated the layer, committing the texture.
1238 EXPECT_EQ(1, prepare_called_);
1239 // Make layer invisible.
1240 parent_layer_->SetOpacity(0.f);
1241 break;
1242 case 2:
1243 // Layer shouldn't have been updated.
1244 EXPECT_EQ(1, prepare_called_);
1245 // Change the texture.
1246 mailbox_ = MakeMailbox('2');
1247 mailbox_changed_ = true;
1248 texture_layer_->SetNeedsDisplay();
1249 // Force a change to make sure we draw a frame.
1250 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1251 break;
1252 case 3:
1253 // Layer shouldn't have been updated.
1254 EXPECT_EQ(1, prepare_called_);
1255 // So the old mailbox isn't returned yet.
1256 EXPECT_EQ(0, mailbox_returned_);
1257 // Make layer visible again.
1258 parent_layer_->SetOpacity(1.f);
1259 break;
1260 case 4:
1261 // Layer should have been updated.
1262 EXPECT_EQ(2, prepare_called_);
1263 // So the old mailbox should have been returned already.
1264 EXPECT_EQ(1, mailbox_returned_);
1265 texture_layer_->ClearClient();
1266 break;
1267 case 5:
1268 EXPECT_EQ(2, mailbox_returned_);
1269 EndTest();
1270 break;
1271 default:
1272 NOTREACHED();
1273 break;
1277 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1278 ASSERT_TRUE(result);
1279 DelegatedFrameData* delegated_frame_data =
1280 output_surface()->last_sent_frame().delegated_frame_data.get();
1281 if (!delegated_frame_data)
1282 return;
1284 // Return all resources immediately.
1285 TransferableResourceArray resources_to_return =
1286 output_surface()->resources_held_by_parent();
1288 CompositorFrameAck ack;
1289 for (size_t i = 0; i < resources_to_return.size(); ++i)
1290 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1291 host_impl->ReclaimResources(&ack);
1294 void AfterTest() override {}
1296 private:
1297 scoped_refptr<SolidColorLayer> solid_layer_;
1298 scoped_refptr<Layer> parent_layer_;
1299 scoped_refptr<TextureLayer> texture_layer_;
1301 // Used on the main thread.
1302 bool mailbox_changed_;
1303 TextureMailbox mailbox_;
1304 int mailbox_returned_;
1305 int prepare_called_;
1306 int commit_count_;
1309 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1311 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1312 // the mailbox back to TextureLayerClient.
1313 class TextureLayerReleaseResourcesBase
1314 : public LayerTreeTest,
1315 public TextureLayerClient {
1316 public:
1317 // TextureLayerClient implementation.
1318 bool PrepareTextureMailbox(
1319 TextureMailbox* mailbox,
1320 scoped_ptr<SingleReleaseCallback>* release_callback,
1321 bool use_shared_memory) override {
1322 *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1323 *release_callback = SingleReleaseCallback::Create(
1324 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1325 base::Unretained(this)));
1326 return true;
1329 void MailboxReleased(unsigned sync_point, bool lost_resource) {
1330 mailbox_released_ = true;
1333 void SetupTree() override {
1334 LayerTreeTest::SetupTree();
1336 scoped_refptr<TextureLayer> texture_layer =
1337 TextureLayer::CreateForMailbox(layer_settings(), this);
1338 texture_layer->SetBounds(gfx::Size(10, 10));
1339 texture_layer->SetIsDrawable(true);
1341 layer_tree_host()->root_layer()->AddChild(texture_layer);
1344 void BeginTest() override {
1345 mailbox_released_ = false;
1346 PostSetNeedsCommitToMainThread();
1349 void DidCommitAndDrawFrame() override { EndTest(); }
1351 void AfterTest() override { EXPECT_TRUE(mailbox_released_); }
1353 private:
1354 bool mailbox_released_;
1357 class TextureLayerReleaseResourcesAfterCommit
1358 : public TextureLayerReleaseResourcesBase {
1359 public:
1360 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
1361 LayerTreeImpl* tree = nullptr;
1362 tree = host_impl->sync_tree();
1363 tree->root_layer()->children()[0]->ReleaseResources();
1367 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1369 class TextureLayerReleaseResourcesAfterActivate
1370 : public TextureLayerReleaseResourcesBase {
1371 public:
1372 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
1373 host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
1377 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
1379 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
1380 public:
1381 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1382 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1383 EXPECT_FALSE(lost_resource);
1384 ++callback_count_;
1385 EndTest();
1388 void SetMailbox(char mailbox_char) {
1389 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1390 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1391 base::Bind(
1392 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
1393 base::Unretained(this)));
1394 layer_->SetTextureMailbox(
1395 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1396 callback.Pass());
1399 void SetupTree() override {
1400 gfx::Size bounds(100, 100);
1401 root_ = Layer::Create(layer_settings());
1402 root_->SetBounds(bounds);
1404 layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr);
1405 layer_->SetIsDrawable(true);
1406 layer_->SetBounds(bounds);
1408 root_->AddChild(layer_);
1409 layer_tree_host()->SetRootLayer(root_);
1410 layer_tree_host()->SetViewportSize(bounds);
1413 void BeginTest() override {
1414 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1416 callback_count_ = 0;
1418 // Set the mailbox on the main thread.
1419 SetMailbox('1');
1420 EXPECT_EQ(0, callback_count_);
1422 PostSetNeedsCommitToMainThread();
1425 void DidCommitAndDrawFrame() override {
1426 switch (layer_tree_host()->source_frame_number()) {
1427 case 1:
1428 // Delete the TextureLayer on the main thread while the mailbox is in
1429 // the impl tree.
1430 layer_->RemoveFromParent();
1431 layer_ = nullptr;
1432 break;
1436 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1438 private:
1439 base::ThreadChecker main_thread_;
1440 int callback_count_;
1441 scoped_refptr<Layer> root_;
1442 scoped_refptr<TextureLayer> layer_;
1445 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1446 TextureLayerWithMailboxMainThreadDeleted);
1448 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
1449 public:
1450 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1451 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1452 EXPECT_FALSE(lost_resource);
1453 ++callback_count_;
1454 EndTest();
1457 void SetMailbox(char mailbox_char) {
1458 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1459 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1460 base::Bind(
1461 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
1462 base::Unretained(this)));
1463 layer_->SetTextureMailbox(
1464 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1465 callback.Pass());
1468 void SetupTree() override {
1469 gfx::Size bounds(100, 100);
1470 root_ = Layer::Create(layer_settings());
1471 root_->SetBounds(bounds);
1473 layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr);
1474 layer_->SetIsDrawable(true);
1475 layer_->SetBounds(bounds);
1477 root_->AddChild(layer_);
1478 layer_tree_host()->SetRootLayer(root_);
1479 layer_tree_host()->SetViewportSize(bounds);
1482 void BeginTest() override {
1483 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1485 callback_count_ = 0;
1487 // Set the mailbox on the main thread.
1488 SetMailbox('1');
1489 EXPECT_EQ(0, callback_count_);
1491 PostSetNeedsCommitToMainThread();
1494 void DidCommitAndDrawFrame() override {
1495 switch (layer_tree_host()->source_frame_number()) {
1496 case 1:
1497 // Remove the TextureLayer on the main thread while the mailbox is in
1498 // the impl tree, but don't delete the TextureLayer until after the impl
1499 // tree side is deleted.
1500 layer_->RemoveFromParent();
1501 break;
1502 case 2:
1503 layer_ = nullptr;
1504 break;
1508 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1510 private:
1511 base::ThreadChecker main_thread_;
1512 int callback_count_;
1513 scoped_refptr<Layer> root_;
1514 scoped_refptr<TextureLayer> layer_;
1517 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1518 TextureLayerWithMailboxImplThreadDeleted);
1520 } // namespace
1521 } // namespace cc