Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / cc / layers / texture_layer_unittest.cc
blobc3c6fd5110e11a3ceaa6ed2ea0c50ff158569bdc
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/layers/texture_layer.h"
7 #include <algorithm>
8 #include <string>
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/location.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/threading/thread.h"
17 #include "base/time/time.h"
18 #include "cc/layers/solid_color_layer.h"
19 #include "cc/layers/texture_layer_client.h"
20 #include "cc/layers/texture_layer_impl.h"
21 #include "cc/output/compositor_frame_ack.h"
22 #include "cc/output/context_provider.h"
23 #include "cc/resources/returned_resource.h"
24 #include "cc/test/fake_impl_proxy.h"
25 #include "cc/test/fake_layer_tree_host_client.h"
26 #include "cc/test/fake_layer_tree_host_impl.h"
27 #include "cc/test/fake_output_surface.h"
28 #include "cc/test/layer_test_common.h"
29 #include "cc/test/layer_tree_test.h"
30 #include "cc/test/test_task_graph_runner.h"
31 #include "cc/test/test_web_graphics_context_3d.h"
32 #include "cc/trees/blocking_task_runner.h"
33 #include "cc/trees/layer_tree_host.h"
34 #include "cc/trees/layer_tree_impl.h"
35 #include "cc/trees/single_thread_proxy.h"
36 #include "gpu/GLES2/gl2extchromium.h"
37 #include "testing/gmock/include/gmock/gmock.h"
38 #include "testing/gtest/include/gtest/gtest.h"
40 using ::testing::Mock;
41 using ::testing::_;
42 using ::testing::AtLeast;
43 using ::testing::AnyNumber;
44 using ::testing::InvokeWithoutArgs;
46 namespace cc {
47 namespace {
49 gpu::Mailbox MailboxFromChar(char value) {
50 gpu::Mailbox mailbox;
51 memset(mailbox.name, value, sizeof(mailbox.name));
52 return mailbox;
55 class MockLayerTreeHost : public LayerTreeHost {
56 public:
57 static scoped_ptr<MockLayerTreeHost> Create(FakeLayerTreeHostClient* client) {
58 LayerTreeHost::InitParams params;
59 params.client = client;
60 LayerTreeSettings settings;
61 params.settings = &settings;
62 return make_scoped_ptr(new MockLayerTreeHost(client, &params));
65 MOCK_METHOD0(SetNeedsCommit, void());
66 MOCK_METHOD0(SetNeedsUpdateLayers, void());
67 MOCK_METHOD0(StartRateLimiter, void());
68 MOCK_METHOD0(StopRateLimiter, void());
70 private:
71 MockLayerTreeHost(FakeLayerTreeHostClient* client,
72 LayerTreeHost::InitParams* params)
73 : LayerTreeHost(params) {
74 InitializeSingleThreaded(client, base::ThreadTaskRunnerHandle::Get(),
75 nullptr);
79 class FakeTextureLayerClient : public TextureLayerClient {
80 public:
81 FakeTextureLayerClient() : mailbox_changed_(true) {}
83 bool PrepareTextureMailbox(
84 TextureMailbox* mailbox,
85 scoped_ptr<SingleReleaseCallback>* release_callback,
86 bool use_shared_memory) override {
87 if (!mailbox_changed_)
88 return false;
90 *mailbox = mailbox_;
91 *release_callback = release_callback_.Pass();
92 mailbox_changed_ = false;
93 return true;
96 void set_mailbox(const TextureMailbox& mailbox,
97 scoped_ptr<SingleReleaseCallback> release_callback) {
98 mailbox_ = mailbox;
99 release_callback_ = release_callback.Pass();
100 mailbox_changed_ = true;
103 private:
104 TextureMailbox mailbox_;
105 scoped_ptr<SingleReleaseCallback> release_callback_;
106 bool mailbox_changed_;
107 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient);
110 class MockMailboxCallback {
111 public:
112 MOCK_METHOD3(Release,
113 void(const gpu::Mailbox& mailbox,
114 uint32 sync_point,
115 bool lost_resource));
116 MOCK_METHOD3(Release2,
117 void(SharedBitmap* shared_bitmap,
118 uint32 sync_point,
119 bool lost_resource));
120 MOCK_METHOD4(ReleaseImpl,
121 void(const gpu::Mailbox& mailbox,
122 uint32 sync_point,
123 bool lost_resource,
124 BlockingTaskRunner* main_thread_task_runner));
125 MOCK_METHOD4(ReleaseImpl2,
126 void(SharedBitmap* shared_bitmap,
127 uint32 sync_point,
128 bool lost_resource,
129 BlockingTaskRunner* main_thread_task_runner));
132 struct CommonMailboxObjects {
133 explicit CommonMailboxObjects(SharedBitmapManager* manager)
134 : mailbox_name1_(MailboxFromChar('1')),
135 mailbox_name2_(MailboxFromChar('2')),
136 sync_point1_(1),
137 sync_point2_(2) {
138 release_mailbox1_ = base::Bind(&MockMailboxCallback::Release,
139 base::Unretained(&mock_callback_),
140 mailbox_name1_);
141 release_mailbox2_ = base::Bind(&MockMailboxCallback::Release,
142 base::Unretained(&mock_callback_),
143 mailbox_name2_);
144 release_mailbox1_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl,
145 base::Unretained(&mock_callback_),
146 mailbox_name1_);
147 release_mailbox2_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl,
148 base::Unretained(&mock_callback_),
149 mailbox_name2_);
150 const uint32 arbitrary_target1 = GL_TEXTURE_2D;
151 const uint32 arbitrary_target2 = GL_TEXTURE_EXTERNAL_OES;
152 mailbox1_ = TextureMailbox(mailbox_name1_, arbitrary_target1, sync_point1_);
153 mailbox2_ = TextureMailbox(mailbox_name2_, arbitrary_target2, sync_point2_);
154 gfx::Size size(128, 128);
155 shared_bitmap_ = manager->AllocateSharedBitmap(size);
156 DCHECK(shared_bitmap_);
157 release_mailbox3_ =
158 base::Bind(&MockMailboxCallback::Release2,
159 base::Unretained(&mock_callback_), shared_bitmap_.get());
160 release_mailbox3_impl_ =
161 base::Bind(&MockMailboxCallback::ReleaseImpl2,
162 base::Unretained(&mock_callback_), shared_bitmap_.get());
163 mailbox3_ = TextureMailbox(shared_bitmap_.get(), size);
166 gpu::Mailbox mailbox_name1_;
167 gpu::Mailbox mailbox_name2_;
168 MockMailboxCallback mock_callback_;
169 ReleaseCallback release_mailbox1_;
170 ReleaseCallback release_mailbox2_;
171 ReleaseCallback release_mailbox3_;
172 ReleaseCallbackImpl release_mailbox1_impl_;
173 ReleaseCallbackImpl release_mailbox2_impl_;
174 ReleaseCallbackImpl release_mailbox3_impl_;
175 TextureMailbox mailbox1_;
176 TextureMailbox mailbox2_;
177 TextureMailbox mailbox3_;
178 uint32 sync_point1_;
179 uint32 sync_point2_;
180 scoped_ptr<SharedBitmap> shared_bitmap_;
183 class TextureLayerTest : public testing::Test {
184 public:
185 TextureLayerTest()
186 : fake_client_(
187 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
188 host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_),
189 test_data_(&shared_bitmap_manager_) {}
191 protected:
192 void SetUp() override {
193 layer_tree_host_ = MockLayerTreeHost::Create(&fake_client_);
194 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
195 layer_tree_host_->SetViewportSize(gfx::Size(10, 10));
196 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
199 void TearDown() override {
200 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
201 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
203 layer_tree_host_->SetRootLayer(nullptr);
204 layer_tree_host_ = nullptr;
207 scoped_ptr<MockLayerTreeHost> layer_tree_host_;
208 FakeImplProxy proxy_;
209 FakeLayerTreeHostClient fake_client_;
210 TestSharedBitmapManager shared_bitmap_manager_;
211 TestTaskGraphRunner task_graph_runner_;
212 FakeLayerTreeHostImpl host_impl_;
213 CommonMailboxObjects test_data_;
214 LayerSettings layer_settings_;
217 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) {
218 scoped_refptr<TextureLayer> test_layer =
219 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
220 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer));
222 // Test properties that should call SetNeedsCommit. All properties need to
223 // be set to new values in order for SetNeedsCommit to be called.
224 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false));
225 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetNearestNeighbor(true));
226 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV(
227 gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f)));
228 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity(
229 0.5f, 0.5f, 0.5f, 0.5f));
230 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false));
231 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true));
234 TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) {
235 const gfx::Size layer_bounds(100, 100);
236 const gfx::Rect layer_rect(layer_bounds);
237 const Region layer_region(layer_rect);
239 scoped_refptr<TextureLayer> layer =
240 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
241 layer->SetBounds(layer_bounds);
242 layer->draw_properties().visible_content_rect = layer_rect;
243 layer->SetBlendBackgroundColor(true);
245 // Verify initial conditions.
246 EXPECT_FALSE(layer->contents_opaque());
247 EXPECT_EQ(0u, layer->background_color());
248 EXPECT_EQ(Region().ToString(),
249 layer->VisibleContentOpaqueRegion().ToString());
251 // Opaque background.
252 layer->SetBackgroundColor(SK_ColorWHITE);
253 EXPECT_EQ(layer_region.ToString(),
254 layer->VisibleContentOpaqueRegion().ToString());
256 // Transparent background.
257 layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
258 EXPECT_EQ(Region().ToString(),
259 layer->VisibleContentOpaqueRegion().ToString());
262 TEST_F(TextureLayerTest, RateLimiter) {
263 FakeTextureLayerClient client;
264 scoped_refptr<TextureLayer> test_layer =
265 TextureLayer::CreateForMailbox(layer_settings_, &client);
266 test_layer->SetIsDrawable(true);
267 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
268 layer_tree_host_->SetRootLayer(test_layer);
270 // Don't rate limit until we invalidate.
271 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
272 test_layer->SetRateLimitContext(true);
273 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
275 // Do rate limit after we invalidate.
276 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
277 test_layer->SetNeedsDisplay();
278 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
280 // Stop rate limiter when we don't want it any more.
281 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
282 test_layer->SetRateLimitContext(false);
283 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
285 // Or we clear the client.
286 test_layer->SetRateLimitContext(true);
287 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
288 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
289 test_layer->ClearClient();
290 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
292 // Reset to a layer with a client, that started the rate limiter.
293 test_layer = TextureLayer::CreateForMailbox(layer_settings_, &client);
294 test_layer->SetIsDrawable(true);
295 test_layer->SetRateLimitContext(true);
296 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
297 layer_tree_host_->SetRootLayer(test_layer);
298 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
299 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
300 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
301 test_layer->SetNeedsDisplay();
302 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
304 // Stop rate limiter when we're removed from the tree.
305 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
306 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
307 layer_tree_host_->SetRootLayer(nullptr);
308 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
311 class TestMailboxHolder : public TextureLayer::TextureMailboxHolder {
312 public:
313 using TextureLayer::TextureMailboxHolder::Create;
315 protected:
316 ~TestMailboxHolder() override {}
319 class TextureLayerWithMailboxTest : public TextureLayerTest {
320 protected:
321 void TearDown() override {
322 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
323 EXPECT_CALL(test_data_.mock_callback_,
324 Release(test_data_.mailbox_name1_,
325 test_data_.sync_point1_,
326 false)).Times(1);
327 TextureLayerTest::TearDown();
331 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
332 scoped_refptr<TextureLayer> test_layer =
333 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
334 ASSERT_TRUE(test_layer.get());
336 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
337 layer_tree_host_->SetRootLayer(test_layer);
338 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
340 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
341 test_layer->SetTextureMailbox(
342 test_data_.mailbox1_,
343 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
344 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
346 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
347 EXPECT_CALL(test_data_.mock_callback_,
348 Release(test_data_.mailbox_name1_,
349 test_data_.sync_point1_,
350 false))
351 .Times(1);
352 test_layer->SetTextureMailbox(
353 test_data_.mailbox2_,
354 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
355 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
356 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
358 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
359 EXPECT_CALL(test_data_.mock_callback_,
360 Release(test_data_.mailbox_name2_,
361 test_data_.sync_point2_,
362 false))
363 .Times(1);
364 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
365 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
366 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
368 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
369 test_layer->SetTextureMailbox(
370 test_data_.mailbox3_,
371 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
372 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
373 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
375 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
376 EXPECT_CALL(test_data_.mock_callback_,
377 Release2(test_data_.shared_bitmap_.get(), 0, false)).Times(1);
378 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
379 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
380 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
382 // Test destructor.
383 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
384 test_layer->SetTextureMailbox(
385 test_data_.mailbox1_,
386 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
389 TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) {
390 scoped_refptr<TextureLayer> test_layer =
391 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
392 ASSERT_TRUE(test_layer.get());
394 // These use the same gpu::Mailbox, but different sync points.
395 TextureMailbox mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D, 1);
396 TextureMailbox mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D, 2);
398 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
399 layer_tree_host_->SetRootLayer(test_layer);
400 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
402 // Set the mailbox the first time. It should cause a commit.
403 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
404 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox1);
405 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
407 // Set the mailbox again with a new sync point, as the backing texture has
408 // been updated. It should cause a new commit.
409 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
410 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox2);
411 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
414 class TextureLayerMailboxHolderTest : public TextureLayerTest {
415 public:
416 TextureLayerMailboxHolderTest()
417 : main_thread_("MAIN") {
418 main_thread_.Start();
419 main_thread_.message_loop()->task_runner()->PostTask(
420 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain,
421 base::Unretained(this)));
422 Wait(main_thread_);
425 void Wait(const base::Thread& thread) {
426 bool manual_reset = false;
427 bool initially_signaled = false;
428 base::WaitableEvent event(manual_reset, initially_signaled);
429 thread.message_loop()->task_runner()->PostTask(
430 FROM_HERE,
431 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
432 event.Wait();
435 void CreateMainRef() {
436 main_ref_ = TestMailboxHolder::Create(
437 test_data_.mailbox1_,
438 SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass();
441 void ReleaseMainRef() { main_ref_ = nullptr; }
443 void CreateImplRef(scoped_ptr<SingleReleaseCallbackImpl>* impl_ref) {
444 *impl_ref = main_ref_->holder()->GetCallbackForImplThread();
447 void CapturePostTasksAndWait(base::WaitableEvent* begin_capture,
448 base::WaitableEvent* wait_for_capture,
449 base::WaitableEvent* stop_capture) {
450 begin_capture->Wait();
451 BlockingTaskRunner::CapturePostTasks capture(
452 main_thread_task_runner_.get());
453 wait_for_capture->Signal();
454 stop_capture->Wait();
457 protected:
458 void InitializeOnMain() {
459 main_thread_task_runner_ =
460 BlockingTaskRunner::Create(main_thread_.task_runner());
463 scoped_ptr<TestMailboxHolder::MainThreadReference>
464 main_ref_;
465 base::Thread main_thread_;
466 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
469 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) {
470 scoped_refptr<TextureLayer> test_layer =
471 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
472 ASSERT_TRUE(test_layer.get());
474 main_thread_.message_loop()->task_runner()->PostTask(
475 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
476 base::Unretained(this)));
478 Wait(main_thread_);
480 // The texture layer is attached to compositor1, and passes a reference to its
481 // impl tree.
482 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
483 main_thread_.message_loop()->task_runner()->PostTask(
484 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
485 base::Unretained(this), &compositor1));
487 // Then the texture layer is removed and attached to compositor2, and passes a
488 // reference to its impl tree.
489 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
490 main_thread_.message_loop()->task_runner()->PostTask(
491 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
492 base::Unretained(this), &compositor2));
494 Wait(main_thread_);
495 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
497 // The compositors both destroy their impl trees before the main thread layer
498 // is destroyed.
499 compositor1->Run(100, false, main_thread_task_runner_.get());
500 compositor2->Run(200, false, main_thread_task_runner_.get());
502 Wait(main_thread_);
504 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
505 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
507 // The main thread ref is the last one, so the mailbox is released back to the
508 // embedder, with the last sync point provided by the impl trees.
509 EXPECT_CALL(test_data_.mock_callback_,
510 Release(test_data_.mailbox_name1_, 200, false)).Times(1);
512 main_thread_.message_loop()->task_runner()->PostTask(
513 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
514 base::Unretained(this)));
515 Wait(main_thread_);
516 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
519 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) {
520 scoped_refptr<TextureLayer> test_layer =
521 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
522 ASSERT_TRUE(test_layer.get());
524 main_thread_.message_loop()->task_runner()->PostTask(
525 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
526 base::Unretained(this)));
528 Wait(main_thread_);
530 // The texture layer is attached to compositor1, and passes a reference to its
531 // impl tree.
532 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
533 main_thread_.message_loop()->task_runner()->PostTask(
534 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
535 base::Unretained(this), &compositor1));
537 // Then the texture layer is removed and attached to compositor2, and passes a
538 // reference to its impl tree.
539 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
540 main_thread_.message_loop()->task_runner()->PostTask(
541 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
542 base::Unretained(this), &compositor2));
544 Wait(main_thread_);
545 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
547 // One compositor destroys their impl tree.
548 compositor1->Run(100, false, main_thread_task_runner_.get());
550 // Then the main thread reference is destroyed.
551 main_thread_.message_loop()->task_runner()->PostTask(
552 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
553 base::Unretained(this)));
555 Wait(main_thread_);
557 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
558 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
560 // The second impl reference is destroyed last, causing the mailbox to be
561 // released back to the embedder with the last sync point from the impl tree.
562 EXPECT_CALL(test_data_.mock_callback_,
563 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
565 compositor2->Run(200, true, main_thread_task_runner_.get());
566 Wait(main_thread_);
567 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
570 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) {
571 scoped_refptr<TextureLayer> test_layer =
572 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
573 ASSERT_TRUE(test_layer.get());
575 main_thread_.message_loop()->task_runner()->PostTask(
576 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
577 base::Unretained(this)));
579 Wait(main_thread_);
581 // The texture layer is attached to compositor1, and passes a reference to its
582 // impl tree.
583 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
584 main_thread_.message_loop()->task_runner()->PostTask(
585 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
586 base::Unretained(this), &compositor1));
588 // Then the texture layer is removed and attached to compositor2, and passes a
589 // reference to its impl tree.
590 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
591 main_thread_.message_loop()->task_runner()->PostTask(
592 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
593 base::Unretained(this), &compositor2));
595 Wait(main_thread_);
596 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
598 // The main thread reference is destroyed first.
599 main_thread_.message_loop()->task_runner()->PostTask(
600 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
601 base::Unretained(this)));
603 // One compositor destroys their impl tree.
604 compositor2->Run(200, false, main_thread_task_runner_.get());
606 Wait(main_thread_);
608 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
609 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
611 // The second impl reference is destroyed last, causing the mailbox to be
612 // released back to the embedder with the last sync point from the impl tree.
613 EXPECT_CALL(test_data_.mock_callback_,
614 Release(test_data_.mailbox_name1_, 100, true)).Times(1);
616 compositor1->Run(100, true, main_thread_task_runner_.get());
617 Wait(main_thread_);
618 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
621 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) {
622 scoped_refptr<TextureLayer> test_layer =
623 TextureLayer::CreateForMailbox(layer_settings_, nullptr);
624 ASSERT_TRUE(test_layer.get());
626 main_thread_.message_loop()->task_runner()->PostTask(
627 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
628 base::Unretained(this)));
630 Wait(main_thread_);
632 // The texture layer is attached to compositor1, and passes a reference to its
633 // impl tree.
634 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
635 main_thread_.message_loop()->task_runner()->PostTask(
636 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
637 base::Unretained(this), &compositor1));
639 // Then the texture layer is removed and attached to compositor2, and passes a
640 // reference to its impl tree.
641 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
642 main_thread_.message_loop()->task_runner()->PostTask(
643 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
644 base::Unretained(this), &compositor2));
646 Wait(main_thread_);
647 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
649 // The main thread reference is destroyed first.
650 main_thread_.message_loop()->task_runner()->PostTask(
651 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
652 base::Unretained(this)));
654 EXPECT_CALL(test_data_.mock_callback_,
655 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
657 bool manual_reset = false;
658 bool initially_signaled = false;
659 base::WaitableEvent begin_capture(manual_reset, initially_signaled);
660 base::WaitableEvent wait_for_capture(manual_reset, initially_signaled);
661 base::WaitableEvent stop_capture(manual_reset, initially_signaled);
663 // Post a task to start capturing tasks on the main thread. This will block
664 // the main thread until we signal the |stop_capture| event.
665 main_thread_.message_loop()->task_runner()->PostTask(
666 FROM_HERE,
667 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait,
668 base::Unretained(this), &begin_capture, &wait_for_capture,
669 &stop_capture));
671 // Before the main thread capturing starts, one compositor destroys their
672 // impl reference. Since capturing did not start, this gets post-tasked to
673 // the main thread.
674 compositor1->Run(100, false, main_thread_task_runner_.get());
676 // Start capturing on the main thread.
677 begin_capture.Signal();
678 wait_for_capture.Wait();
680 // Meanwhile, the second compositor released its impl reference, but this task
681 // gets shortcutted directly to the main thread. This means the reference is
682 // released before compositor1, whose reference will be released later when
683 // the post-task is serviced. But since it was destroyed _on the impl thread_
684 // last, its sync point values should be used.
685 compositor2->Run(200, true, main_thread_task_runner_.get());
687 stop_capture.Signal();
688 Wait(main_thread_);
690 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
693 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest {
694 public:
695 TextureLayerImplWithMailboxThreadedCallback()
696 : callback_count_(0),
697 commit_count_(0) {}
699 // Make sure callback is received on main and doesn't block the impl thread.
700 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
701 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
702 EXPECT_FALSE(lost_resource);
703 ++callback_count_;
706 void SetMailbox(char mailbox_char) {
707 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
708 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
709 base::Bind(
710 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback,
711 base::Unretained(this)));
712 layer_->SetTextureMailbox(
713 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
714 callback.Pass());
717 void BeginTest() override {
718 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
720 gfx::Size bounds(100, 100);
721 root_ = Layer::Create(layer_settings());
722 root_->SetBounds(bounds);
724 layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr);
725 layer_->SetIsDrawable(true);
726 layer_->SetBounds(bounds);
728 root_->AddChild(layer_);
729 layer_tree_host()->SetRootLayer(root_);
730 layer_tree_host()->SetViewportSize(bounds);
731 SetMailbox('1');
732 EXPECT_EQ(0, callback_count_);
734 // Case #1: change mailbox before the commit. The old mailbox should be
735 // released immediately.
736 SetMailbox('2');
737 EXPECT_EQ(1, callback_count_);
738 PostSetNeedsCommitToMainThread();
741 void DidCommit() override {
742 ++commit_count_;
743 switch (commit_count_) {
744 case 1:
745 // Case #2: change mailbox after the commit (and draw), where the
746 // layer draws. The old mailbox should be released during the next
747 // commit.
748 SetMailbox('3');
749 EXPECT_EQ(1, callback_count_);
750 break;
751 case 2:
752 EXPECT_EQ(2, callback_count_);
753 // Case #3: change mailbox when the layer doesn't draw. The old
754 // mailbox should be released during the next commit.
755 layer_->SetBounds(gfx::Size());
756 SetMailbox('4');
757 break;
758 case 3:
759 EXPECT_EQ(3, callback_count_);
760 // Case #4: release mailbox that was committed but never drawn. The
761 // old mailbox should be released during the next commit.
762 layer_->SetTextureMailbox(TextureMailbox(), nullptr);
763 break;
764 case 4:
765 if (layer_tree_host()->settings().impl_side_painting) {
766 // With impl painting, the texture mailbox will still be on the impl
767 // thread when the commit finishes, because the layer is not drawble
768 // when it has no texture mailbox, and thus does not block the commit
769 // on activation. So, we wait for activation.
770 // TODO(danakj): fix this. crbug.com/277953
771 layer_tree_host()->SetNeedsCommit();
772 break;
773 } else {
774 ++commit_count_;
776 case 5:
777 EXPECT_EQ(4, callback_count_);
778 // Restore a mailbox for the next step.
779 SetMailbox('5');
780 break;
781 case 6:
782 // Case #5: remove layer from tree. Callback should *not* be called, the
783 // mailbox is returned to the main thread.
784 EXPECT_EQ(4, callback_count_);
785 layer_->RemoveFromParent();
786 break;
787 case 7:
788 if (layer_tree_host()->settings().impl_side_painting) {
789 // With impl painting, the texture mailbox will still be on the impl
790 // thread when the commit finishes, because the layer is not around to
791 // block the commit on activation anymore. So, we wait for activation.
792 // TODO(danakj): fix this. crbug.com/277953
793 layer_tree_host()->SetNeedsCommit();
794 break;
795 } else {
796 ++commit_count_;
798 case 8:
799 EXPECT_EQ(4, callback_count_);
800 // Resetting the mailbox will call the callback now.
801 layer_->SetTextureMailbox(TextureMailbox(), nullptr);
802 EXPECT_EQ(5, callback_count_);
803 EndTest();
804 break;
805 default:
806 NOTREACHED();
807 break;
811 void AfterTest() override {}
813 private:
814 base::ThreadChecker main_thread_;
815 int callback_count_;
816 int commit_count_;
817 scoped_refptr<Layer> root_;
818 scoped_refptr<TextureLayer> layer_;
821 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
822 TextureLayerImplWithMailboxThreadedCallback);
825 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
826 protected:
827 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
829 static void ReleaseCallback(uint32 sync_point, bool lost_resource) {}
831 void SetMailbox(char mailbox_char) {
832 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
833 base::Bind(
834 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
835 layer_->SetTextureMailbox(
836 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
837 callback.Pass());
840 void BeginTest() override {
841 gfx::Size bounds(100, 100);
842 root_ = Layer::Create(layer_settings());
843 root_->SetBounds(bounds);
845 layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr);
846 layer_->SetIsDrawable(true);
847 layer_->SetBounds(bounds);
849 root_->AddChild(layer_);
850 layer_tree_host()->SetRootLayer(root_);
851 layer_tree_host()->SetViewportSize(bounds);
852 SetMailbox('1');
854 PostSetNeedsCommitToMainThread();
857 void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
858 ++activate_count_;
861 void DidCommit() override {
862 switch (layer_tree_host()->source_frame_number()) {
863 case 1:
864 // The first mailbox has been activated. Set a new mailbox, and
865 // expect the next commit to finish *after* it is activated.
866 SetMailbox('2');
867 break;
868 case 2:
869 // The second mailbox has been activated. Remove the layer from
870 // the tree to cause another commit/activation. The commit should
871 // finish *after* the layer is removed from the active tree.
872 layer_->RemoveFromParent();
873 break;
874 case 3:
875 EndTest();
876 break;
880 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
881 switch (host_impl->active_tree()->source_frame_number()) {
882 case 0: {
883 // The activate for the 1st mailbox should have happened before now.
884 EXPECT_EQ(1, activate_count_);
885 break;
887 case 1: {
888 // The activate for the 2nd mailbox should have happened before now.
889 EXPECT_EQ(2, activate_count_);
890 break;
892 case 2: {
893 // The activate to remove the layer should have happened before now.
894 EXPECT_EQ(3, activate_count_);
895 break;
897 case 3: {
898 NOTREACHED();
899 break;
904 void AfterTest() override {}
906 int activate_count_;
907 scoped_refptr<Layer> root_;
908 scoped_refptr<TextureLayer> layer_;
911 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
912 TextureLayerMailboxIsActivatedDuringCommit);
914 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
915 protected:
916 TextureLayerImplWithMailboxTest()
917 : fake_client_(
918 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
920 void SetUp() override {
921 TextureLayerTest::SetUp();
922 layer_tree_host_ = MockLayerTreeHost::Create(&fake_client_);
923 EXPECT_TRUE(host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()));
926 bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
927 bool will_draw = layer->WillDraw(
928 mode, host_impl_.active_tree()->resource_provider());
929 if (will_draw)
930 layer->DidDraw(host_impl_.active_tree()->resource_provider());
931 return will_draw;
934 FakeLayerTreeHostClient fake_client_;
937 // Test conditions for results of TextureLayerImpl::WillDraw under
938 // different configurations of different mailbox, texture_id, and draw_mode.
939 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
940 EXPECT_CALL(
941 test_data_.mock_callback_,
942 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
943 .Times(AnyNumber());
944 EXPECT_CALL(test_data_.mock_callback_,
945 ReleaseImpl2(test_data_.shared_bitmap_.get(), 0, false, _))
946 .Times(AnyNumber());
947 // Hardware mode.
949 scoped_ptr<TextureLayerImpl> impl_layer =
950 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
951 impl_layer->SetTextureMailbox(
952 test_data_.mailbox1_,
953 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
954 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
958 scoped_ptr<TextureLayerImpl> impl_layer =
959 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
960 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
961 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
965 // Software resource.
966 scoped_ptr<TextureLayerImpl> impl_layer =
967 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
968 impl_layer->SetTextureMailbox(
969 test_data_.mailbox3_,
970 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
971 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
974 // Software mode.
976 scoped_ptr<TextureLayerImpl> impl_layer =
977 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
978 impl_layer->SetTextureMailbox(
979 test_data_.mailbox1_,
980 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
981 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
985 scoped_ptr<TextureLayerImpl> impl_layer =
986 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
987 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
988 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
992 // Software resource.
993 scoped_ptr<TextureLayerImpl> impl_layer =
994 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
995 impl_layer->SetTextureMailbox(
996 test_data_.mailbox3_,
997 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
998 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1001 // Resourceless software mode.
1003 scoped_ptr<TextureLayerImpl> impl_layer =
1004 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1005 impl_layer->SetTextureMailbox(
1006 test_data_.mailbox1_,
1007 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1008 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
1012 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
1013 host_impl_.CreatePendingTree();
1014 scoped_ptr<TextureLayerImpl> pending_layer;
1015 pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1);
1016 ASSERT_TRUE(pending_layer);
1018 scoped_ptr<LayerImpl> active_layer(
1019 pending_layer->CreateLayerImpl(host_impl_.active_tree()));
1020 ASSERT_TRUE(active_layer);
1022 pending_layer->SetTextureMailbox(
1023 test_data_.mailbox1_,
1024 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1026 // Test multiple commits without an activation.
1027 EXPECT_CALL(
1028 test_data_.mock_callback_,
1029 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
1030 .Times(1);
1031 pending_layer->SetTextureMailbox(
1032 test_data_.mailbox2_,
1033 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox2_impl_));
1034 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1036 // Test callback after activation.
1037 pending_layer->PushPropertiesTo(active_layer.get());
1038 active_layer->DidBecomeActive();
1040 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1041 pending_layer->SetTextureMailbox(
1042 test_data_.mailbox1_,
1043 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1044 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1046 EXPECT_CALL(test_data_.mock_callback_,
1047 ReleaseImpl(test_data_.mailbox_name2_, _, false, _)).Times(1);
1048 pending_layer->PushPropertiesTo(active_layer.get());
1049 active_layer->DidBecomeActive();
1050 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1052 // Test resetting the mailbox.
1053 EXPECT_CALL(test_data_.mock_callback_,
1054 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1055 pending_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1056 pending_layer->PushPropertiesTo(active_layer.get());
1057 active_layer->DidBecomeActive();
1058 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1060 // Test destructor.
1061 EXPECT_CALL(
1062 test_data_.mock_callback_,
1063 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
1064 .Times(1);
1065 pending_layer->SetTextureMailbox(
1066 test_data_.mailbox1_,
1067 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1070 TEST_F(TextureLayerImplWithMailboxTest,
1071 TestDestructorCallbackOnCreatedResource) {
1072 scoped_ptr<TextureLayerImpl> impl_layer;
1073 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1074 ASSERT_TRUE(impl_layer);
1076 EXPECT_CALL(test_data_.mock_callback_,
1077 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1078 impl_layer->SetTextureMailbox(
1079 test_data_.mailbox1_,
1080 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1081 impl_layer->DidBecomeActive();
1082 EXPECT_TRUE(impl_layer->WillDraw(
1083 DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1084 impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1085 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1088 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1089 ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1090 ResourceId id = provider->CreateResourceFromTextureMailbox(
1091 test_data_.mailbox1_,
1092 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1093 provider->AllocateForTesting(id);
1095 // Transfer some resources to the parent.
1096 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1097 resource_ids_to_transfer.push_back(id);
1098 TransferableResourceArray list;
1099 provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1100 EXPECT_TRUE(provider->InUseByConsumer(id));
1101 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1102 provider->DeleteResource(id);
1103 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1104 EXPECT_CALL(test_data_.mock_callback_,
1105 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1106 ReturnedResourceArray returned;
1107 TransferableResource::ReturnResources(list, &returned);
1108 provider->ReceiveReturnsFromParent(returned);
1111 // Checks that TextureLayer::Update does not cause an extra commit when setting
1112 // the texture mailbox.
1113 class TextureLayerNoExtraCommitForMailboxTest
1114 : public LayerTreeTest,
1115 public TextureLayerClient {
1116 public:
1117 // TextureLayerClient implementation.
1118 bool PrepareTextureMailbox(
1119 TextureMailbox* texture_mailbox,
1120 scoped_ptr<SingleReleaseCallback>* release_callback,
1121 bool use_shared_memory) override {
1122 if (layer_tree_host()->source_frame_number() == 1) {
1123 // Once this has been committed, the mailbox will be released.
1124 *texture_mailbox = TextureMailbox();
1125 return true;
1128 *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1129 *release_callback = SingleReleaseCallback::Create(
1130 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1131 base::Unretained(this)));
1132 return true;
1135 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1136 // Source frame number during callback is the same as the source frame
1137 // on which it was released.
1138 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1139 EndTest();
1142 void SetupTree() override {
1143 scoped_refptr<Layer> root = Layer::Create(layer_settings());
1144 root->SetBounds(gfx::Size(10, 10));
1145 root->SetIsDrawable(true);
1147 texture_layer_ = TextureLayer::CreateForMailbox(layer_settings(), this);
1148 texture_layer_->SetBounds(gfx::Size(10, 10));
1149 texture_layer_->SetIsDrawable(true);
1150 root->AddChild(texture_layer_);
1152 layer_tree_host()->SetRootLayer(root);
1153 LayerTreeTest::SetupTree();
1156 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1158 void DidCommitAndDrawFrame() override {
1159 switch (layer_tree_host()->source_frame_number()) {
1160 case 1:
1161 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1162 // Invalidate the texture layer to clear the mailbox before
1163 // ending the test.
1164 texture_layer_->SetNeedsDisplay();
1165 break;
1166 case 2:
1167 break;
1168 default:
1169 NOTREACHED();
1170 break;
1174 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1175 ASSERT_TRUE(result);
1176 DelegatedFrameData* delegated_frame_data =
1177 output_surface()->last_sent_frame().delegated_frame_data.get();
1178 if (!delegated_frame_data)
1179 return;
1181 // Return all resources immediately.
1182 TransferableResourceArray resources_to_return =
1183 output_surface()->resources_held_by_parent();
1185 CompositorFrameAck ack;
1186 for (size_t i = 0; i < resources_to_return.size(); ++i)
1187 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1188 host_impl->ReclaimResources(&ack);
1191 void AfterTest() override {}
1193 private:
1194 scoped_refptr<TextureLayer> texture_layer_;
1197 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1199 // Checks that changing a mailbox in the client for a TextureLayer that's
1200 // invisible correctly works and uses the new mailbox as soon as the layer
1201 // becomes visible (and returns the old one).
1202 class TextureLayerChangeInvisibleMailboxTest
1203 : public LayerTreeTest,
1204 public TextureLayerClient {
1205 public:
1206 TextureLayerChangeInvisibleMailboxTest()
1207 : mailbox_changed_(true),
1208 mailbox_returned_(0),
1209 prepare_called_(0),
1210 commit_count_(0) {
1211 mailbox_ = MakeMailbox('1');
1214 // TextureLayerClient implementation.
1215 bool PrepareTextureMailbox(
1216 TextureMailbox* mailbox,
1217 scoped_ptr<SingleReleaseCallback>* release_callback,
1218 bool use_shared_memory) override {
1219 ++prepare_called_;
1220 if (!mailbox_changed_)
1221 return false;
1222 *mailbox = mailbox_;
1223 *release_callback = SingleReleaseCallback::Create(
1224 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1225 base::Unretained(this)));
1226 return true;
1229 TextureMailbox MakeMailbox(char name) {
1230 return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0);
1233 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1234 ++mailbox_returned_;
1237 void SetupTree() override {
1238 scoped_refptr<Layer> root = Layer::Create(layer_settings());
1239 root->SetBounds(gfx::Size(10, 10));
1240 root->SetIsDrawable(true);
1242 solid_layer_ = SolidColorLayer::Create(layer_settings());
1243 solid_layer_->SetBounds(gfx::Size(10, 10));
1244 solid_layer_->SetIsDrawable(true);
1245 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1246 root->AddChild(solid_layer_);
1248 parent_layer_ = Layer::Create(layer_settings());
1249 parent_layer_->SetBounds(gfx::Size(10, 10));
1250 parent_layer_->SetIsDrawable(true);
1251 root->AddChild(parent_layer_);
1253 texture_layer_ = TextureLayer::CreateForMailbox(layer_settings(), this);
1254 texture_layer_->SetBounds(gfx::Size(10, 10));
1255 texture_layer_->SetIsDrawable(true);
1256 parent_layer_->AddChild(texture_layer_);
1258 layer_tree_host()->SetRootLayer(root);
1259 LayerTreeTest::SetupTree();
1262 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1264 void DidCommitAndDrawFrame() override {
1265 ++commit_count_;
1266 switch (commit_count_) {
1267 case 1:
1268 // We should have updated the layer, committing the texture.
1269 EXPECT_EQ(1, prepare_called_);
1270 // Make layer invisible.
1271 parent_layer_->SetOpacity(0.f);
1272 break;
1273 case 2:
1274 // Layer shouldn't have been updated.
1275 EXPECT_EQ(1, prepare_called_);
1276 // Change the texture.
1277 mailbox_ = MakeMailbox('2');
1278 mailbox_changed_ = true;
1279 texture_layer_->SetNeedsDisplay();
1280 // Force a change to make sure we draw a frame.
1281 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1282 break;
1283 case 3:
1284 // Layer shouldn't have been updated.
1285 EXPECT_EQ(1, prepare_called_);
1286 // So the old mailbox isn't returned yet.
1287 EXPECT_EQ(0, mailbox_returned_);
1288 // Make layer visible again.
1289 parent_layer_->SetOpacity(1.f);
1290 break;
1291 case 4:
1292 // Layer should have been updated.
1293 EXPECT_EQ(2, prepare_called_);
1294 // So the old mailbox should have been returned already.
1295 EXPECT_EQ(1, mailbox_returned_);
1296 texture_layer_->ClearClient();
1297 break;
1298 case 5:
1299 EXPECT_EQ(2, mailbox_returned_);
1300 EndTest();
1301 break;
1302 default:
1303 NOTREACHED();
1304 break;
1308 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1309 ASSERT_TRUE(result);
1310 DelegatedFrameData* delegated_frame_data =
1311 output_surface()->last_sent_frame().delegated_frame_data.get();
1312 if (!delegated_frame_data)
1313 return;
1315 // Return all resources immediately.
1316 TransferableResourceArray resources_to_return =
1317 output_surface()->resources_held_by_parent();
1319 CompositorFrameAck ack;
1320 for (size_t i = 0; i < resources_to_return.size(); ++i)
1321 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1322 host_impl->ReclaimResources(&ack);
1325 void AfterTest() override {}
1327 private:
1328 scoped_refptr<SolidColorLayer> solid_layer_;
1329 scoped_refptr<Layer> parent_layer_;
1330 scoped_refptr<TextureLayer> texture_layer_;
1332 // Used on the main thread.
1333 bool mailbox_changed_;
1334 TextureMailbox mailbox_;
1335 int mailbox_returned_;
1336 int prepare_called_;
1337 int commit_count_;
1340 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1342 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1343 // the mailbox back to TextureLayerClient.
1344 class TextureLayerReleaseResourcesBase
1345 : public LayerTreeTest,
1346 public TextureLayerClient {
1347 public:
1348 // TextureLayerClient implementation.
1349 bool PrepareTextureMailbox(
1350 TextureMailbox* mailbox,
1351 scoped_ptr<SingleReleaseCallback>* release_callback,
1352 bool use_shared_memory) override {
1353 *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1354 *release_callback = SingleReleaseCallback::Create(
1355 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1356 base::Unretained(this)));
1357 return true;
1360 void MailboxReleased(unsigned sync_point, bool lost_resource) {
1361 mailbox_released_ = true;
1364 void SetupTree() override {
1365 LayerTreeTest::SetupTree();
1367 scoped_refptr<TextureLayer> texture_layer =
1368 TextureLayer::CreateForMailbox(layer_settings(), this);
1369 texture_layer->SetBounds(gfx::Size(10, 10));
1370 texture_layer->SetIsDrawable(true);
1372 layer_tree_host()->root_layer()->AddChild(texture_layer);
1375 void BeginTest() override {
1376 mailbox_released_ = false;
1377 PostSetNeedsCommitToMainThread();
1380 void DidCommitAndDrawFrame() override { EndTest(); }
1382 void AfterTest() override { EXPECT_TRUE(mailbox_released_); }
1384 private:
1385 bool mailbox_released_;
1388 class TextureLayerReleaseResourcesAfterCommit
1389 : public TextureLayerReleaseResourcesBase {
1390 public:
1391 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
1392 LayerTreeImpl* tree = nullptr;
1393 tree = host_impl->sync_tree();
1394 tree->root_layer()->children()[0]->ReleaseResources();
1398 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1400 class TextureLayerReleaseResourcesAfterActivate
1401 : public TextureLayerReleaseResourcesBase {
1402 public:
1403 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
1404 host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
1408 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
1410 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
1411 public:
1412 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1413 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1414 EXPECT_FALSE(lost_resource);
1415 ++callback_count_;
1416 EndTest();
1419 void SetMailbox(char mailbox_char) {
1420 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1421 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1422 base::Bind(
1423 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
1424 base::Unretained(this)));
1425 layer_->SetTextureMailbox(
1426 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1427 callback.Pass());
1430 void SetupTree() override {
1431 gfx::Size bounds(100, 100);
1432 root_ = Layer::Create(layer_settings());
1433 root_->SetBounds(bounds);
1435 layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr);
1436 layer_->SetIsDrawable(true);
1437 layer_->SetBounds(bounds);
1439 root_->AddChild(layer_);
1440 layer_tree_host()->SetRootLayer(root_);
1441 layer_tree_host()->SetViewportSize(bounds);
1444 void BeginTest() override {
1445 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1447 callback_count_ = 0;
1449 // Set the mailbox on the main thread.
1450 SetMailbox('1');
1451 EXPECT_EQ(0, callback_count_);
1453 PostSetNeedsCommitToMainThread();
1456 void DidCommitAndDrawFrame() override {
1457 switch (layer_tree_host()->source_frame_number()) {
1458 case 1:
1459 // Delete the TextureLayer on the main thread while the mailbox is in
1460 // the impl tree.
1461 layer_->RemoveFromParent();
1462 layer_ = nullptr;
1463 break;
1467 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1469 private:
1470 base::ThreadChecker main_thread_;
1471 int callback_count_;
1472 scoped_refptr<Layer> root_;
1473 scoped_refptr<TextureLayer> layer_;
1476 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1477 TextureLayerWithMailboxMainThreadDeleted);
1479 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
1480 public:
1481 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1482 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1483 EXPECT_FALSE(lost_resource);
1484 ++callback_count_;
1485 EndTest();
1488 void SetMailbox(char mailbox_char) {
1489 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1490 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1491 base::Bind(
1492 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
1493 base::Unretained(this)));
1494 layer_->SetTextureMailbox(
1495 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1496 callback.Pass());
1499 void SetupTree() override {
1500 gfx::Size bounds(100, 100);
1501 root_ = Layer::Create(layer_settings());
1502 root_->SetBounds(bounds);
1504 layer_ = TextureLayer::CreateForMailbox(layer_settings(), nullptr);
1505 layer_->SetIsDrawable(true);
1506 layer_->SetBounds(bounds);
1508 root_->AddChild(layer_);
1509 layer_tree_host()->SetRootLayer(root_);
1510 layer_tree_host()->SetViewportSize(bounds);
1513 void BeginTest() override {
1514 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1516 callback_count_ = 0;
1518 // Set the mailbox on the main thread.
1519 SetMailbox('1');
1520 EXPECT_EQ(0, callback_count_);
1522 PostSetNeedsCommitToMainThread();
1525 void DidCommitAndDrawFrame() override {
1526 switch (layer_tree_host()->source_frame_number()) {
1527 case 1:
1528 // Remove the TextureLayer on the main thread while the mailbox is in
1529 // the impl tree, but don't delete the TextureLayer until after the impl
1530 // tree side is deleted.
1531 layer_->RemoveFromParent();
1532 break;
1533 case 2:
1534 layer_ = nullptr;
1535 break;
1539 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1541 private:
1542 base::ThreadChecker main_thread_;
1543 int callback_count_;
1544 scoped_refptr<Layer> root_;
1545 scoped_refptr<TextureLayer> layer_;
1548 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1549 TextureLayerWithMailboxImplThreadDeleted);
1551 } // namespace
1552 } // namespace cc