Support swap promises that are pinned to a particular layer tree.
[chromium-blink-merge.git] / cc / layers / texture_layer_unittest.cc
blob82894299f7ae249248d7bbc47b825bea4930cde6
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/lock.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "base/threading/thread.h"
18 #include "base/time/time.h"
19 #include "cc/layers/solid_color_layer.h"
20 #include "cc/layers/texture_layer_client.h"
21 #include "cc/layers/texture_layer_impl.h"
22 #include "cc/output/compositor_frame_ack.h"
23 #include "cc/output/context_provider.h"
24 #include "cc/resources/returned_resource.h"
25 #include "cc/test/fake_impl_proxy.h"
26 #include "cc/test/fake_layer_tree_host_client.h"
27 #include "cc/test/fake_layer_tree_host_impl.h"
28 #include "cc/test/fake_output_surface.h"
29 #include "cc/test/layer_test_common.h"
30 #include "cc/test/layer_tree_test.h"
31 #include "cc/test/test_task_graph_runner.h"
32 #include "cc/test/test_web_graphics_context_3d.h"
33 #include "cc/trees/blocking_task_runner.h"
34 #include "cc/trees/layer_tree_host.h"
35 #include "cc/trees/layer_tree_impl.h"
36 #include "cc/trees/single_thread_proxy.h"
37 #include "gpu/GLES2/gl2extchromium.h"
38 #include "testing/gmock/include/gmock/gmock.h"
39 #include "testing/gtest/include/gtest/gtest.h"
41 using ::testing::Mock;
42 using ::testing::_;
43 using ::testing::AtLeast;
44 using ::testing::AnyNumber;
45 using ::testing::InvokeWithoutArgs;
47 namespace cc {
48 namespace {
50 gpu::Mailbox MailboxFromChar(char value) {
51 gpu::Mailbox mailbox;
52 memset(mailbox.name, value, sizeof(mailbox.name));
53 return mailbox;
56 class MockLayerTreeHost : public LayerTreeHost {
57 public:
58 static scoped_ptr<MockLayerTreeHost> Create(
59 FakeLayerTreeHostClient* client,
60 TaskGraphRunner* task_graph_runner) {
61 LayerTreeHost::InitParams params;
62 params.client = client;
63 params.task_graph_runner = task_graph_runner;
64 LayerTreeSettings settings;
65 params.settings = &settings;
66 return make_scoped_ptr(new MockLayerTreeHost(client, &params));
69 MOCK_METHOD0(SetNeedsCommit, void());
70 MOCK_METHOD0(SetNeedsUpdateLayers, void());
71 MOCK_METHOD0(StartRateLimiter, void());
72 MOCK_METHOD0(StopRateLimiter, void());
74 private:
75 MockLayerTreeHost(FakeLayerTreeHostClient* client,
76 LayerTreeHost::InitParams* params)
77 : LayerTreeHost(params) {
78 InitializeSingleThreaded(client, base::ThreadTaskRunnerHandle::Get(),
79 nullptr);
83 class FakeTextureLayerClient : public TextureLayerClient {
84 public:
85 FakeTextureLayerClient() : mailbox_changed_(true) {}
87 bool PrepareTextureMailbox(
88 TextureMailbox* mailbox,
89 scoped_ptr<SingleReleaseCallback>* release_callback,
90 bool use_shared_memory) override {
91 if (!mailbox_changed_)
92 return false;
94 *mailbox = mailbox_;
95 *release_callback = release_callback_.Pass();
96 mailbox_changed_ = false;
97 return true;
100 void set_mailbox(const TextureMailbox& mailbox,
101 scoped_ptr<SingleReleaseCallback> release_callback) {
102 mailbox_ = mailbox;
103 release_callback_ = release_callback.Pass();
104 mailbox_changed_ = true;
107 private:
108 TextureMailbox mailbox_;
109 scoped_ptr<SingleReleaseCallback> release_callback_;
110 bool mailbox_changed_;
111 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient);
114 class MockMailboxCallback {
115 public:
116 MOCK_METHOD3(Release,
117 void(const gpu::Mailbox& mailbox,
118 uint32 sync_point,
119 bool lost_resource));
120 MOCK_METHOD3(Release2,
121 void(SharedBitmap* shared_bitmap,
122 uint32 sync_point,
123 bool lost_resource));
124 MOCK_METHOD4(ReleaseImpl,
125 void(const gpu::Mailbox& mailbox,
126 uint32 sync_point,
127 bool lost_resource,
128 BlockingTaskRunner* main_thread_task_runner));
129 MOCK_METHOD4(ReleaseImpl2,
130 void(SharedBitmap* shared_bitmap,
131 uint32 sync_point,
132 bool lost_resource,
133 BlockingTaskRunner* main_thread_task_runner));
136 struct CommonMailboxObjects {
137 explicit CommonMailboxObjects(SharedBitmapManager* manager)
138 : mailbox_name1_(MailboxFromChar('1')),
139 mailbox_name2_(MailboxFromChar('2')),
140 sync_point1_(1),
141 sync_point2_(2) {
142 release_mailbox1_ = base::Bind(&MockMailboxCallback::Release,
143 base::Unretained(&mock_callback_),
144 mailbox_name1_);
145 release_mailbox2_ = base::Bind(&MockMailboxCallback::Release,
146 base::Unretained(&mock_callback_),
147 mailbox_name2_);
148 release_mailbox1_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl,
149 base::Unretained(&mock_callback_),
150 mailbox_name1_);
151 release_mailbox2_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl,
152 base::Unretained(&mock_callback_),
153 mailbox_name2_);
154 const uint32 arbitrary_target1 = GL_TEXTURE_2D;
155 const uint32 arbitrary_target2 = GL_TEXTURE_EXTERNAL_OES;
156 mailbox1_ = TextureMailbox(mailbox_name1_, arbitrary_target1, sync_point1_);
157 mailbox2_ = TextureMailbox(mailbox_name2_, arbitrary_target2, sync_point2_);
158 gfx::Size size(128, 128);
159 shared_bitmap_ = manager->AllocateSharedBitmap(size);
160 DCHECK(shared_bitmap_);
161 release_mailbox3_ =
162 base::Bind(&MockMailboxCallback::Release2,
163 base::Unretained(&mock_callback_), shared_bitmap_.get());
164 release_mailbox3_impl_ =
165 base::Bind(&MockMailboxCallback::ReleaseImpl2,
166 base::Unretained(&mock_callback_), shared_bitmap_.get());
167 mailbox3_ = TextureMailbox(shared_bitmap_.get(), size);
170 gpu::Mailbox mailbox_name1_;
171 gpu::Mailbox mailbox_name2_;
172 MockMailboxCallback mock_callback_;
173 ReleaseCallback release_mailbox1_;
174 ReleaseCallback release_mailbox2_;
175 ReleaseCallback release_mailbox3_;
176 ReleaseCallbackImpl release_mailbox1_impl_;
177 ReleaseCallbackImpl release_mailbox2_impl_;
178 ReleaseCallbackImpl release_mailbox3_impl_;
179 TextureMailbox mailbox1_;
180 TextureMailbox mailbox2_;
181 TextureMailbox mailbox3_;
182 uint32 sync_point1_;
183 uint32 sync_point2_;
184 scoped_ptr<SharedBitmap> shared_bitmap_;
187 class TextureLayerTest : public testing::Test {
188 public:
189 TextureLayerTest()
190 : fake_client_(
191 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
192 host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_),
193 test_data_(&shared_bitmap_manager_) {}
195 protected:
196 void SetUp() override {
197 layer_tree_host_ =
198 MockLayerTreeHost::Create(&fake_client_, &task_graph_runner_);
199 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
200 layer_tree_host_->SetViewportSize(gfx::Size(10, 10));
201 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
204 void TearDown() override {
205 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
206 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
208 layer_tree_host_->SetRootLayer(nullptr);
209 layer_tree_host_ = nullptr;
212 scoped_ptr<MockLayerTreeHost> layer_tree_host_;
213 FakeImplProxy proxy_;
214 FakeLayerTreeHostClient fake_client_;
215 TestSharedBitmapManager shared_bitmap_manager_;
216 TestTaskGraphRunner task_graph_runner_;
217 FakeLayerTreeHostImpl host_impl_;
218 CommonMailboxObjects test_data_;
219 LayerSettings layer_settings_;
222 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) {
223 scoped_refptr<TextureLayer> test_layer =
224 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
225 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer));
227 // Test properties that should call SetNeedsCommit. All properties need to
228 // be set to new values in order for SetNeedsCommit to be called.
229 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false));
230 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetNearestNeighbor(true));
231 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV(
232 gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f)));
233 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity(
234 0.5f, 0.5f, 0.5f, 0.5f));
235 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false));
236 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true));
239 TEST_F(TextureLayerTest, RateLimiter) {
240 FakeTextureLayerClient client;
241 scoped_refptr<TextureLayer> test_layer =
242 TextureLayer::CreateForMailbox(layer_settings_, &client);
243 test_layer->SetIsDrawable(true);
244 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
245 layer_tree_host_->SetRootLayer(test_layer);
247 // Don't rate limit until we invalidate.
248 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
249 test_layer->SetRateLimitContext(true);
250 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
252 // Do rate limit after we invalidate.
253 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
254 test_layer->SetNeedsDisplay();
255 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
257 // Stop rate limiter when we don't want it any more.
258 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
259 test_layer->SetRateLimitContext(false);
260 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
262 // Or we clear the client.
263 test_layer->SetRateLimitContext(true);
264 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
265 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
266 test_layer->ClearClient();
267 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
269 // Reset to a layer with a client, that started the rate limiter.
270 test_layer = TextureLayer::CreateForMailbox(layer_settings_, &client);
271 test_layer->SetIsDrawable(true);
272 test_layer->SetRateLimitContext(true);
273 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
274 layer_tree_host_->SetRootLayer(test_layer);
275 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
276 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
277 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
278 test_layer->SetNeedsDisplay();
279 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
281 // Stop rate limiter when we're removed from the tree.
282 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
283 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
284 layer_tree_host_->SetRootLayer(nullptr);
285 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
288 class TestMailboxHolder : public TextureLayer::TextureMailboxHolder {
289 public:
290 using TextureLayer::TextureMailboxHolder::Create;
292 protected:
293 ~TestMailboxHolder() override {}
296 class TextureLayerWithMailboxTest : public TextureLayerTest {
297 protected:
298 void TearDown() override {
299 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
300 EXPECT_CALL(test_data_.mock_callback_,
301 Release(test_data_.mailbox_name1_,
302 test_data_.sync_point1_,
303 false)).Times(1);
304 TextureLayerTest::TearDown();
308 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
309 scoped_refptr<TextureLayer> test_layer =
310 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
311 ASSERT_TRUE(test_layer.get());
313 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
314 layer_tree_host_->SetRootLayer(test_layer);
315 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
317 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
318 test_layer->SetTextureMailbox(
319 test_data_.mailbox1_,
320 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
321 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
323 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
324 EXPECT_CALL(test_data_.mock_callback_,
325 Release(test_data_.mailbox_name1_,
326 test_data_.sync_point1_,
327 false))
328 .Times(1);
329 test_layer->SetTextureMailbox(
330 test_data_.mailbox2_,
331 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
332 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
333 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
335 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
336 EXPECT_CALL(test_data_.mock_callback_,
337 Release(test_data_.mailbox_name2_,
338 test_data_.sync_point2_,
339 false))
340 .Times(1);
341 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
342 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
343 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
345 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
346 test_layer->SetTextureMailbox(
347 test_data_.mailbox3_,
348 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
349 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
350 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
352 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
353 EXPECT_CALL(test_data_.mock_callback_,
354 Release2(test_data_.shared_bitmap_.get(), 0, false)).Times(1);
355 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
356 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
357 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
359 // Test destructor.
360 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
361 test_layer->SetTextureMailbox(
362 test_data_.mailbox1_,
363 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
366 TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) {
367 scoped_refptr<TextureLayer> test_layer =
368 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
369 ASSERT_TRUE(test_layer.get());
371 // These use the same gpu::Mailbox, but different sync points.
372 TextureMailbox mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D, 1);
373 TextureMailbox mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D, 2);
375 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
376 layer_tree_host_->SetRootLayer(test_layer);
377 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
379 // Set the mailbox the first time. It should cause a commit.
380 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
381 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox1);
382 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
384 // Set the mailbox again with a new sync point, as the backing texture has
385 // been updated. It should cause a new commit.
386 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
387 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox2);
388 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
391 class TextureLayerMailboxHolderTest : public TextureLayerTest {
392 public:
393 TextureLayerMailboxHolderTest()
394 : main_thread_("MAIN") {
395 main_thread_.Start();
396 main_thread_.message_loop()->task_runner()->PostTask(
397 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain,
398 base::Unretained(this)));
399 Wait(main_thread_);
402 void Wait(const base::Thread& thread) {
403 bool manual_reset = false;
404 bool initially_signaled = false;
405 base::WaitableEvent event(manual_reset, initially_signaled);
406 thread.message_loop()->task_runner()->PostTask(
407 FROM_HERE,
408 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
409 event.Wait();
412 void CreateMainRef() {
413 main_ref_ = TestMailboxHolder::Create(
414 test_data_.mailbox1_,
415 SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass();
418 void ReleaseMainRef() { main_ref_ = nullptr; }
420 void CreateImplRef(scoped_ptr<SingleReleaseCallbackImpl>* impl_ref) {
421 *impl_ref = main_ref_->holder()->GetCallbackForImplThread();
424 void CapturePostTasksAndWait(base::WaitableEvent* begin_capture,
425 base::WaitableEvent* wait_for_capture,
426 base::WaitableEvent* stop_capture) {
427 begin_capture->Wait();
428 BlockingTaskRunner::CapturePostTasks capture(
429 main_thread_task_runner_.get());
430 wait_for_capture->Signal();
431 stop_capture->Wait();
434 protected:
435 void InitializeOnMain() {
436 main_thread_task_runner_ =
437 BlockingTaskRunner::Create(main_thread_.task_runner());
440 scoped_ptr<TestMailboxHolder::MainThreadReference>
441 main_ref_;
442 base::Thread main_thread_;
443 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
446 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) {
447 scoped_refptr<TextureLayer> test_layer =
448 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
449 ASSERT_TRUE(test_layer.get());
451 main_thread_.message_loop()->task_runner()->PostTask(
452 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
453 base::Unretained(this)));
455 Wait(main_thread_);
457 // The texture layer is attached to compositor1, and passes a reference to its
458 // impl tree.
459 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
460 main_thread_.message_loop()->task_runner()->PostTask(
461 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
462 base::Unretained(this), &compositor1));
464 // Then the texture layer is removed and attached to compositor2, and passes a
465 // reference to its impl tree.
466 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
467 main_thread_.message_loop()->task_runner()->PostTask(
468 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
469 base::Unretained(this), &compositor2));
471 Wait(main_thread_);
472 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
474 // The compositors both destroy their impl trees before the main thread layer
475 // is destroyed.
476 compositor1->Run(100, false, main_thread_task_runner_.get());
477 compositor2->Run(200, false, main_thread_task_runner_.get());
479 Wait(main_thread_);
481 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
482 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
484 // The main thread ref is the last one, so the mailbox is released back to the
485 // embedder, with the last sync point provided by the impl trees.
486 EXPECT_CALL(test_data_.mock_callback_,
487 Release(test_data_.mailbox_name1_, 200, false)).Times(1);
489 main_thread_.message_loop()->task_runner()->PostTask(
490 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
491 base::Unretained(this)));
492 Wait(main_thread_);
493 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
496 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) {
497 scoped_refptr<TextureLayer> test_layer =
498 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
499 ASSERT_TRUE(test_layer.get());
501 main_thread_.message_loop()->task_runner()->PostTask(
502 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
503 base::Unretained(this)));
505 Wait(main_thread_);
507 // The texture layer is attached to compositor1, and passes a reference to its
508 // impl tree.
509 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
510 main_thread_.message_loop()->task_runner()->PostTask(
511 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
512 base::Unretained(this), &compositor1));
514 // Then the texture layer is removed and attached to compositor2, and passes a
515 // reference to its impl tree.
516 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
517 main_thread_.message_loop()->task_runner()->PostTask(
518 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
519 base::Unretained(this), &compositor2));
521 Wait(main_thread_);
522 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
524 // One compositor destroys their impl tree.
525 compositor1->Run(100, false, main_thread_task_runner_.get());
527 // Then the main thread reference is destroyed.
528 main_thread_.message_loop()->task_runner()->PostTask(
529 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
530 base::Unretained(this)));
532 Wait(main_thread_);
534 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
535 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
537 // The second impl reference is destroyed last, causing the mailbox to be
538 // released back to the embedder with the last sync point from the impl tree.
539 EXPECT_CALL(test_data_.mock_callback_,
540 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
542 compositor2->Run(200, true, main_thread_task_runner_.get());
543 Wait(main_thread_);
544 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
547 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) {
548 scoped_refptr<TextureLayer> test_layer =
549 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
550 ASSERT_TRUE(test_layer.get());
552 main_thread_.message_loop()->task_runner()->PostTask(
553 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
554 base::Unretained(this)));
556 Wait(main_thread_);
558 // The texture layer is attached to compositor1, and passes a reference to its
559 // impl tree.
560 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
561 main_thread_.message_loop()->task_runner()->PostTask(
562 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
563 base::Unretained(this), &compositor1));
565 // Then the texture layer is removed and attached to compositor2, and passes a
566 // reference to its impl tree.
567 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
568 main_thread_.message_loop()->task_runner()->PostTask(
569 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
570 base::Unretained(this), &compositor2));
572 Wait(main_thread_);
573 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
575 // The main thread reference is destroyed first.
576 main_thread_.message_loop()->task_runner()->PostTask(
577 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
578 base::Unretained(this)));
580 // One compositor destroys their impl tree.
581 compositor2->Run(200, false, main_thread_task_runner_.get());
583 Wait(main_thread_);
585 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
586 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
588 // The second impl reference is destroyed last, causing the mailbox to be
589 // released back to the embedder with the last sync point from the impl tree.
590 EXPECT_CALL(test_data_.mock_callback_,
591 Release(test_data_.mailbox_name1_, 100, true)).Times(1);
593 compositor1->Run(100, true, main_thread_task_runner_.get());
594 Wait(main_thread_);
595 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
598 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) {
599 scoped_refptr<TextureLayer> test_layer =
600 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
601 ASSERT_TRUE(test_layer.get());
603 main_thread_.message_loop()->task_runner()->PostTask(
604 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
605 base::Unretained(this)));
607 Wait(main_thread_);
609 // The texture layer is attached to compositor1, and passes a reference to its
610 // impl tree.
611 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
612 main_thread_.message_loop()->task_runner()->PostTask(
613 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
614 base::Unretained(this), &compositor1));
616 // Then the texture layer is removed and attached to compositor2, and passes a
617 // reference to its impl tree.
618 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
619 main_thread_.message_loop()->task_runner()->PostTask(
620 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
621 base::Unretained(this), &compositor2));
623 Wait(main_thread_);
624 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
626 // The main thread reference is destroyed first.
627 main_thread_.message_loop()->task_runner()->PostTask(
628 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
629 base::Unretained(this)));
631 EXPECT_CALL(test_data_.mock_callback_,
632 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
634 bool manual_reset = false;
635 bool initially_signaled = false;
636 base::WaitableEvent begin_capture(manual_reset, initially_signaled);
637 base::WaitableEvent wait_for_capture(manual_reset, initially_signaled);
638 base::WaitableEvent stop_capture(manual_reset, initially_signaled);
640 // Post a task to start capturing tasks on the main thread. This will block
641 // the main thread until we signal the |stop_capture| event.
642 main_thread_.message_loop()->task_runner()->PostTask(
643 FROM_HERE,
644 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait,
645 base::Unretained(this), &begin_capture, &wait_for_capture,
646 &stop_capture));
648 // Before the main thread capturing starts, one compositor destroys their
649 // impl reference. Since capturing did not start, this gets post-tasked to
650 // the main thread.
651 compositor1->Run(100, false, main_thread_task_runner_.get());
653 // Start capturing on the main thread.
654 begin_capture.Signal();
655 wait_for_capture.Wait();
657 // Meanwhile, the second compositor released its impl reference, but this task
658 // gets shortcutted directly to the main thread. This means the reference is
659 // released before compositor1, whose reference will be released later when
660 // the post-task is serviced. But since it was destroyed _on the impl thread_
661 // last, its sync point values should be used.
662 compositor2->Run(200, true, main_thread_task_runner_.get());
664 stop_capture.Signal();
665 Wait(main_thread_);
667 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
670 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest {
671 public:
672 TextureLayerImplWithMailboxThreadedCallback()
673 : callback_count_(0),
674 commit_count_(0) {}
676 // Make sure callback is received on main and doesn't block the impl thread.
677 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
678 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
679 EXPECT_FALSE(lost_resource);
680 ++callback_count_;
683 void SetMailbox(char mailbox_char) {
684 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
685 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
686 base::Bind(
687 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback,
688 base::Unretained(this)));
689 layer_->SetTextureMailbox(
690 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
691 callback.Pass());
694 void BeginTest() override {
695 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
697 gfx::Size bounds(100, 100);
698 root_ = Layer::Create(layer_settings());
699 root_->SetBounds(bounds);
701 layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr);
702 layer_->SetIsDrawable(true);
703 layer_->SetBounds(bounds);
705 root_->AddChild(layer_);
706 layer_tree_host()->SetRootLayer(root_);
707 layer_tree_host()->SetViewportSize(bounds);
708 SetMailbox('1');
709 EXPECT_EQ(0, callback_count_);
711 // Case #1: change mailbox before the commit. The old mailbox should be
712 // released immediately.
713 SetMailbox('2');
714 EXPECT_EQ(1, callback_count_);
715 PostSetNeedsCommitToMainThread();
718 void DidCommit() override {
719 ++commit_count_;
720 switch (commit_count_) {
721 case 1:
722 // Case #2: change mailbox after the commit (and draw), where the
723 // layer draws. The old mailbox should be released during the next
724 // commit.
725 SetMailbox('3');
726 EXPECT_EQ(1, callback_count_);
727 break;
728 case 2:
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());
733 SetMailbox('4');
734 break;
735 case 3:
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(), nullptr);
740 break;
741 case 4:
742 // With impl painting, the texture mailbox will still be on the impl
743 // thread when the commit finishes, because the layer is not drawble
744 // when it has no texture mailbox, and thus does not block the commit
745 // on activation. So, we wait for activation.
746 // TODO(danakj): fix this. crbug.com/277953
747 layer_tree_host()->SetNeedsCommit();
748 break;
749 case 5:
750 EXPECT_EQ(4, callback_count_);
751 // Restore a mailbox for the next step.
752 SetMailbox('5');
753 break;
754 case 6:
755 // Case #5: remove layer from tree. Callback should *not* be called, the
756 // mailbox is returned to the main thread.
757 EXPECT_EQ(4, callback_count_);
758 layer_->RemoveFromParent();
759 break;
760 case 7:
761 // With impl painting, the texture mailbox will still be on the impl
762 // thread when the commit finishes, because the layer is not around to
763 // block the commit on activation anymore. So, we wait for activation.
764 // TODO(danakj): fix this. crbug.com/277953
765 layer_tree_host()->SetNeedsCommit();
766 break;
767 case 8:
768 EXPECT_EQ(4, callback_count_);
769 // Resetting the mailbox will call the callback now.
770 layer_->SetTextureMailbox(TextureMailbox(), nullptr);
771 EXPECT_EQ(5, callback_count_);
772 EndTest();
773 break;
774 default:
775 NOTREACHED();
776 break;
780 void AfterTest() override {}
782 private:
783 base::ThreadChecker main_thread_;
784 int callback_count_;
785 int commit_count_;
786 scoped_refptr<Layer> root_;
787 scoped_refptr<TextureLayer> layer_;
790 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
791 TextureLayerImplWithMailboxThreadedCallback);
794 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
795 protected:
796 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
798 static void ReleaseCallback(uint32 sync_point, bool lost_resource) {}
800 void SetMailbox(char mailbox_char) {
801 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
802 base::Bind(
803 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
804 layer_->SetTextureMailbox(
805 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
806 callback.Pass());
809 void BeginTest() override {
810 gfx::Size bounds(100, 100);
811 root_ = Layer::Create(layer_settings());
812 root_->SetBounds(bounds);
814 layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr);
815 layer_->SetIsDrawable(true);
816 layer_->SetBounds(bounds);
818 root_->AddChild(layer_);
819 layer_tree_host()->SetRootLayer(root_);
820 layer_tree_host()->SetViewportSize(bounds);
821 SetMailbox('1');
823 PostSetNeedsCommitToMainThread();
826 void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
827 base::AutoLock lock(activate_count_lock_);
828 ++activate_count_;
831 void DidCommit() override {
832 // The first frame doesn't cause anything to be returned so it does not
833 // need to wait for activation.
834 if (layer_tree_host()->source_frame_number() > 1) {
835 base::AutoLock lock(activate_count_lock_);
836 // The activate happened before commit is done on the main side.
837 EXPECT_EQ(activate_count_, layer_tree_host()->source_frame_number());
840 switch (layer_tree_host()->source_frame_number()) {
841 case 1:
842 // The first mailbox has been activated. Set a new mailbox, and
843 // expect the next commit to finish *after* it is activated.
844 SetMailbox('2');
845 break;
846 case 2:
847 // The second mailbox has been activated. Remove the layer from
848 // the tree to cause another commit/activation. The commit should
849 // finish *after* the layer is removed from the active tree.
850 layer_->RemoveFromParent();
851 break;
852 case 3:
853 EndTest();
854 break;
858 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
859 // The activate didn't happen before commit is done on the impl side (but it
860 // should happen before the main thread is done).
861 EXPECT_EQ(activate_count_, host_impl->sync_tree()->source_frame_number());
864 void AfterTest() override {}
866 base::Lock activate_count_lock_;
867 int activate_count_;
868 scoped_refptr<Layer> root_;
869 scoped_refptr<TextureLayer> layer_;
872 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
873 TextureLayerMailboxIsActivatedDuringCommit);
875 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
876 protected:
877 TextureLayerImplWithMailboxTest()
878 : fake_client_(
879 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
881 void SetUp() override {
882 TextureLayerTest::SetUp();
883 layer_tree_host_ =
884 MockLayerTreeHost::Create(&fake_client_, &task_graph_runner_);
885 EXPECT_TRUE(host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()));
888 bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
889 bool will_draw = layer->WillDraw(
890 mode, host_impl_.active_tree()->resource_provider());
891 if (will_draw)
892 layer->DidDraw(host_impl_.active_tree()->resource_provider());
893 return will_draw;
896 FakeLayerTreeHostClient fake_client_;
899 // Test conditions for results of TextureLayerImpl::WillDraw under
900 // different configurations of different mailbox, texture_id, and draw_mode.
901 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
902 EXPECT_CALL(
903 test_data_.mock_callback_,
904 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
905 .Times(AnyNumber());
906 EXPECT_CALL(test_data_.mock_callback_,
907 ReleaseImpl2(test_data_.shared_bitmap_.get(), 0, false, _))
908 .Times(AnyNumber());
909 // Hardware mode.
911 scoped_ptr<TextureLayerImpl> impl_layer =
912 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
913 impl_layer->SetTextureMailbox(
914 test_data_.mailbox1_,
915 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
916 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
920 scoped_ptr<TextureLayerImpl> impl_layer =
921 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
922 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
923 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
927 // Software resource.
928 scoped_ptr<TextureLayerImpl> impl_layer =
929 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
930 impl_layer->SetTextureMailbox(
931 test_data_.mailbox3_,
932 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
933 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
936 // Software mode.
938 scoped_ptr<TextureLayerImpl> impl_layer =
939 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
940 impl_layer->SetTextureMailbox(
941 test_data_.mailbox1_,
942 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
943 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
947 scoped_ptr<TextureLayerImpl> impl_layer =
948 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
949 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
950 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
954 // Software resource.
955 scoped_ptr<TextureLayerImpl> impl_layer =
956 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
957 impl_layer->SetTextureMailbox(
958 test_data_.mailbox3_,
959 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
960 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
963 // Resourceless software mode.
965 scoped_ptr<TextureLayerImpl> impl_layer =
966 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
967 impl_layer->SetTextureMailbox(
968 test_data_.mailbox1_,
969 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
970 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
974 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
975 host_impl_.CreatePendingTree();
976 scoped_ptr<TextureLayerImpl> pending_layer;
977 pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1);
978 ASSERT_TRUE(pending_layer);
980 scoped_ptr<LayerImpl> active_layer(
981 pending_layer->CreateLayerImpl(host_impl_.active_tree()));
982 ASSERT_TRUE(active_layer);
984 pending_layer->SetTextureMailbox(
985 test_data_.mailbox1_,
986 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
988 // Test multiple commits without an activation.
989 EXPECT_CALL(
990 test_data_.mock_callback_,
991 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
992 .Times(1);
993 pending_layer->SetTextureMailbox(
994 test_data_.mailbox2_,
995 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox2_impl_));
996 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
998 // Test callback after activation.
999 pending_layer->PushPropertiesTo(active_layer.get());
1000 active_layer->DidBecomeActive();
1002 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1003 pending_layer->SetTextureMailbox(
1004 test_data_.mailbox1_,
1005 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1006 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1008 EXPECT_CALL(test_data_.mock_callback_,
1009 ReleaseImpl(test_data_.mailbox_name2_, _, false, _)).Times(1);
1010 pending_layer->PushPropertiesTo(active_layer.get());
1011 active_layer->DidBecomeActive();
1012 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1014 // Test resetting the mailbox.
1015 EXPECT_CALL(test_data_.mock_callback_,
1016 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1017 pending_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1018 pending_layer->PushPropertiesTo(active_layer.get());
1019 active_layer->DidBecomeActive();
1020 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1022 // Test destructor.
1023 EXPECT_CALL(
1024 test_data_.mock_callback_,
1025 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
1026 .Times(1);
1027 pending_layer->SetTextureMailbox(
1028 test_data_.mailbox1_,
1029 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1032 TEST_F(TextureLayerImplWithMailboxTest,
1033 TestDestructorCallbackOnCreatedResource) {
1034 scoped_ptr<TextureLayerImpl> impl_layer;
1035 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1036 ASSERT_TRUE(impl_layer);
1038 EXPECT_CALL(test_data_.mock_callback_,
1039 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1040 impl_layer->SetTextureMailbox(
1041 test_data_.mailbox1_,
1042 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1043 impl_layer->DidBecomeActive();
1044 EXPECT_TRUE(impl_layer->WillDraw(
1045 DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1046 impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1047 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1050 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1051 ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1052 ResourceId id = provider->CreateResourceFromTextureMailbox(
1053 test_data_.mailbox1_,
1054 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1055 provider->AllocateForTesting(id);
1057 // Transfer some resources to the parent.
1058 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1059 resource_ids_to_transfer.push_back(id);
1060 TransferableResourceArray list;
1061 provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1062 EXPECT_TRUE(provider->InUseByConsumer(id));
1063 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1064 provider->DeleteResource(id);
1065 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1066 EXPECT_CALL(test_data_.mock_callback_,
1067 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1068 ReturnedResourceArray returned;
1069 TransferableResource::ReturnResources(list, &returned);
1070 provider->ReceiveReturnsFromParent(returned);
1073 // Checks that TextureLayer::Update does not cause an extra commit when setting
1074 // the texture mailbox.
1075 class TextureLayerNoExtraCommitForMailboxTest
1076 : public LayerTreeTest,
1077 public TextureLayerClient {
1078 public:
1079 // TextureLayerClient implementation.
1080 bool PrepareTextureMailbox(
1081 TextureMailbox* texture_mailbox,
1082 scoped_ptr<SingleReleaseCallback>* release_callback,
1083 bool use_shared_memory) override {
1084 if (layer_tree_host()->source_frame_number() == 1) {
1085 // Once this has been committed, the mailbox will be released.
1086 *texture_mailbox = TextureMailbox();
1087 return true;
1090 *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1091 *release_callback = SingleReleaseCallback::Create(
1092 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1093 base::Unretained(this)));
1094 return true;
1097 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1098 // Source frame number during callback is the same as the source frame
1099 // on which it was released.
1100 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1101 EndTest();
1104 void SetupTree() override {
1105 scoped_refptr<Layer> root = Layer::Create(layer_settings());
1106 root->SetBounds(gfx::Size(10, 10));
1107 root->SetIsDrawable(true);
1109 texture_layer_ = TextureLayer::CreateForMailbox(layer_settings(), this);
1110 texture_layer_->SetBounds(gfx::Size(10, 10));
1111 texture_layer_->SetIsDrawable(true);
1112 root->AddChild(texture_layer_);
1114 layer_tree_host()->SetRootLayer(root);
1115 LayerTreeTest::SetupTree();
1118 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1120 void DidCommitAndDrawFrame() override {
1121 switch (layer_tree_host()->source_frame_number()) {
1122 case 1:
1123 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1124 // Invalidate the texture layer to clear the mailbox before
1125 // ending the test.
1126 texture_layer_->SetNeedsDisplay();
1127 break;
1128 case 2:
1129 break;
1130 default:
1131 NOTREACHED();
1132 break;
1136 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1137 ASSERT_TRUE(result);
1138 DelegatedFrameData* delegated_frame_data =
1139 output_surface()->last_sent_frame().delegated_frame_data.get();
1140 if (!delegated_frame_data)
1141 return;
1143 // Return all resources immediately.
1144 TransferableResourceArray resources_to_return =
1145 output_surface()->resources_held_by_parent();
1147 CompositorFrameAck ack;
1148 for (size_t i = 0; i < resources_to_return.size(); ++i)
1149 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1150 host_impl->ReclaimResources(&ack);
1153 void AfterTest() override {}
1155 private:
1156 scoped_refptr<TextureLayer> texture_layer_;
1159 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1161 // Checks that changing a mailbox in the client for a TextureLayer that's
1162 // invisible correctly works and uses the new mailbox as soon as the layer
1163 // becomes visible (and returns the old one).
1164 class TextureLayerChangeInvisibleMailboxTest
1165 : public LayerTreeTest,
1166 public TextureLayerClient {
1167 public:
1168 TextureLayerChangeInvisibleMailboxTest()
1169 : mailbox_changed_(true),
1170 mailbox_returned_(0),
1171 prepare_called_(0),
1172 commit_count_(0) {
1173 mailbox_ = MakeMailbox('1');
1176 // TextureLayerClient implementation.
1177 bool PrepareTextureMailbox(
1178 TextureMailbox* mailbox,
1179 scoped_ptr<SingleReleaseCallback>* release_callback,
1180 bool use_shared_memory) override {
1181 ++prepare_called_;
1182 if (!mailbox_changed_)
1183 return false;
1184 *mailbox = mailbox_;
1185 *release_callback = SingleReleaseCallback::Create(
1186 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1187 base::Unretained(this)));
1188 return true;
1191 TextureMailbox MakeMailbox(char name) {
1192 return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0);
1195 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1196 ++mailbox_returned_;
1199 void SetupTree() override {
1200 scoped_refptr<Layer> root = Layer::Create(layer_settings());
1201 root->SetBounds(gfx::Size(10, 10));
1202 root->SetIsDrawable(true);
1204 solid_layer_ = SolidColorLayer::Create(layer_settings());
1205 solid_layer_->SetBounds(gfx::Size(10, 10));
1206 solid_layer_->SetIsDrawable(true);
1207 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1208 root->AddChild(solid_layer_);
1210 parent_layer_ = Layer::Create(layer_settings());
1211 parent_layer_->SetBounds(gfx::Size(10, 10));
1212 parent_layer_->SetIsDrawable(true);
1213 root->AddChild(parent_layer_);
1215 texture_layer_ = TextureLayer::CreateForMailbox(layer_settings(), this);
1216 texture_layer_->SetBounds(gfx::Size(10, 10));
1217 texture_layer_->SetIsDrawable(true);
1218 parent_layer_->AddChild(texture_layer_);
1220 layer_tree_host()->SetRootLayer(root);
1221 LayerTreeTest::SetupTree();
1224 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1226 void DidCommitAndDrawFrame() override {
1227 ++commit_count_;
1228 switch (commit_count_) {
1229 case 1:
1230 // We should have updated the layer, committing the texture.
1231 EXPECT_EQ(1, prepare_called_);
1232 // Make layer invisible.
1233 parent_layer_->SetOpacity(0.f);
1234 break;
1235 case 2:
1236 // Layer shouldn't have been updated.
1237 EXPECT_EQ(1, prepare_called_);
1238 // Change the texture.
1239 mailbox_ = MakeMailbox('2');
1240 mailbox_changed_ = true;
1241 texture_layer_->SetNeedsDisplay();
1242 // Force a change to make sure we draw a frame.
1243 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1244 break;
1245 case 3:
1246 // Layer shouldn't have been updated.
1247 EXPECT_EQ(1, prepare_called_);
1248 // So the old mailbox isn't returned yet.
1249 EXPECT_EQ(0, mailbox_returned_);
1250 // Make layer visible again.
1251 parent_layer_->SetOpacity(1.f);
1252 break;
1253 case 4:
1254 // Layer should have been updated.
1255 EXPECT_EQ(2, prepare_called_);
1256 // So the old mailbox should have been returned already.
1257 EXPECT_EQ(1, mailbox_returned_);
1258 texture_layer_->ClearClient();
1259 break;
1260 case 5:
1261 EXPECT_EQ(2, mailbox_returned_);
1262 EndTest();
1263 break;
1264 default:
1265 NOTREACHED();
1266 break;
1270 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1271 ASSERT_TRUE(result);
1272 DelegatedFrameData* delegated_frame_data =
1273 output_surface()->last_sent_frame().delegated_frame_data.get();
1274 if (!delegated_frame_data)
1275 return;
1277 // Return all resources immediately.
1278 TransferableResourceArray resources_to_return =
1279 output_surface()->resources_held_by_parent();
1281 CompositorFrameAck ack;
1282 for (size_t i = 0; i < resources_to_return.size(); ++i)
1283 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1284 host_impl->ReclaimResources(&ack);
1287 void AfterTest() override {}
1289 private:
1290 scoped_refptr<SolidColorLayer> solid_layer_;
1291 scoped_refptr<Layer> parent_layer_;
1292 scoped_refptr<TextureLayer> texture_layer_;
1294 // Used on the main thread.
1295 bool mailbox_changed_;
1296 TextureMailbox mailbox_;
1297 int mailbox_returned_;
1298 int prepare_called_;
1299 int commit_count_;
1302 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1304 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1305 // the mailbox back to TextureLayerClient.
1306 class TextureLayerReleaseResourcesBase
1307 : public LayerTreeTest,
1308 public TextureLayerClient {
1309 public:
1310 // TextureLayerClient implementation.
1311 bool PrepareTextureMailbox(
1312 TextureMailbox* mailbox,
1313 scoped_ptr<SingleReleaseCallback>* release_callback,
1314 bool use_shared_memory) override {
1315 *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1316 *release_callback = SingleReleaseCallback::Create(
1317 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1318 base::Unretained(this)));
1319 return true;
1322 void MailboxReleased(unsigned sync_point, bool lost_resource) {
1323 mailbox_released_ = true;
1326 void SetupTree() override {
1327 LayerTreeTest::SetupTree();
1329 scoped_refptr<TextureLayer> texture_layer =
1330 TextureLayer::CreateForMailbox(layer_settings(), this);
1331 texture_layer->SetBounds(gfx::Size(10, 10));
1332 texture_layer->SetIsDrawable(true);
1334 layer_tree_host()->root_layer()->AddChild(texture_layer);
1337 void BeginTest() override {
1338 mailbox_released_ = false;
1339 PostSetNeedsCommitToMainThread();
1342 void DidCommitAndDrawFrame() override { EndTest(); }
1344 void AfterTest() override { EXPECT_TRUE(mailbox_released_); }
1346 private:
1347 bool mailbox_released_;
1350 class TextureLayerReleaseResourcesAfterCommit
1351 : public TextureLayerReleaseResourcesBase {
1352 public:
1353 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
1354 LayerTreeImpl* tree = nullptr;
1355 tree = host_impl->sync_tree();
1356 tree->root_layer()->children()[0]->ReleaseResources();
1360 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1362 class TextureLayerReleaseResourcesAfterActivate
1363 : public TextureLayerReleaseResourcesBase {
1364 public:
1365 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
1366 host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
1370 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
1372 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
1373 public:
1374 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1375 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1376 EXPECT_FALSE(lost_resource);
1377 ++callback_count_;
1378 EndTest();
1381 void SetMailbox(char mailbox_char) {
1382 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1383 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1384 base::Bind(
1385 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
1386 base::Unretained(this)));
1387 layer_->SetTextureMailbox(
1388 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1389 callback.Pass());
1392 void SetupTree() override {
1393 gfx::Size bounds(100, 100);
1394 root_ = Layer::Create(layer_settings());
1395 root_->SetBounds(bounds);
1397 layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr);
1398 layer_->SetIsDrawable(true);
1399 layer_->SetBounds(bounds);
1401 root_->AddChild(layer_);
1402 layer_tree_host()->SetRootLayer(root_);
1403 layer_tree_host()->SetViewportSize(bounds);
1406 void BeginTest() override {
1407 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1409 callback_count_ = 0;
1411 // Set the mailbox on the main thread.
1412 SetMailbox('1');
1413 EXPECT_EQ(0, callback_count_);
1415 PostSetNeedsCommitToMainThread();
1418 void DidCommitAndDrawFrame() override {
1419 switch (layer_tree_host()->source_frame_number()) {
1420 case 1:
1421 // Delete the TextureLayer on the main thread while the mailbox is in
1422 // the impl tree.
1423 layer_->RemoveFromParent();
1424 layer_ = nullptr;
1425 break;
1429 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1431 private:
1432 base::ThreadChecker main_thread_;
1433 int callback_count_;
1434 scoped_refptr<Layer> root_;
1435 scoped_refptr<TextureLayer> layer_;
1438 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1439 TextureLayerWithMailboxMainThreadDeleted);
1441 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
1442 public:
1443 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1444 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1445 EXPECT_FALSE(lost_resource);
1446 ++callback_count_;
1447 EndTest();
1450 void SetMailbox(char mailbox_char) {
1451 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1452 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1453 base::Bind(
1454 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
1455 base::Unretained(this)));
1456 layer_->SetTextureMailbox(
1457 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1458 callback.Pass());
1461 void SetupTree() override {
1462 gfx::Size bounds(100, 100);
1463 root_ = Layer::Create(layer_settings());
1464 root_->SetBounds(bounds);
1466 layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr);
1467 layer_->SetIsDrawable(true);
1468 layer_->SetBounds(bounds);
1470 root_->AddChild(layer_);
1471 layer_tree_host()->SetRootLayer(root_);
1472 layer_tree_host()->SetViewportSize(bounds);
1475 void BeginTest() override {
1476 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1478 callback_count_ = 0;
1480 // Set the mailbox on the main thread.
1481 SetMailbox('1');
1482 EXPECT_EQ(0, callback_count_);
1484 PostSetNeedsCommitToMainThread();
1487 void DidCommitAndDrawFrame() override {
1488 switch (layer_tree_host()->source_frame_number()) {
1489 case 1:
1490 // Remove the TextureLayer on the main thread while the mailbox is in
1491 // the impl tree, but don't delete the TextureLayer until after the impl
1492 // tree side is deleted.
1493 layer_->RemoveFromParent();
1494 break;
1495 case 2:
1496 layer_ = nullptr;
1497 break;
1501 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1503 private:
1504 base::ThreadChecker main_thread_;
1505 int callback_count_;
1506 scoped_refptr<Layer> root_;
1507 scoped_refptr<TextureLayer> layer_;
1510 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1511 TextureLayerWithMailboxImplThreadDeleted);
1513 } // namespace
1514 } // namespace cc