Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / cc / layers / texture_layer_unittest.cc
blob3bd90ec5782195eeb21c197ace139f70057bdb83
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 explicit MockLayerTreeHost(FakeLayerTreeHostClient* client)
58 : LayerTreeHost(client, nullptr, nullptr, nullptr, LayerTreeSettings()) {
59 InitializeSingleThreaded(client, base::ThreadTaskRunnerHandle::Get(),
60 nullptr);
63 MOCK_METHOD0(SetNeedsCommit, void());
64 MOCK_METHOD0(SetNeedsUpdateLayers, void());
65 MOCK_METHOD0(StartRateLimiter, void());
66 MOCK_METHOD0(StopRateLimiter, void());
69 class FakeTextureLayerClient : public TextureLayerClient {
70 public:
71 FakeTextureLayerClient() : mailbox_changed_(true) {}
73 bool PrepareTextureMailbox(
74 TextureMailbox* mailbox,
75 scoped_ptr<SingleReleaseCallback>* release_callback,
76 bool use_shared_memory) override {
77 if (!mailbox_changed_)
78 return false;
80 *mailbox = mailbox_;
81 *release_callback = release_callback_.Pass();
82 mailbox_changed_ = false;
83 return true;
86 void set_mailbox(const TextureMailbox& mailbox,
87 scoped_ptr<SingleReleaseCallback> release_callback) {
88 mailbox_ = mailbox;
89 release_callback_ = release_callback.Pass();
90 mailbox_changed_ = true;
93 private:
94 TextureMailbox mailbox_;
95 scoped_ptr<SingleReleaseCallback> release_callback_;
96 bool mailbox_changed_;
97 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient);
100 class MockMailboxCallback {
101 public:
102 MOCK_METHOD3(Release,
103 void(const gpu::Mailbox& mailbox,
104 uint32 sync_point,
105 bool lost_resource));
106 MOCK_METHOD3(Release2,
107 void(SharedBitmap* shared_bitmap,
108 uint32 sync_point,
109 bool lost_resource));
110 MOCK_METHOD4(ReleaseImpl,
111 void(const gpu::Mailbox& mailbox,
112 uint32 sync_point,
113 bool lost_resource,
114 BlockingTaskRunner* main_thread_task_runner));
115 MOCK_METHOD4(ReleaseImpl2,
116 void(SharedBitmap* shared_bitmap,
117 uint32 sync_point,
118 bool lost_resource,
119 BlockingTaskRunner* main_thread_task_runner));
122 struct CommonMailboxObjects {
123 explicit CommonMailboxObjects(SharedBitmapManager* manager)
124 : mailbox_name1_(MailboxFromChar('1')),
125 mailbox_name2_(MailboxFromChar('2')),
126 sync_point1_(1),
127 sync_point2_(2) {
128 release_mailbox1_ = base::Bind(&MockMailboxCallback::Release,
129 base::Unretained(&mock_callback_),
130 mailbox_name1_);
131 release_mailbox2_ = base::Bind(&MockMailboxCallback::Release,
132 base::Unretained(&mock_callback_),
133 mailbox_name2_);
134 release_mailbox1_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl,
135 base::Unretained(&mock_callback_),
136 mailbox_name1_);
137 release_mailbox2_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl,
138 base::Unretained(&mock_callback_),
139 mailbox_name2_);
140 const uint32 arbitrary_target1 = GL_TEXTURE_2D;
141 const uint32 arbitrary_target2 = GL_TEXTURE_EXTERNAL_OES;
142 mailbox1_ = TextureMailbox(mailbox_name1_, arbitrary_target1, sync_point1_);
143 mailbox2_ = TextureMailbox(mailbox_name2_, arbitrary_target2, sync_point2_);
144 gfx::Size size(128, 128);
145 shared_bitmap_ = manager->AllocateSharedBitmap(size);
146 DCHECK(shared_bitmap_);
147 release_mailbox3_ =
148 base::Bind(&MockMailboxCallback::Release2,
149 base::Unretained(&mock_callback_), shared_bitmap_.get());
150 release_mailbox3_impl_ =
151 base::Bind(&MockMailboxCallback::ReleaseImpl2,
152 base::Unretained(&mock_callback_), shared_bitmap_.get());
153 mailbox3_ = TextureMailbox(shared_bitmap_.get(), size);
156 gpu::Mailbox mailbox_name1_;
157 gpu::Mailbox mailbox_name2_;
158 MockMailboxCallback mock_callback_;
159 ReleaseCallback release_mailbox1_;
160 ReleaseCallback release_mailbox2_;
161 ReleaseCallback release_mailbox3_;
162 ReleaseCallbackImpl release_mailbox1_impl_;
163 ReleaseCallbackImpl release_mailbox2_impl_;
164 ReleaseCallbackImpl release_mailbox3_impl_;
165 TextureMailbox mailbox1_;
166 TextureMailbox mailbox2_;
167 TextureMailbox mailbox3_;
168 uint32 sync_point1_;
169 uint32 sync_point2_;
170 scoped_ptr<SharedBitmap> shared_bitmap_;
173 class TextureLayerTest : public testing::Test {
174 public:
175 TextureLayerTest()
176 : fake_client_(
177 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
178 host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_),
179 test_data_(&shared_bitmap_manager_) {}
181 protected:
182 void SetUp() override {
183 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
184 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
185 layer_tree_host_->SetViewportSize(gfx::Size(10, 10));
186 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
189 void TearDown() override {
190 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
191 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
193 layer_tree_host_->SetRootLayer(nullptr);
194 layer_tree_host_ = nullptr;
197 scoped_ptr<MockLayerTreeHost> layer_tree_host_;
198 FakeImplProxy proxy_;
199 FakeLayerTreeHostClient fake_client_;
200 TestSharedBitmapManager shared_bitmap_manager_;
201 TestTaskGraphRunner task_graph_runner_;
202 FakeLayerTreeHostImpl host_impl_;
203 CommonMailboxObjects test_data_;
206 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) {
207 scoped_refptr<TextureLayer> test_layer =
208 TextureLayer::CreateForMailbox(nullptr);
209 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer));
211 // Test properties that should call SetNeedsCommit. All properties need to
212 // be set to new values in order for SetNeedsCommit to be called.
213 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false));
214 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetNearestNeighbor(true));
215 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV(
216 gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f)));
217 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity(
218 0.5f, 0.5f, 0.5f, 0.5f));
219 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false));
220 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true));
223 TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) {
224 const gfx::Size layer_bounds(100, 100);
225 const gfx::Rect layer_rect(layer_bounds);
226 const Region layer_region(layer_rect);
228 scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(nullptr);
229 layer->SetBounds(layer_bounds);
230 layer->draw_properties().visible_content_rect = layer_rect;
231 layer->SetBlendBackgroundColor(true);
233 // Verify initial conditions.
234 EXPECT_FALSE(layer->contents_opaque());
235 EXPECT_EQ(0u, layer->background_color());
236 EXPECT_EQ(Region().ToString(),
237 layer->VisibleContentOpaqueRegion().ToString());
239 // Opaque background.
240 layer->SetBackgroundColor(SK_ColorWHITE);
241 EXPECT_EQ(layer_region.ToString(),
242 layer->VisibleContentOpaqueRegion().ToString());
244 // Transparent background.
245 layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
246 EXPECT_EQ(Region().ToString(),
247 layer->VisibleContentOpaqueRegion().ToString());
250 TEST_F(TextureLayerTest, RateLimiter) {
251 FakeTextureLayerClient client;
252 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(
253 &client);
254 test_layer->SetIsDrawable(true);
255 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
256 layer_tree_host_->SetRootLayer(test_layer);
258 // Don't rate limit until we invalidate.
259 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
260 test_layer->SetRateLimitContext(true);
261 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
263 // Do rate limit after we invalidate.
264 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
265 test_layer->SetNeedsDisplay();
266 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
268 // Stop rate limiter when we don't want it any more.
269 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
270 test_layer->SetRateLimitContext(false);
271 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
273 // Or we clear the client.
274 test_layer->SetRateLimitContext(true);
275 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
276 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
277 test_layer->ClearClient();
278 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
280 // Reset to a layer with a client, that started the rate limiter.
281 test_layer = TextureLayer::CreateForMailbox(
282 &client);
283 test_layer->SetIsDrawable(true);
284 test_layer->SetRateLimitContext(true);
285 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
286 layer_tree_host_->SetRootLayer(test_layer);
287 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
288 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
289 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
290 test_layer->SetNeedsDisplay();
291 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
293 // Stop rate limiter when we're removed from the tree.
294 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
295 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
296 layer_tree_host_->SetRootLayer(nullptr);
297 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
300 class TestMailboxHolder : public TextureLayer::TextureMailboxHolder {
301 public:
302 using TextureLayer::TextureMailboxHolder::Create;
304 protected:
305 ~TestMailboxHolder() override {}
308 class TextureLayerWithMailboxTest : public TextureLayerTest {
309 protected:
310 void TearDown() override {
311 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
312 EXPECT_CALL(test_data_.mock_callback_,
313 Release(test_data_.mailbox_name1_,
314 test_data_.sync_point1_,
315 false)).Times(1);
316 TextureLayerTest::TearDown();
320 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
321 scoped_refptr<TextureLayer> test_layer =
322 TextureLayer::CreateForMailbox(nullptr);
323 ASSERT_TRUE(test_layer.get());
325 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
326 layer_tree_host_->SetRootLayer(test_layer);
327 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
329 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
330 test_layer->SetTextureMailbox(
331 test_data_.mailbox1_,
332 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
333 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
335 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
336 EXPECT_CALL(test_data_.mock_callback_,
337 Release(test_data_.mailbox_name1_,
338 test_data_.sync_point1_,
339 false))
340 .Times(1);
341 test_layer->SetTextureMailbox(
342 test_data_.mailbox2_,
343 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
344 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
345 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
347 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
348 EXPECT_CALL(test_data_.mock_callback_,
349 Release(test_data_.mailbox_name2_,
350 test_data_.sync_point2_,
351 false))
352 .Times(1);
353 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
354 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
355 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
357 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
358 test_layer->SetTextureMailbox(
359 test_data_.mailbox3_,
360 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
361 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
362 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
364 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
365 EXPECT_CALL(test_data_.mock_callback_,
366 Release2(test_data_.shared_bitmap_.get(), 0, false)).Times(1);
367 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
368 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
369 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
371 // Test destructor.
372 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
373 test_layer->SetTextureMailbox(
374 test_data_.mailbox1_,
375 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
378 TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) {
379 scoped_refptr<TextureLayer> test_layer =
380 TextureLayer::CreateForMailbox(nullptr);
381 ASSERT_TRUE(test_layer.get());
383 // These use the same gpu::Mailbox, but different sync points.
384 TextureMailbox mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D, 1);
385 TextureMailbox mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D, 2);
387 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
388 layer_tree_host_->SetRootLayer(test_layer);
389 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
391 // Set the mailbox the first time. It should cause a commit.
392 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
393 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox1);
394 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
396 // Set the mailbox again with a new sync point, as the backing texture has
397 // been updated. It should cause a new commit.
398 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
399 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox2);
400 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
403 class TextureLayerMailboxHolderTest : public TextureLayerTest {
404 public:
405 TextureLayerMailboxHolderTest()
406 : main_thread_("MAIN") {
407 main_thread_.Start();
408 main_thread_.message_loop()->task_runner()->PostTask(
409 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain,
410 base::Unretained(this)));
411 Wait(main_thread_);
414 void Wait(const base::Thread& thread) {
415 bool manual_reset = false;
416 bool initially_signaled = false;
417 base::WaitableEvent event(manual_reset, initially_signaled);
418 thread.message_loop()->task_runner()->PostTask(
419 FROM_HERE,
420 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
421 event.Wait();
424 void CreateMainRef() {
425 main_ref_ = TestMailboxHolder::Create(
426 test_data_.mailbox1_,
427 SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass();
430 void ReleaseMainRef() { main_ref_ = nullptr; }
432 void CreateImplRef(scoped_ptr<SingleReleaseCallbackImpl>* impl_ref) {
433 *impl_ref = main_ref_->holder()->GetCallbackForImplThread();
436 void CapturePostTasksAndWait(base::WaitableEvent* begin_capture,
437 base::WaitableEvent* wait_for_capture,
438 base::WaitableEvent* stop_capture) {
439 begin_capture->Wait();
440 BlockingTaskRunner::CapturePostTasks capture(
441 main_thread_task_runner_.get());
442 wait_for_capture->Signal();
443 stop_capture->Wait();
446 protected:
447 void InitializeOnMain() {
448 main_thread_task_runner_ =
449 BlockingTaskRunner::Create(main_thread_.task_runner());
452 scoped_ptr<TestMailboxHolder::MainThreadReference>
453 main_ref_;
454 base::Thread main_thread_;
455 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
458 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) {
459 scoped_refptr<TextureLayer> test_layer =
460 TextureLayer::CreateForMailbox(nullptr);
461 ASSERT_TRUE(test_layer.get());
463 main_thread_.message_loop()->task_runner()->PostTask(
464 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
465 base::Unretained(this)));
467 Wait(main_thread_);
469 // The texture layer is attached to compositor1, and passes a reference to its
470 // impl tree.
471 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
472 main_thread_.message_loop()->task_runner()->PostTask(
473 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
474 base::Unretained(this), &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()->task_runner()->PostTask(
480 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
481 base::Unretained(this), &compositor2));
483 Wait(main_thread_);
484 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
486 // The compositors both destroy their impl trees before the main thread layer
487 // is destroyed.
488 compositor1->Run(100, false, main_thread_task_runner_.get());
489 compositor2->Run(200, false, main_thread_task_runner_.get());
491 Wait(main_thread_);
493 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
494 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
496 // The main thread ref is the last one, so the mailbox is released back to the
497 // embedder, with the last sync point provided by the impl trees.
498 EXPECT_CALL(test_data_.mock_callback_,
499 Release(test_data_.mailbox_name1_, 200, false)).Times(1);
501 main_thread_.message_loop()->task_runner()->PostTask(
502 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
503 base::Unretained(this)));
504 Wait(main_thread_);
505 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
508 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) {
509 scoped_refptr<TextureLayer> test_layer =
510 TextureLayer::CreateForMailbox(nullptr);
511 ASSERT_TRUE(test_layer.get());
513 main_thread_.message_loop()->task_runner()->PostTask(
514 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
515 base::Unretained(this)));
517 Wait(main_thread_);
519 // The texture layer is attached to compositor1, and passes a reference to its
520 // impl tree.
521 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
522 main_thread_.message_loop()->task_runner()->PostTask(
523 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
524 base::Unretained(this), &compositor1));
526 // Then the texture layer is removed and attached to compositor2, and passes a
527 // reference to its impl tree.
528 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
529 main_thread_.message_loop()->task_runner()->PostTask(
530 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
531 base::Unretained(this), &compositor2));
533 Wait(main_thread_);
534 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
536 // One compositor destroys their impl tree.
537 compositor1->Run(100, false, main_thread_task_runner_.get());
539 // Then the main thread reference is destroyed.
540 main_thread_.message_loop()->task_runner()->PostTask(
541 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
542 base::Unretained(this)));
544 Wait(main_thread_);
546 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
547 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
549 // The second impl reference is destroyed last, causing the mailbox to be
550 // released back to the embedder with the last sync point from the impl tree.
551 EXPECT_CALL(test_data_.mock_callback_,
552 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
554 compositor2->Run(200, true, main_thread_task_runner_.get());
555 Wait(main_thread_);
556 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
559 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) {
560 scoped_refptr<TextureLayer> test_layer =
561 TextureLayer::CreateForMailbox(nullptr);
562 ASSERT_TRUE(test_layer.get());
564 main_thread_.message_loop()->task_runner()->PostTask(
565 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
566 base::Unretained(this)));
568 Wait(main_thread_);
570 // The texture layer is attached to compositor1, and passes a reference to its
571 // impl tree.
572 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
573 main_thread_.message_loop()->task_runner()->PostTask(
574 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
575 base::Unretained(this), &compositor1));
577 // Then the texture layer is removed and attached to compositor2, and passes a
578 // reference to its impl tree.
579 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
580 main_thread_.message_loop()->task_runner()->PostTask(
581 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
582 base::Unretained(this), &compositor2));
584 Wait(main_thread_);
585 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
587 // The main thread reference is destroyed first.
588 main_thread_.message_loop()->task_runner()->PostTask(
589 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
590 base::Unretained(this)));
592 // One compositor destroys their impl tree.
593 compositor2->Run(200, false, main_thread_task_runner_.get());
595 Wait(main_thread_);
597 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
598 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
600 // The second impl reference is destroyed last, causing the mailbox to be
601 // released back to the embedder with the last sync point from the impl tree.
602 EXPECT_CALL(test_data_.mock_callback_,
603 Release(test_data_.mailbox_name1_, 100, true)).Times(1);
605 compositor1->Run(100, true, main_thread_task_runner_.get());
606 Wait(main_thread_);
607 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
610 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) {
611 scoped_refptr<TextureLayer> test_layer =
612 TextureLayer::CreateForMailbox(nullptr);
613 ASSERT_TRUE(test_layer.get());
615 main_thread_.message_loop()->task_runner()->PostTask(
616 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
617 base::Unretained(this)));
619 Wait(main_thread_);
621 // The texture layer is attached to compositor1, and passes a reference to its
622 // impl tree.
623 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
624 main_thread_.message_loop()->task_runner()->PostTask(
625 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
626 base::Unretained(this), &compositor1));
628 // Then the texture layer is removed and attached to compositor2, and passes a
629 // reference to its impl tree.
630 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
631 main_thread_.message_loop()->task_runner()->PostTask(
632 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
633 base::Unretained(this), &compositor2));
635 Wait(main_thread_);
636 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
638 // The main thread reference is destroyed first.
639 main_thread_.message_loop()->task_runner()->PostTask(
640 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
641 base::Unretained(this)));
643 EXPECT_CALL(test_data_.mock_callback_,
644 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
646 bool manual_reset = false;
647 bool initially_signaled = false;
648 base::WaitableEvent begin_capture(manual_reset, initially_signaled);
649 base::WaitableEvent wait_for_capture(manual_reset, initially_signaled);
650 base::WaitableEvent stop_capture(manual_reset, initially_signaled);
652 // Post a task to start capturing tasks on the main thread. This will block
653 // the main thread until we signal the |stop_capture| event.
654 main_thread_.message_loop()->task_runner()->PostTask(
655 FROM_HERE,
656 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait,
657 base::Unretained(this), &begin_capture, &wait_for_capture,
658 &stop_capture));
660 // Before the main thread capturing starts, one compositor destroys their
661 // impl reference. Since capturing did not start, this gets post-tasked to
662 // the main thread.
663 compositor1->Run(100, false, main_thread_task_runner_.get());
665 // Start capturing on the main thread.
666 begin_capture.Signal();
667 wait_for_capture.Wait();
669 // Meanwhile, the second compositor released its impl reference, but this task
670 // gets shortcutted directly to the main thread. This means the reference is
671 // released before compositor1, whose reference will be released later when
672 // the post-task is serviced. But since it was destroyed _on the impl thread_
673 // last, its sync point values should be used.
674 compositor2->Run(200, true, main_thread_task_runner_.get());
676 stop_capture.Signal();
677 Wait(main_thread_);
679 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
682 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest {
683 public:
684 TextureLayerImplWithMailboxThreadedCallback()
685 : callback_count_(0),
686 commit_count_(0) {}
688 // Make sure callback is received on main and doesn't block the impl thread.
689 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
690 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
691 EXPECT_FALSE(lost_resource);
692 ++callback_count_;
695 void SetMailbox(char mailbox_char) {
696 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
697 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
698 base::Bind(
699 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback,
700 base::Unretained(this)));
701 layer_->SetTextureMailbox(
702 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
703 callback.Pass());
706 void BeginTest() override {
707 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
709 gfx::Size bounds(100, 100);
710 root_ = Layer::Create();
711 root_->SetBounds(bounds);
713 layer_ = TextureLayer::CreateForMailbox(nullptr);
714 layer_->SetIsDrawable(true);
715 layer_->SetBounds(bounds);
717 root_->AddChild(layer_);
718 layer_tree_host()->SetRootLayer(root_);
719 layer_tree_host()->SetViewportSize(bounds);
720 SetMailbox('1');
721 EXPECT_EQ(0, callback_count_);
723 // Case #1: change mailbox before the commit. The old mailbox should be
724 // released immediately.
725 SetMailbox('2');
726 EXPECT_EQ(1, callback_count_);
727 PostSetNeedsCommitToMainThread();
730 void DidCommit() override {
731 ++commit_count_;
732 switch (commit_count_) {
733 case 1:
734 // Case #2: change mailbox after the commit (and draw), where the
735 // layer draws. The old mailbox should be released during the next
736 // commit.
737 SetMailbox('3');
738 EXPECT_EQ(1, callback_count_);
739 break;
740 case 2:
741 EXPECT_EQ(2, callback_count_);
742 // Case #3: change mailbox when the layer doesn't draw. The old
743 // mailbox should be released during the next commit.
744 layer_->SetBounds(gfx::Size());
745 SetMailbox('4');
746 break;
747 case 3:
748 EXPECT_EQ(3, callback_count_);
749 // Case #4: release mailbox that was committed but never drawn. The
750 // old mailbox should be released during the next commit.
751 layer_->SetTextureMailbox(TextureMailbox(), nullptr);
752 break;
753 case 4:
754 if (layer_tree_host()->settings().impl_side_painting) {
755 // With impl painting, the texture mailbox will still be on the impl
756 // thread when the commit finishes, because the layer is not drawble
757 // when it has no texture mailbox, and thus does not block the commit
758 // on activation. So, we wait for activation.
759 // TODO(danakj): fix this. crbug.com/277953
760 layer_tree_host()->SetNeedsCommit();
761 break;
762 } else {
763 ++commit_count_;
765 case 5:
766 EXPECT_EQ(4, callback_count_);
767 // Restore a mailbox for the next step.
768 SetMailbox('5');
769 break;
770 case 6:
771 // Case #5: remove layer from tree. Callback should *not* be called, the
772 // mailbox is returned to the main thread.
773 EXPECT_EQ(4, callback_count_);
774 layer_->RemoveFromParent();
775 break;
776 case 7:
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 around to
780 // block the commit on activation anymore. So, we wait for activation.
781 // TODO(danakj): fix this. crbug.com/277953
782 layer_tree_host()->SetNeedsCommit();
783 break;
784 } else {
785 ++commit_count_;
787 case 8:
788 EXPECT_EQ(4, callback_count_);
789 // Resetting the mailbox will call the callback now.
790 layer_->SetTextureMailbox(TextureMailbox(), nullptr);
791 EXPECT_EQ(5, callback_count_);
792 EndTest();
793 break;
794 default:
795 NOTREACHED();
796 break;
800 void AfterTest() override {}
802 private:
803 base::ThreadChecker main_thread_;
804 int callback_count_;
805 int commit_count_;
806 scoped_refptr<Layer> root_;
807 scoped_refptr<TextureLayer> layer_;
810 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
811 TextureLayerImplWithMailboxThreadedCallback);
814 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
815 protected:
816 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
818 static void ReleaseCallback(uint32 sync_point, bool lost_resource) {}
820 void SetMailbox(char mailbox_char) {
821 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
822 base::Bind(
823 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
824 layer_->SetTextureMailbox(
825 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
826 callback.Pass());
829 void BeginTest() override {
830 gfx::Size bounds(100, 100);
831 root_ = Layer::Create();
832 root_->SetBounds(bounds);
834 layer_ = TextureLayer::CreateForMailbox(nullptr);
835 layer_->SetIsDrawable(true);
836 layer_->SetBounds(bounds);
838 root_->AddChild(layer_);
839 layer_tree_host()->SetRootLayer(root_);
840 layer_tree_host()->SetViewportSize(bounds);
841 SetMailbox('1');
843 PostSetNeedsCommitToMainThread();
846 void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
847 ++activate_count_;
850 void DidCommit() override {
851 switch (layer_tree_host()->source_frame_number()) {
852 case 1:
853 // The first mailbox has been activated. Set a new mailbox, and
854 // expect the next commit to finish *after* it is activated.
855 SetMailbox('2');
856 break;
857 case 2:
858 // The second mailbox has been activated. Remove the layer from
859 // the tree to cause another commit/activation. The commit should
860 // finish *after* the layer is removed from the active tree.
861 layer_->RemoveFromParent();
862 break;
863 case 3:
864 EndTest();
865 break;
869 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
870 switch (host_impl->active_tree()->source_frame_number()) {
871 case 0: {
872 // The activate for the 1st mailbox should have happened before now.
873 EXPECT_EQ(1, activate_count_);
874 break;
876 case 1: {
877 // The activate for the 2nd mailbox should have happened before now.
878 EXPECT_EQ(2, activate_count_);
879 break;
881 case 2: {
882 // The activate to remove the layer should have happened before now.
883 EXPECT_EQ(3, activate_count_);
884 break;
886 case 3: {
887 NOTREACHED();
888 break;
893 void AfterTest() override {}
895 int activate_count_;
896 scoped_refptr<Layer> root_;
897 scoped_refptr<TextureLayer> layer_;
900 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
901 TextureLayerMailboxIsActivatedDuringCommit);
903 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
904 protected:
905 TextureLayerImplWithMailboxTest()
906 : fake_client_(
907 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
909 void SetUp() override {
910 TextureLayerTest::SetUp();
911 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
912 EXPECT_TRUE(host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()));
915 bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
916 bool will_draw = layer->WillDraw(
917 mode, host_impl_.active_tree()->resource_provider());
918 if (will_draw)
919 layer->DidDraw(host_impl_.active_tree()->resource_provider());
920 return will_draw;
923 FakeLayerTreeHostClient fake_client_;
926 // Test conditions for results of TextureLayerImpl::WillDraw under
927 // different configurations of different mailbox, texture_id, and draw_mode.
928 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
929 EXPECT_CALL(
930 test_data_.mock_callback_,
931 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
932 .Times(AnyNumber());
933 EXPECT_CALL(test_data_.mock_callback_,
934 ReleaseImpl2(test_data_.shared_bitmap_.get(), 0, false, _))
935 .Times(AnyNumber());
936 // Hardware mode.
938 scoped_ptr<TextureLayerImpl> impl_layer =
939 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
940 impl_layer->SetTextureMailbox(
941 test_data_.mailbox1_,
942 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
943 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
947 scoped_ptr<TextureLayerImpl> impl_layer =
948 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
949 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
950 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
954 // Software resource.
955 scoped_ptr<TextureLayerImpl> impl_layer =
956 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
957 impl_layer->SetTextureMailbox(
958 test_data_.mailbox3_,
959 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
960 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
963 // Software mode.
965 scoped_ptr<TextureLayerImpl> impl_layer =
966 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
967 impl_layer->SetTextureMailbox(
968 test_data_.mailbox1_,
969 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
970 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
974 scoped_ptr<TextureLayerImpl> impl_layer =
975 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
976 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
977 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
981 // Software resource.
982 scoped_ptr<TextureLayerImpl> impl_layer =
983 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
984 impl_layer->SetTextureMailbox(
985 test_data_.mailbox3_,
986 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
987 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
990 // Resourceless software mode.
992 scoped_ptr<TextureLayerImpl> impl_layer =
993 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
994 impl_layer->SetTextureMailbox(
995 test_data_.mailbox1_,
996 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
997 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
1001 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
1002 host_impl_.CreatePendingTree();
1003 scoped_ptr<TextureLayerImpl> pending_layer;
1004 pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1);
1005 ASSERT_TRUE(pending_layer);
1007 scoped_ptr<LayerImpl> active_layer(
1008 pending_layer->CreateLayerImpl(host_impl_.active_tree()));
1009 ASSERT_TRUE(active_layer);
1011 pending_layer->SetTextureMailbox(
1012 test_data_.mailbox1_,
1013 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1015 // Test multiple commits without an activation.
1016 EXPECT_CALL(
1017 test_data_.mock_callback_,
1018 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
1019 .Times(1);
1020 pending_layer->SetTextureMailbox(
1021 test_data_.mailbox2_,
1022 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox2_impl_));
1023 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1025 // Test callback after activation.
1026 pending_layer->PushPropertiesTo(active_layer.get());
1027 active_layer->DidBecomeActive();
1029 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1030 pending_layer->SetTextureMailbox(
1031 test_data_.mailbox1_,
1032 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1033 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1035 EXPECT_CALL(test_data_.mock_callback_,
1036 ReleaseImpl(test_data_.mailbox_name2_, _, false, _)).Times(1);
1037 pending_layer->PushPropertiesTo(active_layer.get());
1038 active_layer->DidBecomeActive();
1039 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1041 // Test resetting the mailbox.
1042 EXPECT_CALL(test_data_.mock_callback_,
1043 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1044 pending_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1045 pending_layer->PushPropertiesTo(active_layer.get());
1046 active_layer->DidBecomeActive();
1047 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1049 // Test destructor.
1050 EXPECT_CALL(
1051 test_data_.mock_callback_,
1052 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
1053 .Times(1);
1054 pending_layer->SetTextureMailbox(
1055 test_data_.mailbox1_,
1056 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1059 TEST_F(TextureLayerImplWithMailboxTest,
1060 TestDestructorCallbackOnCreatedResource) {
1061 scoped_ptr<TextureLayerImpl> impl_layer;
1062 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1063 ASSERT_TRUE(impl_layer);
1065 EXPECT_CALL(test_data_.mock_callback_,
1066 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1067 impl_layer->SetTextureMailbox(
1068 test_data_.mailbox1_,
1069 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1070 impl_layer->DidBecomeActive();
1071 EXPECT_TRUE(impl_layer->WillDraw(
1072 DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1073 impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1074 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1077 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1078 ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1079 ResourceProvider::ResourceId id = provider->CreateResourceFromTextureMailbox(
1080 test_data_.mailbox1_,
1081 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1082 provider->AllocateForTesting(id);
1084 // Transfer some resources to the parent.
1085 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1086 resource_ids_to_transfer.push_back(id);
1087 TransferableResourceArray list;
1088 provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1089 EXPECT_TRUE(provider->InUseByConsumer(id));
1090 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1091 provider->DeleteResource(id);
1092 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1093 EXPECT_CALL(test_data_.mock_callback_,
1094 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1095 ReturnedResourceArray returned;
1096 TransferableResource::ReturnResources(list, &returned);
1097 provider->ReceiveReturnsFromParent(returned);
1100 // Checks that TextureLayer::Update does not cause an extra commit when setting
1101 // the texture mailbox.
1102 class TextureLayerNoExtraCommitForMailboxTest
1103 : public LayerTreeTest,
1104 public TextureLayerClient {
1105 public:
1106 // TextureLayerClient implementation.
1107 bool PrepareTextureMailbox(
1108 TextureMailbox* texture_mailbox,
1109 scoped_ptr<SingleReleaseCallback>* release_callback,
1110 bool use_shared_memory) override {
1111 if (layer_tree_host()->source_frame_number() == 1) {
1112 // Once this has been committed, the mailbox will be released.
1113 *texture_mailbox = TextureMailbox();
1114 return true;
1117 *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1118 *release_callback = SingleReleaseCallback::Create(
1119 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1120 base::Unretained(this)));
1121 return true;
1124 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1125 // Source frame number during callback is the same as the source frame
1126 // on which it was released.
1127 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1128 EndTest();
1131 void SetupTree() override {
1132 scoped_refptr<Layer> root = Layer::Create();
1133 root->SetBounds(gfx::Size(10, 10));
1134 root->SetIsDrawable(true);
1136 texture_layer_ = TextureLayer::CreateForMailbox(this);
1137 texture_layer_->SetBounds(gfx::Size(10, 10));
1138 texture_layer_->SetIsDrawable(true);
1139 root->AddChild(texture_layer_);
1141 layer_tree_host()->SetRootLayer(root);
1142 LayerTreeTest::SetupTree();
1145 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1147 void DidCommitAndDrawFrame() override {
1148 switch (layer_tree_host()->source_frame_number()) {
1149 case 1:
1150 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1151 // Invalidate the texture layer to clear the mailbox before
1152 // ending the test.
1153 texture_layer_->SetNeedsDisplay();
1154 break;
1155 case 2:
1156 break;
1157 default:
1158 NOTREACHED();
1159 break;
1163 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1164 ASSERT_TRUE(result);
1165 DelegatedFrameData* delegated_frame_data =
1166 output_surface()->last_sent_frame().delegated_frame_data.get();
1167 if (!delegated_frame_data)
1168 return;
1170 // Return all resources immediately.
1171 TransferableResourceArray resources_to_return =
1172 output_surface()->resources_held_by_parent();
1174 CompositorFrameAck ack;
1175 for (size_t i = 0; i < resources_to_return.size(); ++i)
1176 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1177 host_impl->ReclaimResources(&ack);
1180 void AfterTest() override {}
1182 private:
1183 scoped_refptr<TextureLayer> texture_layer_;
1186 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1188 // Checks that changing a mailbox in the client for a TextureLayer that's
1189 // invisible correctly works and uses the new mailbox as soon as the layer
1190 // becomes visible (and returns the old one).
1191 class TextureLayerChangeInvisibleMailboxTest
1192 : public LayerTreeTest,
1193 public TextureLayerClient {
1194 public:
1195 TextureLayerChangeInvisibleMailboxTest()
1196 : mailbox_changed_(true),
1197 mailbox_returned_(0),
1198 prepare_called_(0),
1199 commit_count_(0) {
1200 mailbox_ = MakeMailbox('1');
1203 // TextureLayerClient implementation.
1204 bool PrepareTextureMailbox(
1205 TextureMailbox* mailbox,
1206 scoped_ptr<SingleReleaseCallback>* release_callback,
1207 bool use_shared_memory) override {
1208 ++prepare_called_;
1209 if (!mailbox_changed_)
1210 return false;
1211 *mailbox = mailbox_;
1212 *release_callback = SingleReleaseCallback::Create(
1213 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1214 base::Unretained(this)));
1215 return true;
1218 TextureMailbox MakeMailbox(char name) {
1219 return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0);
1222 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1223 ++mailbox_returned_;
1226 void SetupTree() override {
1227 scoped_refptr<Layer> root = Layer::Create();
1228 root->SetBounds(gfx::Size(10, 10));
1229 root->SetIsDrawable(true);
1231 solid_layer_ = SolidColorLayer::Create();
1232 solid_layer_->SetBounds(gfx::Size(10, 10));
1233 solid_layer_->SetIsDrawable(true);
1234 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1235 root->AddChild(solid_layer_);
1237 parent_layer_ = Layer::Create();
1238 parent_layer_->SetBounds(gfx::Size(10, 10));
1239 parent_layer_->SetIsDrawable(true);
1240 root->AddChild(parent_layer_);
1242 texture_layer_ = TextureLayer::CreateForMailbox(this);
1243 texture_layer_->SetBounds(gfx::Size(10, 10));
1244 texture_layer_->SetIsDrawable(true);
1245 parent_layer_->AddChild(texture_layer_);
1247 layer_tree_host()->SetRootLayer(root);
1248 LayerTreeTest::SetupTree();
1251 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1253 void DidCommitAndDrawFrame() override {
1254 ++commit_count_;
1255 switch (commit_count_) {
1256 case 1:
1257 // We should have updated the layer, committing the texture.
1258 EXPECT_EQ(1, prepare_called_);
1259 // Make layer invisible.
1260 parent_layer_->SetOpacity(0.f);
1261 break;
1262 case 2:
1263 // Layer shouldn't have been updated.
1264 EXPECT_EQ(1, prepare_called_);
1265 // Change the texture.
1266 mailbox_ = MakeMailbox('2');
1267 mailbox_changed_ = true;
1268 texture_layer_->SetNeedsDisplay();
1269 // Force a change to make sure we draw a frame.
1270 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1271 break;
1272 case 3:
1273 // Layer shouldn't have been updated.
1274 EXPECT_EQ(1, prepare_called_);
1275 // So the old mailbox isn't returned yet.
1276 EXPECT_EQ(0, mailbox_returned_);
1277 // Make layer visible again.
1278 parent_layer_->SetOpacity(1.f);
1279 break;
1280 case 4:
1281 // Layer should have been updated.
1282 EXPECT_EQ(2, prepare_called_);
1283 // So the old mailbox should have been returned already.
1284 EXPECT_EQ(1, mailbox_returned_);
1285 texture_layer_->ClearClient();
1286 break;
1287 case 5:
1288 EXPECT_EQ(2, mailbox_returned_);
1289 EndTest();
1290 break;
1291 default:
1292 NOTREACHED();
1293 break;
1297 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1298 ASSERT_TRUE(result);
1299 DelegatedFrameData* delegated_frame_data =
1300 output_surface()->last_sent_frame().delegated_frame_data.get();
1301 if (!delegated_frame_data)
1302 return;
1304 // Return all resources immediately.
1305 TransferableResourceArray resources_to_return =
1306 output_surface()->resources_held_by_parent();
1308 CompositorFrameAck ack;
1309 for (size_t i = 0; i < resources_to_return.size(); ++i)
1310 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1311 host_impl->ReclaimResources(&ack);
1314 void AfterTest() override {}
1316 private:
1317 scoped_refptr<SolidColorLayer> solid_layer_;
1318 scoped_refptr<Layer> parent_layer_;
1319 scoped_refptr<TextureLayer> texture_layer_;
1321 // Used on the main thread.
1322 bool mailbox_changed_;
1323 TextureMailbox mailbox_;
1324 int mailbox_returned_;
1325 int prepare_called_;
1326 int commit_count_;
1329 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1331 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1332 // the mailbox back to TextureLayerClient.
1333 class TextureLayerReleaseResourcesBase
1334 : public LayerTreeTest,
1335 public TextureLayerClient {
1336 public:
1337 // TextureLayerClient implementation.
1338 bool PrepareTextureMailbox(
1339 TextureMailbox* mailbox,
1340 scoped_ptr<SingleReleaseCallback>* release_callback,
1341 bool use_shared_memory) override {
1342 *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1343 *release_callback = SingleReleaseCallback::Create(
1344 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1345 base::Unretained(this)));
1346 return true;
1349 void MailboxReleased(unsigned sync_point, bool lost_resource) {
1350 mailbox_released_ = true;
1353 void SetupTree() override {
1354 LayerTreeTest::SetupTree();
1356 scoped_refptr<TextureLayer> texture_layer =
1357 TextureLayer::CreateForMailbox(this);
1358 texture_layer->SetBounds(gfx::Size(10, 10));
1359 texture_layer->SetIsDrawable(true);
1361 layer_tree_host()->root_layer()->AddChild(texture_layer);
1364 void BeginTest() override {
1365 mailbox_released_ = false;
1366 PostSetNeedsCommitToMainThread();
1369 void DidCommitAndDrawFrame() override { EndTest(); }
1371 void AfterTest() override { EXPECT_TRUE(mailbox_released_); }
1373 private:
1374 bool mailbox_released_;
1377 class TextureLayerReleaseResourcesAfterCommit
1378 : public TextureLayerReleaseResourcesBase {
1379 public:
1380 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
1381 LayerTreeImpl* tree = nullptr;
1382 tree = host_impl->sync_tree();
1383 tree->root_layer()->children()[0]->ReleaseResources();
1387 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1389 class TextureLayerReleaseResourcesAfterActivate
1390 : public TextureLayerReleaseResourcesBase {
1391 public:
1392 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
1393 host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
1397 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
1399 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
1400 public:
1401 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1402 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1403 EXPECT_FALSE(lost_resource);
1404 ++callback_count_;
1405 EndTest();
1408 void SetMailbox(char mailbox_char) {
1409 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1410 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1411 base::Bind(
1412 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
1413 base::Unretained(this)));
1414 layer_->SetTextureMailbox(
1415 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1416 callback.Pass());
1419 void SetupTree() override {
1420 gfx::Size bounds(100, 100);
1421 root_ = Layer::Create();
1422 root_->SetBounds(bounds);
1424 layer_ = TextureLayer::CreateForMailbox(nullptr);
1425 layer_->SetIsDrawable(true);
1426 layer_->SetBounds(bounds);
1428 root_->AddChild(layer_);
1429 layer_tree_host()->SetRootLayer(root_);
1430 layer_tree_host()->SetViewportSize(bounds);
1433 void BeginTest() override {
1434 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1436 callback_count_ = 0;
1438 // Set the mailbox on the main thread.
1439 SetMailbox('1');
1440 EXPECT_EQ(0, callback_count_);
1442 PostSetNeedsCommitToMainThread();
1445 void DidCommitAndDrawFrame() override {
1446 switch (layer_tree_host()->source_frame_number()) {
1447 case 1:
1448 // Delete the TextureLayer on the main thread while the mailbox is in
1449 // the impl tree.
1450 layer_->RemoveFromParent();
1451 layer_ = nullptr;
1452 break;
1456 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1458 private:
1459 base::ThreadChecker main_thread_;
1460 int callback_count_;
1461 scoped_refptr<Layer> root_;
1462 scoped_refptr<TextureLayer> layer_;
1465 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1466 TextureLayerWithMailboxMainThreadDeleted);
1468 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
1469 public:
1470 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1471 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1472 EXPECT_FALSE(lost_resource);
1473 ++callback_count_;
1474 EndTest();
1477 void SetMailbox(char mailbox_char) {
1478 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1479 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1480 base::Bind(
1481 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
1482 base::Unretained(this)));
1483 layer_->SetTextureMailbox(
1484 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1485 callback.Pass());
1488 void SetupTree() override {
1489 gfx::Size bounds(100, 100);
1490 root_ = Layer::Create();
1491 root_->SetBounds(bounds);
1493 layer_ = TextureLayer::CreateForMailbox(nullptr);
1494 layer_->SetIsDrawable(true);
1495 layer_->SetBounds(bounds);
1497 root_->AddChild(layer_);
1498 layer_tree_host()->SetRootLayer(root_);
1499 layer_tree_host()->SetViewportSize(bounds);
1502 void BeginTest() override {
1503 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1505 callback_count_ = 0;
1507 // Set the mailbox on the main thread.
1508 SetMailbox('1');
1509 EXPECT_EQ(0, callback_count_);
1511 PostSetNeedsCommitToMainThread();
1514 void DidCommitAndDrawFrame() override {
1515 switch (layer_tree_host()->source_frame_number()) {
1516 case 1:
1517 // Remove the TextureLayer on the main thread while the mailbox is in
1518 // the impl tree, but don't delete the TextureLayer until after the impl
1519 // tree side is deleted.
1520 layer_->RemoveFromParent();
1521 break;
1522 case 2:
1523 layer_ = nullptr;
1524 break;
1528 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1530 private:
1531 base::ThreadChecker main_thread_;
1532 int callback_count_;
1533 scoped_refptr<Layer> root_;
1534 scoped_refptr<TextureLayer> layer_;
1537 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1538 TextureLayerWithMailboxImplThreadDeleted);
1540 } // namespace
1541 } // namespace cc