[Smart Lock] Remove the unused easyUnlockPrivate.getUserImage function.
[chromium-blink-merge.git] / cc / layers / texture_layer_unittest.cc
blob33291be6ec59ad89dcba78f394cab326bee27a47
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/synchronization/waitable_event.h"
13 #include "base/threading/thread.h"
14 #include "base/time/time.h"
15 #include "cc/layers/solid_color_layer.h"
16 #include "cc/layers/texture_layer_client.h"
17 #include "cc/layers/texture_layer_impl.h"
18 #include "cc/output/compositor_frame_ack.h"
19 #include "cc/output/context_provider.h"
20 #include "cc/resources/returned_resource.h"
21 #include "cc/test/fake_impl_proxy.h"
22 #include "cc/test/fake_layer_tree_host_client.h"
23 #include "cc/test/fake_layer_tree_host_impl.h"
24 #include "cc/test/fake_output_surface.h"
25 #include "cc/test/layer_test_common.h"
26 #include "cc/test/layer_tree_test.h"
27 #include "cc/test/test_web_graphics_context_3d.h"
28 #include "cc/trees/blocking_task_runner.h"
29 #include "cc/trees/layer_tree_host.h"
30 #include "cc/trees/layer_tree_impl.h"
31 #include "cc/trees/single_thread_proxy.h"
32 #include "gpu/GLES2/gl2extchromium.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "testing/gtest/include/gtest/gtest.h"
36 using ::testing::Mock;
37 using ::testing::_;
38 using ::testing::AtLeast;
39 using ::testing::AnyNumber;
40 using ::testing::InvokeWithoutArgs;
42 namespace cc {
43 namespace {
45 gpu::Mailbox MailboxFromChar(char value) {
46 gpu::Mailbox mailbox;
47 memset(mailbox.name, value, sizeof(mailbox.name));
48 return mailbox;
51 class MockLayerTreeHost : public LayerTreeHost {
52 public:
53 explicit MockLayerTreeHost(FakeLayerTreeHostClient* client)
54 : LayerTreeHost(client, nullptr, nullptr, LayerTreeSettings()) {
55 InitializeSingleThreaded(client,
56 base::MessageLoopProxy::current(),
57 nullptr);
60 MOCK_METHOD0(SetNeedsCommit, void());
61 MOCK_METHOD0(SetNeedsUpdateLayers, void());
62 MOCK_METHOD0(StartRateLimiter, void());
63 MOCK_METHOD0(StopRateLimiter, void());
66 class FakeTextureLayerClient : public TextureLayerClient {
67 public:
68 FakeTextureLayerClient() : mailbox_changed_(true) {}
70 bool PrepareTextureMailbox(
71 TextureMailbox* mailbox,
72 scoped_ptr<SingleReleaseCallback>* release_callback,
73 bool use_shared_memory) override {
74 if (!mailbox_changed_)
75 return false;
77 *mailbox = mailbox_;
78 *release_callback = release_callback_.Pass();
79 mailbox_changed_ = false;
80 return true;
83 void set_mailbox(const TextureMailbox& mailbox,
84 scoped_ptr<SingleReleaseCallback> release_callback) {
85 mailbox_ = mailbox;
86 release_callback_ = release_callback.Pass();
87 mailbox_changed_ = true;
90 private:
91 TextureMailbox mailbox_;
92 scoped_ptr<SingleReleaseCallback> release_callback_;
93 bool mailbox_changed_;
94 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient);
97 class MockMailboxCallback {
98 public:
99 MOCK_METHOD3(Release,
100 void(const gpu::Mailbox& mailbox,
101 uint32 sync_point,
102 bool lost_resource));
103 MOCK_METHOD3(Release2,
104 void(SharedBitmap* shared_bitmap,
105 uint32 sync_point,
106 bool lost_resource));
107 MOCK_METHOD4(ReleaseImpl,
108 void(const gpu::Mailbox& mailbox,
109 uint32 sync_point,
110 bool lost_resource,
111 BlockingTaskRunner* main_thread_task_runner));
112 MOCK_METHOD4(ReleaseImpl2,
113 void(SharedBitmap* shared_bitmap,
114 uint32 sync_point,
115 bool lost_resource,
116 BlockingTaskRunner* main_thread_task_runner));
119 struct CommonMailboxObjects {
120 explicit CommonMailboxObjects(SharedBitmapManager* manager)
121 : mailbox_name1_(MailboxFromChar('1')),
122 mailbox_name2_(MailboxFromChar('2')),
123 sync_point1_(1),
124 sync_point2_(2) {
125 release_mailbox1_ = base::Bind(&MockMailboxCallback::Release,
126 base::Unretained(&mock_callback_),
127 mailbox_name1_);
128 release_mailbox2_ = base::Bind(&MockMailboxCallback::Release,
129 base::Unretained(&mock_callback_),
130 mailbox_name2_);
131 release_mailbox1_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl,
132 base::Unretained(&mock_callback_),
133 mailbox_name1_);
134 release_mailbox2_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl,
135 base::Unretained(&mock_callback_),
136 mailbox_name2_);
137 const uint32 arbitrary_target1 = GL_TEXTURE_2D;
138 const uint32 arbitrary_target2 = GL_TEXTURE_EXTERNAL_OES;
139 mailbox1_ = TextureMailbox(mailbox_name1_, arbitrary_target1, sync_point1_);
140 mailbox2_ = TextureMailbox(mailbox_name2_, arbitrary_target2, sync_point2_);
141 gfx::Size size(128, 128);
142 shared_bitmap_ = manager->AllocateSharedBitmap(size);
143 DCHECK(shared_bitmap_);
144 release_mailbox3_ =
145 base::Bind(&MockMailboxCallback::Release2,
146 base::Unretained(&mock_callback_), shared_bitmap_.get());
147 release_mailbox3_impl_ =
148 base::Bind(&MockMailboxCallback::ReleaseImpl2,
149 base::Unretained(&mock_callback_), shared_bitmap_.get());
150 mailbox3_ = TextureMailbox(shared_bitmap_.get(), size);
153 gpu::Mailbox mailbox_name1_;
154 gpu::Mailbox mailbox_name2_;
155 MockMailboxCallback mock_callback_;
156 ReleaseCallback release_mailbox1_;
157 ReleaseCallback release_mailbox2_;
158 ReleaseCallback release_mailbox3_;
159 ReleaseCallbackImpl release_mailbox1_impl_;
160 ReleaseCallbackImpl release_mailbox2_impl_;
161 ReleaseCallbackImpl release_mailbox3_impl_;
162 TextureMailbox mailbox1_;
163 TextureMailbox mailbox2_;
164 TextureMailbox mailbox3_;
165 uint32 sync_point1_;
166 uint32 sync_point2_;
167 scoped_ptr<SharedBitmap> shared_bitmap_;
170 class TextureLayerTest : public testing::Test {
171 public:
172 TextureLayerTest()
173 : fake_client_(
174 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
175 host_impl_(&proxy_, &shared_bitmap_manager_),
176 test_data_(&shared_bitmap_manager_) {}
178 protected:
179 void SetUp() override {
180 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
181 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
182 layer_tree_host_->SetViewportSize(gfx::Size(10, 10));
183 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
186 void TearDown() override {
187 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
188 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
190 layer_tree_host_->SetRootLayer(nullptr);
191 layer_tree_host_ = nullptr;
194 scoped_ptr<MockLayerTreeHost> layer_tree_host_;
195 FakeImplProxy proxy_;
196 FakeLayerTreeHostClient fake_client_;
197 TestSharedBitmapManager shared_bitmap_manager_;
198 FakeLayerTreeHostImpl host_impl_;
199 CommonMailboxObjects test_data_;
202 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) {
203 scoped_refptr<TextureLayer> test_layer =
204 TextureLayer::CreateForMailbox(nullptr);
205 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer));
207 // Test properties that should call SetNeedsCommit. All properties need to
208 // be set to new values in order for SetNeedsCommit to be called.
209 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false));
210 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetNearestNeighbor(true));
211 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV(
212 gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f)));
213 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity(
214 0.5f, 0.5f, 0.5f, 0.5f));
215 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false));
216 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true));
219 TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) {
220 const gfx::Size layer_bounds(100, 100);
221 const gfx::Rect layer_rect(layer_bounds);
222 const Region layer_region(layer_rect);
224 scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(nullptr);
225 layer->SetBounds(layer_bounds);
226 layer->draw_properties().visible_content_rect = layer_rect;
227 layer->SetBlendBackgroundColor(true);
229 // Verify initial conditions.
230 EXPECT_FALSE(layer->contents_opaque());
231 EXPECT_EQ(0u, layer->background_color());
232 EXPECT_EQ(Region().ToString(),
233 layer->VisibleContentOpaqueRegion().ToString());
235 // Opaque background.
236 layer->SetBackgroundColor(SK_ColorWHITE);
237 EXPECT_EQ(layer_region.ToString(),
238 layer->VisibleContentOpaqueRegion().ToString());
240 // Transparent background.
241 layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
242 EXPECT_EQ(Region().ToString(),
243 layer->VisibleContentOpaqueRegion().ToString());
246 TEST_F(TextureLayerTest, RateLimiter) {
247 FakeTextureLayerClient client;
248 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(
249 &client);
250 test_layer->SetIsDrawable(true);
251 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
252 layer_tree_host_->SetRootLayer(test_layer);
254 // Don't rate limit until we invalidate.
255 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
256 test_layer->SetRateLimitContext(true);
257 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
259 // Do rate limit after we invalidate.
260 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
261 test_layer->SetNeedsDisplay();
262 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
264 // Stop rate limiter when we don't want it any more.
265 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
266 test_layer->SetRateLimitContext(false);
267 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
269 // Or we clear the client.
270 test_layer->SetRateLimitContext(true);
271 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
272 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
273 test_layer->ClearClient();
274 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
276 // Reset to a layer with a client, that started the rate limiter.
277 test_layer = TextureLayer::CreateForMailbox(
278 &client);
279 test_layer->SetIsDrawable(true);
280 test_layer->SetRateLimitContext(true);
281 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
282 layer_tree_host_->SetRootLayer(test_layer);
283 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
284 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
285 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
286 test_layer->SetNeedsDisplay();
287 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
289 // Stop rate limiter when we're removed from the tree.
290 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
291 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
292 layer_tree_host_->SetRootLayer(nullptr);
293 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
296 class TestMailboxHolder : public TextureLayer::TextureMailboxHolder {
297 public:
298 using TextureLayer::TextureMailboxHolder::Create;
300 protected:
301 ~TestMailboxHolder() override {}
304 class TextureLayerWithMailboxTest : public TextureLayerTest {
305 protected:
306 void TearDown() override {
307 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
308 EXPECT_CALL(test_data_.mock_callback_,
309 Release(test_data_.mailbox_name1_,
310 test_data_.sync_point1_,
311 false)).Times(1);
312 TextureLayerTest::TearDown();
316 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
317 scoped_refptr<TextureLayer> test_layer =
318 TextureLayer::CreateForMailbox(nullptr);
319 ASSERT_TRUE(test_layer.get());
321 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
322 layer_tree_host_->SetRootLayer(test_layer);
323 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
325 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
326 test_layer->SetTextureMailbox(
327 test_data_.mailbox1_,
328 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
329 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
331 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
332 EXPECT_CALL(test_data_.mock_callback_,
333 Release(test_data_.mailbox_name1_,
334 test_data_.sync_point1_,
335 false))
336 .Times(1);
337 test_layer->SetTextureMailbox(
338 test_data_.mailbox2_,
339 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
340 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
341 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
343 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
344 EXPECT_CALL(test_data_.mock_callback_,
345 Release(test_data_.mailbox_name2_,
346 test_data_.sync_point2_,
347 false))
348 .Times(1);
349 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
350 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
351 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
353 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
354 test_layer->SetTextureMailbox(
355 test_data_.mailbox3_,
356 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
357 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
358 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
360 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
361 EXPECT_CALL(test_data_.mock_callback_,
362 Release2(test_data_.shared_bitmap_.get(), 0, false)).Times(1);
363 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
364 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
365 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
367 // Test destructor.
368 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
369 test_layer->SetTextureMailbox(
370 test_data_.mailbox1_,
371 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
374 TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) {
375 scoped_refptr<TextureLayer> test_layer =
376 TextureLayer::CreateForMailbox(nullptr);
377 ASSERT_TRUE(test_layer.get());
379 // These use the same gpu::Mailbox, but different sync points.
380 TextureMailbox mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D, 1);
381 TextureMailbox mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D, 2);
383 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
384 layer_tree_host_->SetRootLayer(test_layer);
385 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
387 // Set the mailbox the first time. It should cause a commit.
388 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
389 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox1);
390 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
392 // Set the mailbox again with a new sync point, as the backing texture has
393 // been updated. It should cause a new commit.
394 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
395 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox2);
396 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
399 class TextureLayerMailboxHolderTest : public TextureLayerTest {
400 public:
401 TextureLayerMailboxHolderTest()
402 : main_thread_("MAIN") {
403 main_thread_.Start();
404 main_thread_.message_loop()->PostTask(
405 FROM_HERE,
406 base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain,
407 base::Unretained(this)));
408 Wait(main_thread_);
411 void Wait(const base::Thread& thread) {
412 bool manual_reset = false;
413 bool initially_signaled = false;
414 base::WaitableEvent event(manual_reset, initially_signaled);
415 thread.message_loop()->PostTask(
416 FROM_HERE,
417 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
418 event.Wait();
421 void CreateMainRef() {
422 main_ref_ = TestMailboxHolder::Create(
423 test_data_.mailbox1_,
424 SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass();
427 void ReleaseMainRef() { main_ref_ = nullptr; }
429 void CreateImplRef(scoped_ptr<SingleReleaseCallbackImpl>* impl_ref) {
430 *impl_ref = main_ref_->holder()->GetCallbackForImplThread();
433 void CapturePostTasksAndWait(base::WaitableEvent* begin_capture,
434 base::WaitableEvent* wait_for_capture,
435 base::WaitableEvent* stop_capture) {
436 begin_capture->Wait();
437 BlockingTaskRunner::CapturePostTasks capture(
438 main_thread_task_runner_.get());
439 wait_for_capture->Signal();
440 stop_capture->Wait();
443 protected:
444 void InitializeOnMain() {
445 main_thread_task_runner_ =
446 BlockingTaskRunner::Create(main_thread_.message_loop_proxy());
449 scoped_ptr<TestMailboxHolder::MainThreadReference>
450 main_ref_;
451 base::Thread main_thread_;
452 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
455 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) {
456 scoped_refptr<TextureLayer> test_layer =
457 TextureLayer::CreateForMailbox(nullptr);
458 ASSERT_TRUE(test_layer.get());
460 main_thread_.message_loop()->PostTask(
461 FROM_HERE,
462 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
463 base::Unretained(this)));
465 Wait(main_thread_);
467 // The texture layer is attached to compositor1, and passes a reference to its
468 // impl tree.
469 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
470 main_thread_.message_loop()->PostTask(
471 FROM_HERE,
472 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
473 base::Unretained(this),
474 &compositor1));
476 // Then the texture layer is removed and attached to compositor2, and passes a
477 // reference to its impl tree.
478 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
479 main_thread_.message_loop()->PostTask(
480 FROM_HERE,
481 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
482 base::Unretained(this),
483 &compositor2));
485 Wait(main_thread_);
486 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
488 // The compositors both destroy their impl trees before the main thread layer
489 // is destroyed.
490 compositor1->Run(100, false, main_thread_task_runner_.get());
491 compositor2->Run(200, false, main_thread_task_runner_.get());
493 Wait(main_thread_);
495 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
496 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
498 // The main thread ref is the last one, so the mailbox is released back to the
499 // embedder, with the last sync point provided by the impl trees.
500 EXPECT_CALL(test_data_.mock_callback_,
501 Release(test_data_.mailbox_name1_, 200, false)).Times(1);
503 main_thread_.message_loop()->PostTask(
504 FROM_HERE,
505 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
506 base::Unretained(this)));
507 Wait(main_thread_);
508 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
511 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) {
512 scoped_refptr<TextureLayer> test_layer =
513 TextureLayer::CreateForMailbox(nullptr);
514 ASSERT_TRUE(test_layer.get());
516 main_thread_.message_loop()->PostTask(
517 FROM_HERE,
518 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
519 base::Unretained(this)));
521 Wait(main_thread_);
523 // The texture layer is attached to compositor1, and passes a reference to its
524 // impl tree.
525 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
526 main_thread_.message_loop()->PostTask(
527 FROM_HERE,
528 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
529 base::Unretained(this),
530 &compositor1));
532 // Then the texture layer is removed and attached to compositor2, and passes a
533 // reference to its impl tree.
534 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
535 main_thread_.message_loop()->PostTask(
536 FROM_HERE,
537 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
538 base::Unretained(this),
539 &compositor2));
541 Wait(main_thread_);
542 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
544 // One compositor destroys their impl tree.
545 compositor1->Run(100, false, main_thread_task_runner_.get());
547 // Then the main thread reference is destroyed.
548 main_thread_.message_loop()->PostTask(
549 FROM_HERE,
550 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
551 base::Unretained(this)));
553 Wait(main_thread_);
555 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
556 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
558 // The second impl reference is destroyed last, causing the mailbox to be
559 // released back to the embedder with the last sync point from the impl tree.
560 EXPECT_CALL(test_data_.mock_callback_,
561 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
563 compositor2->Run(200, true, main_thread_task_runner_.get());
564 Wait(main_thread_);
565 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
568 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) {
569 scoped_refptr<TextureLayer> test_layer =
570 TextureLayer::CreateForMailbox(nullptr);
571 ASSERT_TRUE(test_layer.get());
573 main_thread_.message_loop()->PostTask(
574 FROM_HERE,
575 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
576 base::Unretained(this)));
578 Wait(main_thread_);
580 // The texture layer is attached to compositor1, and passes a reference to its
581 // impl tree.
582 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
583 main_thread_.message_loop()->PostTask(
584 FROM_HERE,
585 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
586 base::Unretained(this),
587 &compositor1));
589 // Then the texture layer is removed and attached to compositor2, and passes a
590 // reference to its impl tree.
591 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
592 main_thread_.message_loop()->PostTask(
593 FROM_HERE,
594 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
595 base::Unretained(this),
596 &compositor2));
598 Wait(main_thread_);
599 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
601 // The main thread reference is destroyed first.
602 main_thread_.message_loop()->PostTask(
603 FROM_HERE,
604 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
605 base::Unretained(this)));
607 // One compositor destroys their impl tree.
608 compositor2->Run(200, false, main_thread_task_runner_.get());
610 Wait(main_thread_);
612 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
613 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
615 // The second impl reference is destroyed last, causing the mailbox to be
616 // released back to the embedder with the last sync point from the impl tree.
617 EXPECT_CALL(test_data_.mock_callback_,
618 Release(test_data_.mailbox_name1_, 100, true)).Times(1);
620 compositor1->Run(100, true, main_thread_task_runner_.get());
621 Wait(main_thread_);
622 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
625 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) {
626 scoped_refptr<TextureLayer> test_layer =
627 TextureLayer::CreateForMailbox(nullptr);
628 ASSERT_TRUE(test_layer.get());
630 main_thread_.message_loop()->PostTask(
631 FROM_HERE,
632 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
633 base::Unretained(this)));
635 Wait(main_thread_);
637 // The texture layer is attached to compositor1, and passes a reference to its
638 // impl tree.
639 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
640 main_thread_.message_loop()->PostTask(
641 FROM_HERE,
642 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
643 base::Unretained(this),
644 &compositor1));
646 // Then the texture layer is removed and attached to compositor2, and passes a
647 // reference to its impl tree.
648 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
649 main_thread_.message_loop()->PostTask(
650 FROM_HERE,
651 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
652 base::Unretained(this),
653 &compositor2));
655 Wait(main_thread_);
656 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
658 // The main thread reference is destroyed first.
659 main_thread_.message_loop()->PostTask(
660 FROM_HERE,
661 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
662 base::Unretained(this)));
664 EXPECT_CALL(test_data_.mock_callback_,
665 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
667 bool manual_reset = false;
668 bool initially_signaled = false;
669 base::WaitableEvent begin_capture(manual_reset, initially_signaled);
670 base::WaitableEvent wait_for_capture(manual_reset, initially_signaled);
671 base::WaitableEvent stop_capture(manual_reset, initially_signaled);
673 // Post a task to start capturing tasks on the main thread. This will block
674 // the main thread until we signal the |stop_capture| event.
675 main_thread_.message_loop()->PostTask(
676 FROM_HERE,
677 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait,
678 base::Unretained(this),
679 &begin_capture,
680 &wait_for_capture,
681 &stop_capture));
683 // Before the main thread capturing starts, one compositor destroys their
684 // impl reference. Since capturing did not start, this gets post-tasked to
685 // the main thread.
686 compositor1->Run(100, false, main_thread_task_runner_.get());
688 // Start capturing on the main thread.
689 begin_capture.Signal();
690 wait_for_capture.Wait();
692 // Meanwhile, the second compositor released its impl reference, but this task
693 // gets shortcutted directly to the main thread. This means the reference is
694 // released before compositor1, whose reference will be released later when
695 // the post-task is serviced. But since it was destroyed _on the impl thread_
696 // last, its sync point values should be used.
697 compositor2->Run(200, true, main_thread_task_runner_.get());
699 stop_capture.Signal();
700 Wait(main_thread_);
702 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
705 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest {
706 public:
707 TextureLayerImplWithMailboxThreadedCallback()
708 : callback_count_(0),
709 commit_count_(0) {}
711 // Make sure callback is received on main and doesn't block the impl thread.
712 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
713 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
714 EXPECT_FALSE(lost_resource);
715 ++callback_count_;
718 void SetMailbox(char mailbox_char) {
719 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
720 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
721 base::Bind(
722 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback,
723 base::Unretained(this)));
724 layer_->SetTextureMailbox(
725 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
726 callback.Pass());
729 void BeginTest() override {
730 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
732 gfx::Size bounds(100, 100);
733 root_ = Layer::Create();
734 root_->SetBounds(bounds);
736 layer_ = TextureLayer::CreateForMailbox(nullptr);
737 layer_->SetIsDrawable(true);
738 layer_->SetBounds(bounds);
740 root_->AddChild(layer_);
741 layer_tree_host()->SetRootLayer(root_);
742 layer_tree_host()->SetViewportSize(bounds);
743 SetMailbox('1');
744 EXPECT_EQ(0, callback_count_);
746 // Case #1: change mailbox before the commit. The old mailbox should be
747 // released immediately.
748 SetMailbox('2');
749 EXPECT_EQ(1, callback_count_);
750 PostSetNeedsCommitToMainThread();
753 void DidCommit() override {
754 ++commit_count_;
755 switch (commit_count_) {
756 case 1:
757 // Case #2: change mailbox after the commit (and draw), where the
758 // layer draws. The old mailbox should be released during the next
759 // commit.
760 SetMailbox('3');
761 EXPECT_EQ(1, callback_count_);
762 break;
763 case 2:
764 EXPECT_EQ(2, callback_count_);
765 // Case #3: change mailbox when the layer doesn't draw. The old
766 // mailbox should be released during the next commit.
767 layer_->SetBounds(gfx::Size());
768 SetMailbox('4');
769 break;
770 case 3:
771 EXPECT_EQ(3, callback_count_);
772 // Case #4: release mailbox that was committed but never drawn. The
773 // old mailbox should be released during the next commit.
774 layer_->SetTextureMailbox(TextureMailbox(), nullptr);
775 break;
776 case 4:
777 if (layer_tree_host()->settings().impl_side_painting) {
778 // With impl painting, the texture mailbox will still be on the impl
779 // thread when the commit finishes, because the layer is not drawble
780 // when it has no texture mailbox, and thus does not block the commit
781 // on activation. So, we wait for activation.
782 // TODO(danakj): fix this. crbug.com/277953
783 layer_tree_host()->SetNeedsCommit();
784 break;
785 } else {
786 ++commit_count_;
788 case 5:
789 EXPECT_EQ(4, callback_count_);
790 // Restore a mailbox for the next step.
791 SetMailbox('5');
792 break;
793 case 6:
794 // Case #5: remove layer from tree. Callback should *not* be called, the
795 // mailbox is returned to the main thread.
796 EXPECT_EQ(4, callback_count_);
797 layer_->RemoveFromParent();
798 break;
799 case 7:
800 if (layer_tree_host()->settings().impl_side_painting) {
801 // With impl painting, the texture mailbox will still be on the impl
802 // thread when the commit finishes, because the layer is not around to
803 // block the commit on activation anymore. So, we wait for activation.
804 // TODO(danakj): fix this. crbug.com/277953
805 layer_tree_host()->SetNeedsCommit();
806 break;
807 } else {
808 ++commit_count_;
810 case 8:
811 EXPECT_EQ(4, callback_count_);
812 // Resetting the mailbox will call the callback now.
813 layer_->SetTextureMailbox(TextureMailbox(), nullptr);
814 EXPECT_EQ(5, callback_count_);
815 EndTest();
816 break;
817 default:
818 NOTREACHED();
819 break;
823 void AfterTest() override {}
825 private:
826 base::ThreadChecker main_thread_;
827 int callback_count_;
828 int commit_count_;
829 scoped_refptr<Layer> root_;
830 scoped_refptr<TextureLayer> layer_;
833 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
834 TextureLayerImplWithMailboxThreadedCallback);
837 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
838 protected:
839 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
841 static void ReleaseCallback(uint32 sync_point, bool lost_resource) {}
843 void SetMailbox(char mailbox_char) {
844 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
845 base::Bind(
846 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
847 layer_->SetTextureMailbox(
848 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
849 callback.Pass());
852 void BeginTest() override {
853 gfx::Size bounds(100, 100);
854 root_ = Layer::Create();
855 root_->SetBounds(bounds);
857 layer_ = TextureLayer::CreateForMailbox(nullptr);
858 layer_->SetIsDrawable(true);
859 layer_->SetBounds(bounds);
861 root_->AddChild(layer_);
862 layer_tree_host()->SetRootLayer(root_);
863 layer_tree_host()->SetViewportSize(bounds);
864 SetMailbox('1');
866 PostSetNeedsCommitToMainThread();
869 void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
870 ++activate_count_;
873 void DidCommit() override {
874 switch (layer_tree_host()->source_frame_number()) {
875 case 1:
876 // The first mailbox has been activated. Set a new mailbox, and
877 // expect the next commit to finish *after* it is activated.
878 SetMailbox('2');
879 break;
880 case 2:
881 // The second mailbox has been activated. Remove the layer from
882 // the tree to cause another commit/activation. The commit should
883 // finish *after* the layer is removed from the active tree.
884 layer_->RemoveFromParent();
885 break;
886 case 3:
887 EndTest();
888 break;
892 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
893 switch (host_impl->active_tree()->source_frame_number()) {
894 case 0: {
895 // The activate for the 1st mailbox should have happened before now.
896 EXPECT_EQ(1, activate_count_);
897 break;
899 case 1: {
900 // The activate for the 2nd mailbox should have happened before now.
901 EXPECT_EQ(2, activate_count_);
902 break;
904 case 2: {
905 // The activate to remove the layer should have happened before now.
906 EXPECT_EQ(3, activate_count_);
907 break;
909 case 3: {
910 NOTREACHED();
911 break;
916 void AfterTest() override {}
918 int activate_count_;
919 scoped_refptr<Layer> root_;
920 scoped_refptr<TextureLayer> layer_;
923 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
924 TextureLayerMailboxIsActivatedDuringCommit);
926 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
927 protected:
928 TextureLayerImplWithMailboxTest()
929 : fake_client_(
930 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
932 void SetUp() override {
933 TextureLayerTest::SetUp();
934 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
935 EXPECT_TRUE(host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()));
938 bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
939 bool will_draw = layer->WillDraw(
940 mode, host_impl_.active_tree()->resource_provider());
941 if (will_draw)
942 layer->DidDraw(host_impl_.active_tree()->resource_provider());
943 return will_draw;
946 FakeLayerTreeHostClient fake_client_;
949 // Test conditions for results of TextureLayerImpl::WillDraw under
950 // different configurations of different mailbox, texture_id, and draw_mode.
951 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
952 EXPECT_CALL(
953 test_data_.mock_callback_,
954 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
955 .Times(AnyNumber());
956 EXPECT_CALL(test_data_.mock_callback_,
957 ReleaseImpl2(test_data_.shared_bitmap_.get(), 0, false, _))
958 .Times(AnyNumber());
959 // Hardware mode.
961 scoped_ptr<TextureLayerImpl> impl_layer =
962 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
963 impl_layer->SetTextureMailbox(
964 test_data_.mailbox1_,
965 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
966 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
970 scoped_ptr<TextureLayerImpl> impl_layer =
971 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
972 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
973 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
977 // Software resource.
978 scoped_ptr<TextureLayerImpl> impl_layer =
979 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
980 impl_layer->SetTextureMailbox(
981 test_data_.mailbox3_,
982 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
983 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
986 // Software mode.
988 scoped_ptr<TextureLayerImpl> impl_layer =
989 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
990 impl_layer->SetTextureMailbox(
991 test_data_.mailbox1_,
992 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
993 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
997 scoped_ptr<TextureLayerImpl> impl_layer =
998 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
999 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1000 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1004 // Software resource.
1005 scoped_ptr<TextureLayerImpl> impl_layer =
1006 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1007 impl_layer->SetTextureMailbox(
1008 test_data_.mailbox3_,
1009 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
1010 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1013 // Resourceless software mode.
1015 scoped_ptr<TextureLayerImpl> impl_layer =
1016 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1017 impl_layer->SetTextureMailbox(
1018 test_data_.mailbox1_,
1019 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1020 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
1024 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
1025 host_impl_.CreatePendingTree();
1026 scoped_ptr<TextureLayerImpl> pending_layer;
1027 pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1);
1028 ASSERT_TRUE(pending_layer);
1030 scoped_ptr<LayerImpl> active_layer(
1031 pending_layer->CreateLayerImpl(host_impl_.active_tree()));
1032 ASSERT_TRUE(active_layer);
1034 pending_layer->SetTextureMailbox(
1035 test_data_.mailbox1_,
1036 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1038 // Test multiple commits without an activation.
1039 EXPECT_CALL(
1040 test_data_.mock_callback_,
1041 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
1042 .Times(1);
1043 pending_layer->SetTextureMailbox(
1044 test_data_.mailbox2_,
1045 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox2_impl_));
1046 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1048 // Test callback after activation.
1049 pending_layer->PushPropertiesTo(active_layer.get());
1050 active_layer->DidBecomeActive();
1052 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1053 pending_layer->SetTextureMailbox(
1054 test_data_.mailbox1_,
1055 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1056 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1058 EXPECT_CALL(test_data_.mock_callback_,
1059 ReleaseImpl(test_data_.mailbox_name2_, _, false, _)).Times(1);
1060 pending_layer->PushPropertiesTo(active_layer.get());
1061 active_layer->DidBecomeActive();
1062 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1064 // Test resetting the mailbox.
1065 EXPECT_CALL(test_data_.mock_callback_,
1066 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1067 pending_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1068 pending_layer->PushPropertiesTo(active_layer.get());
1069 active_layer->DidBecomeActive();
1070 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1072 // Test destructor.
1073 EXPECT_CALL(
1074 test_data_.mock_callback_,
1075 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
1076 .Times(1);
1077 pending_layer->SetTextureMailbox(
1078 test_data_.mailbox1_,
1079 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1082 TEST_F(TextureLayerImplWithMailboxTest,
1083 TestDestructorCallbackOnCreatedResource) {
1084 scoped_ptr<TextureLayerImpl> impl_layer;
1085 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1086 ASSERT_TRUE(impl_layer);
1088 EXPECT_CALL(test_data_.mock_callback_,
1089 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1090 impl_layer->SetTextureMailbox(
1091 test_data_.mailbox1_,
1092 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1093 impl_layer->DidBecomeActive();
1094 EXPECT_TRUE(impl_layer->WillDraw(
1095 DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1096 impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1097 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1100 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1101 ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1102 ResourceProvider::ResourceId id = provider->CreateResourceFromTextureMailbox(
1103 test_data_.mailbox1_,
1104 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1105 provider->AllocateForTesting(id);
1107 // Transfer some resources to the parent.
1108 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1109 resource_ids_to_transfer.push_back(id);
1110 TransferableResourceArray list;
1111 provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1112 EXPECT_TRUE(provider->InUseByConsumer(id));
1113 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1114 provider->DeleteResource(id);
1115 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1116 EXPECT_CALL(test_data_.mock_callback_,
1117 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1118 ReturnedResourceArray returned;
1119 TransferableResource::ReturnResources(list, &returned);
1120 provider->ReceiveReturnsFromParent(returned);
1123 // Checks that TextureLayer::Update does not cause an extra commit when setting
1124 // the texture mailbox.
1125 class TextureLayerNoExtraCommitForMailboxTest
1126 : public LayerTreeTest,
1127 public TextureLayerClient {
1128 public:
1129 // TextureLayerClient implementation.
1130 bool PrepareTextureMailbox(
1131 TextureMailbox* texture_mailbox,
1132 scoped_ptr<SingleReleaseCallback>* release_callback,
1133 bool use_shared_memory) override {
1134 if (layer_tree_host()->source_frame_number() == 1) {
1135 // Once this has been committed, the mailbox will be released.
1136 *texture_mailbox = TextureMailbox();
1137 return true;
1140 *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1141 *release_callback = SingleReleaseCallback::Create(
1142 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1143 base::Unretained(this)));
1144 return true;
1147 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1148 // Source frame number during callback is the same as the source frame
1149 // on which it was released.
1150 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1151 EndTest();
1154 void SetupTree() override {
1155 scoped_refptr<Layer> root = Layer::Create();
1156 root->SetBounds(gfx::Size(10, 10));
1157 root->SetIsDrawable(true);
1159 texture_layer_ = TextureLayer::CreateForMailbox(this);
1160 texture_layer_->SetBounds(gfx::Size(10, 10));
1161 texture_layer_->SetIsDrawable(true);
1162 root->AddChild(texture_layer_);
1164 layer_tree_host()->SetRootLayer(root);
1165 LayerTreeTest::SetupTree();
1168 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1170 void DidCommitAndDrawFrame() override {
1171 switch (layer_tree_host()->source_frame_number()) {
1172 case 1:
1173 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1174 // Invalidate the texture layer to clear the mailbox before
1175 // ending the test.
1176 texture_layer_->SetNeedsDisplay();
1177 break;
1178 case 2:
1179 break;
1180 default:
1181 NOTREACHED();
1182 break;
1186 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1187 ASSERT_TRUE(result);
1188 DelegatedFrameData* delegated_frame_data =
1189 output_surface()->last_sent_frame().delegated_frame_data.get();
1190 if (!delegated_frame_data)
1191 return;
1193 // Return all resources immediately.
1194 TransferableResourceArray resources_to_return =
1195 output_surface()->resources_held_by_parent();
1197 CompositorFrameAck ack;
1198 for (size_t i = 0; i < resources_to_return.size(); ++i)
1199 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1200 host_impl->ReclaimResources(&ack);
1203 void AfterTest() override {}
1205 private:
1206 scoped_refptr<TextureLayer> texture_layer_;
1209 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1211 // Checks that changing a mailbox in the client for a TextureLayer that's
1212 // invisible correctly works and uses the new mailbox as soon as the layer
1213 // becomes visible (and returns the old one).
1214 class TextureLayerChangeInvisibleMailboxTest
1215 : public LayerTreeTest,
1216 public TextureLayerClient {
1217 public:
1218 TextureLayerChangeInvisibleMailboxTest()
1219 : mailbox_changed_(true),
1220 mailbox_returned_(0),
1221 prepare_called_(0),
1222 commit_count_(0) {
1223 mailbox_ = MakeMailbox('1');
1226 // TextureLayerClient implementation.
1227 bool PrepareTextureMailbox(
1228 TextureMailbox* mailbox,
1229 scoped_ptr<SingleReleaseCallback>* release_callback,
1230 bool use_shared_memory) override {
1231 ++prepare_called_;
1232 if (!mailbox_changed_)
1233 return false;
1234 *mailbox = mailbox_;
1235 *release_callback = SingleReleaseCallback::Create(
1236 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1237 base::Unretained(this)));
1238 return true;
1241 TextureMailbox MakeMailbox(char name) {
1242 return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0);
1245 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1246 ++mailbox_returned_;
1249 void SetupTree() override {
1250 scoped_refptr<Layer> root = Layer::Create();
1251 root->SetBounds(gfx::Size(10, 10));
1252 root->SetIsDrawable(true);
1254 solid_layer_ = SolidColorLayer::Create();
1255 solid_layer_->SetBounds(gfx::Size(10, 10));
1256 solid_layer_->SetIsDrawable(true);
1257 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1258 root->AddChild(solid_layer_);
1260 parent_layer_ = Layer::Create();
1261 parent_layer_->SetBounds(gfx::Size(10, 10));
1262 parent_layer_->SetIsDrawable(true);
1263 root->AddChild(parent_layer_);
1265 texture_layer_ = TextureLayer::CreateForMailbox(this);
1266 texture_layer_->SetBounds(gfx::Size(10, 10));
1267 texture_layer_->SetIsDrawable(true);
1268 parent_layer_->AddChild(texture_layer_);
1270 layer_tree_host()->SetRootLayer(root);
1271 LayerTreeTest::SetupTree();
1274 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1276 void DidCommitAndDrawFrame() override {
1277 ++commit_count_;
1278 switch (commit_count_) {
1279 case 1:
1280 // We should have updated the layer, committing the texture.
1281 EXPECT_EQ(1, prepare_called_);
1282 // Make layer invisible.
1283 parent_layer_->SetOpacity(0.f);
1284 break;
1285 case 2:
1286 // Layer shouldn't have been updated.
1287 EXPECT_EQ(1, prepare_called_);
1288 // Change the texture.
1289 mailbox_ = MakeMailbox('2');
1290 mailbox_changed_ = true;
1291 texture_layer_->SetNeedsDisplay();
1292 // Force a change to make sure we draw a frame.
1293 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1294 break;
1295 case 3:
1296 // Layer shouldn't have been updated.
1297 EXPECT_EQ(1, prepare_called_);
1298 // So the old mailbox isn't returned yet.
1299 EXPECT_EQ(0, mailbox_returned_);
1300 // Make layer visible again.
1301 parent_layer_->SetOpacity(1.f);
1302 break;
1303 case 4:
1304 // Layer should have been updated.
1305 EXPECT_EQ(2, prepare_called_);
1306 // So the old mailbox should have been returned already.
1307 EXPECT_EQ(1, mailbox_returned_);
1308 texture_layer_->ClearClient();
1309 break;
1310 case 5:
1311 EXPECT_EQ(2, mailbox_returned_);
1312 EndTest();
1313 break;
1314 default:
1315 NOTREACHED();
1316 break;
1320 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1321 ASSERT_TRUE(result);
1322 DelegatedFrameData* delegated_frame_data =
1323 output_surface()->last_sent_frame().delegated_frame_data.get();
1324 if (!delegated_frame_data)
1325 return;
1327 // Return all resources immediately.
1328 TransferableResourceArray resources_to_return =
1329 output_surface()->resources_held_by_parent();
1331 CompositorFrameAck ack;
1332 for (size_t i = 0; i < resources_to_return.size(); ++i)
1333 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1334 host_impl->ReclaimResources(&ack);
1337 void AfterTest() override {}
1339 private:
1340 scoped_refptr<SolidColorLayer> solid_layer_;
1341 scoped_refptr<Layer> parent_layer_;
1342 scoped_refptr<TextureLayer> texture_layer_;
1344 // Used on the main thread.
1345 bool mailbox_changed_;
1346 TextureMailbox mailbox_;
1347 int mailbox_returned_;
1348 int prepare_called_;
1349 int commit_count_;
1352 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1354 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1355 // the mailbox back to TextureLayerClient.
1356 class TextureLayerReleaseResourcesBase
1357 : public LayerTreeTest,
1358 public TextureLayerClient {
1359 public:
1360 // TextureLayerClient implementation.
1361 bool PrepareTextureMailbox(
1362 TextureMailbox* mailbox,
1363 scoped_ptr<SingleReleaseCallback>* release_callback,
1364 bool use_shared_memory) override {
1365 *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1366 *release_callback = SingleReleaseCallback::Create(
1367 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1368 base::Unretained(this)));
1369 return true;
1372 void MailboxReleased(unsigned sync_point, bool lost_resource) {
1373 mailbox_released_ = true;
1376 void SetupTree() override {
1377 LayerTreeTest::SetupTree();
1379 scoped_refptr<TextureLayer> texture_layer =
1380 TextureLayer::CreateForMailbox(this);
1381 texture_layer->SetBounds(gfx::Size(10, 10));
1382 texture_layer->SetIsDrawable(true);
1384 layer_tree_host()->root_layer()->AddChild(texture_layer);
1387 void BeginTest() override {
1388 mailbox_released_ = false;
1389 PostSetNeedsCommitToMainThread();
1392 void DidCommitAndDrawFrame() override { EndTest(); }
1394 void AfterTest() override { EXPECT_TRUE(mailbox_released_); }
1396 private:
1397 bool mailbox_released_;
1400 class TextureLayerReleaseResourcesAfterCommit
1401 : public TextureLayerReleaseResourcesBase {
1402 public:
1403 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
1404 LayerTreeImpl* tree = nullptr;
1405 if (host_impl->settings().impl_side_painting)
1406 tree = host_impl->pending_tree();
1407 else
1408 tree = host_impl->active_tree();
1409 tree->root_layer()->children()[0]->ReleaseResources();
1413 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1415 class TextureLayerReleaseResourcesAfterActivate
1416 : public TextureLayerReleaseResourcesBase {
1417 public:
1418 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
1419 host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
1423 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
1425 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
1426 public:
1427 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1428 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1429 EXPECT_FALSE(lost_resource);
1430 ++callback_count_;
1431 EndTest();
1434 void SetMailbox(char mailbox_char) {
1435 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1436 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1437 base::Bind(
1438 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
1439 base::Unretained(this)));
1440 layer_->SetTextureMailbox(
1441 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1442 callback.Pass());
1445 void SetupTree() override {
1446 gfx::Size bounds(100, 100);
1447 root_ = Layer::Create();
1448 root_->SetBounds(bounds);
1450 layer_ = TextureLayer::CreateForMailbox(nullptr);
1451 layer_->SetIsDrawable(true);
1452 layer_->SetBounds(bounds);
1454 root_->AddChild(layer_);
1455 layer_tree_host()->SetRootLayer(root_);
1456 layer_tree_host()->SetViewportSize(bounds);
1459 void BeginTest() override {
1460 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1462 callback_count_ = 0;
1464 // Set the mailbox on the main thread.
1465 SetMailbox('1');
1466 EXPECT_EQ(0, callback_count_);
1468 PostSetNeedsCommitToMainThread();
1471 void DidCommitAndDrawFrame() override {
1472 switch (layer_tree_host()->source_frame_number()) {
1473 case 1:
1474 // Delete the TextureLayer on the main thread while the mailbox is in
1475 // the impl tree.
1476 layer_->RemoveFromParent();
1477 layer_ = nullptr;
1478 break;
1482 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1484 private:
1485 base::ThreadChecker main_thread_;
1486 int callback_count_;
1487 scoped_refptr<Layer> root_;
1488 scoped_refptr<TextureLayer> layer_;
1491 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1492 TextureLayerWithMailboxMainThreadDeleted);
1494 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
1495 public:
1496 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1497 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1498 EXPECT_FALSE(lost_resource);
1499 ++callback_count_;
1500 EndTest();
1503 void SetMailbox(char mailbox_char) {
1504 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1505 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1506 base::Bind(
1507 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
1508 base::Unretained(this)));
1509 layer_->SetTextureMailbox(
1510 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1511 callback.Pass());
1514 void SetupTree() override {
1515 gfx::Size bounds(100, 100);
1516 root_ = Layer::Create();
1517 root_->SetBounds(bounds);
1519 layer_ = TextureLayer::CreateForMailbox(nullptr);
1520 layer_->SetIsDrawable(true);
1521 layer_->SetBounds(bounds);
1523 root_->AddChild(layer_);
1524 layer_tree_host()->SetRootLayer(root_);
1525 layer_tree_host()->SetViewportSize(bounds);
1528 void BeginTest() override {
1529 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1531 callback_count_ = 0;
1533 // Set the mailbox on the main thread.
1534 SetMailbox('1');
1535 EXPECT_EQ(0, callback_count_);
1537 PostSetNeedsCommitToMainThread();
1540 void DidCommitAndDrawFrame() override {
1541 switch (layer_tree_host()->source_frame_number()) {
1542 case 1:
1543 // Remove the TextureLayer on the main thread while the mailbox is in
1544 // the impl tree, but don't delete the TextureLayer until after the impl
1545 // tree side is deleted.
1546 layer_->RemoveFromParent();
1547 break;
1548 case 2:
1549 layer_ = nullptr;
1550 break;
1554 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1556 private:
1557 base::ThreadChecker main_thread_;
1558 int callback_count_;
1559 scoped_refptr<Layer> root_;
1560 scoped_refptr<TextureLayer> layer_;
1563 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1564 TextureLayerWithMailboxImplThreadDeleted);
1566 } // namespace
1567 } // namespace cc