Update comments of TabObserver#onLoadStarted and rename onContentChanged
[chromium-blink-merge.git] / cc / layers / texture_layer_unittest.cc
blob4a1e76d7e4985ee2943c656cbf9e10b5dfdf9196
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_;
216 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) {
217 scoped_refptr<TextureLayer> test_layer =
218 TextureLayer::CreateForMailbox(nullptr);
219 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer));
221 // Test properties that should call SetNeedsCommit. All properties need to
222 // be set to new values in order for SetNeedsCommit to be called.
223 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false));
224 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetNearestNeighbor(true));
225 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV(
226 gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f)));
227 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity(
228 0.5f, 0.5f, 0.5f, 0.5f));
229 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false));
230 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true));
233 TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) {
234 const gfx::Size layer_bounds(100, 100);
235 const gfx::Rect layer_rect(layer_bounds);
236 const Region layer_region(layer_rect);
238 scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(nullptr);
239 layer->SetBounds(layer_bounds);
240 layer->draw_properties().visible_content_rect = layer_rect;
241 layer->SetBlendBackgroundColor(true);
243 // Verify initial conditions.
244 EXPECT_FALSE(layer->contents_opaque());
245 EXPECT_EQ(0u, layer->background_color());
246 EXPECT_EQ(Region().ToString(),
247 layer->VisibleContentOpaqueRegion().ToString());
249 // Opaque background.
250 layer->SetBackgroundColor(SK_ColorWHITE);
251 EXPECT_EQ(layer_region.ToString(),
252 layer->VisibleContentOpaqueRegion().ToString());
254 // Transparent background.
255 layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
256 EXPECT_EQ(Region().ToString(),
257 layer->VisibleContentOpaqueRegion().ToString());
260 TEST_F(TextureLayerTest, RateLimiter) {
261 FakeTextureLayerClient client;
262 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(
263 &client);
264 test_layer->SetIsDrawable(true);
265 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
266 layer_tree_host_->SetRootLayer(test_layer);
268 // Don't rate limit until we invalidate.
269 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
270 test_layer->SetRateLimitContext(true);
271 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
273 // Do rate limit after we invalidate.
274 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
275 test_layer->SetNeedsDisplay();
276 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
278 // Stop rate limiter when we don't want it any more.
279 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
280 test_layer->SetRateLimitContext(false);
281 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
283 // Or we clear the client.
284 test_layer->SetRateLimitContext(true);
285 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
286 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
287 test_layer->ClearClient();
288 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
290 // Reset to a layer with a client, that started the rate limiter.
291 test_layer = TextureLayer::CreateForMailbox(
292 &client);
293 test_layer->SetIsDrawable(true);
294 test_layer->SetRateLimitContext(true);
295 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
296 layer_tree_host_->SetRootLayer(test_layer);
297 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
298 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
299 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
300 test_layer->SetNeedsDisplay();
301 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
303 // Stop rate limiter when we're removed from the tree.
304 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
305 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
306 layer_tree_host_->SetRootLayer(nullptr);
307 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
310 class TestMailboxHolder : public TextureLayer::TextureMailboxHolder {
311 public:
312 using TextureLayer::TextureMailboxHolder::Create;
314 protected:
315 ~TestMailboxHolder() override {}
318 class TextureLayerWithMailboxTest : public TextureLayerTest {
319 protected:
320 void TearDown() override {
321 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
322 EXPECT_CALL(test_data_.mock_callback_,
323 Release(test_data_.mailbox_name1_,
324 test_data_.sync_point1_,
325 false)).Times(1);
326 TextureLayerTest::TearDown();
330 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
331 scoped_refptr<TextureLayer> test_layer =
332 TextureLayer::CreateForMailbox(nullptr);
333 ASSERT_TRUE(test_layer.get());
335 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
336 layer_tree_host_->SetRootLayer(test_layer);
337 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
339 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
340 test_layer->SetTextureMailbox(
341 test_data_.mailbox1_,
342 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
343 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
345 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
346 EXPECT_CALL(test_data_.mock_callback_,
347 Release(test_data_.mailbox_name1_,
348 test_data_.sync_point1_,
349 false))
350 .Times(1);
351 test_layer->SetTextureMailbox(
352 test_data_.mailbox2_,
353 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
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 EXPECT_CALL(test_data_.mock_callback_,
359 Release(test_data_.mailbox_name2_,
360 test_data_.sync_point2_,
361 false))
362 .Times(1);
363 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
364 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
365 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
367 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
368 test_layer->SetTextureMailbox(
369 test_data_.mailbox3_,
370 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
371 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
372 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
374 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
375 EXPECT_CALL(test_data_.mock_callback_,
376 Release2(test_data_.shared_bitmap_.get(), 0, false)).Times(1);
377 test_layer->SetTextureMailbox(TextureMailbox(), nullptr);
378 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
379 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
381 // Test destructor.
382 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
383 test_layer->SetTextureMailbox(
384 test_data_.mailbox1_,
385 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
388 TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) {
389 scoped_refptr<TextureLayer> test_layer =
390 TextureLayer::CreateForMailbox(nullptr);
391 ASSERT_TRUE(test_layer.get());
393 // These use the same gpu::Mailbox, but different sync points.
394 TextureMailbox mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D, 1);
395 TextureMailbox mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D, 2);
397 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
398 layer_tree_host_->SetRootLayer(test_layer);
399 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
401 // Set the mailbox the first time. It should cause a commit.
402 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
403 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox1);
404 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
406 // Set the mailbox again with a new sync point, as the backing texture has
407 // been updated. It should cause a new commit.
408 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
409 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox2);
410 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
413 class TextureLayerMailboxHolderTest : public TextureLayerTest {
414 public:
415 TextureLayerMailboxHolderTest()
416 : main_thread_("MAIN") {
417 main_thread_.Start();
418 main_thread_.message_loop()->task_runner()->PostTask(
419 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain,
420 base::Unretained(this)));
421 Wait(main_thread_);
424 void Wait(const base::Thread& thread) {
425 bool manual_reset = false;
426 bool initially_signaled = false;
427 base::WaitableEvent event(manual_reset, initially_signaled);
428 thread.message_loop()->task_runner()->PostTask(
429 FROM_HERE,
430 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
431 event.Wait();
434 void CreateMainRef() {
435 main_ref_ = TestMailboxHolder::Create(
436 test_data_.mailbox1_,
437 SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass();
440 void ReleaseMainRef() { main_ref_ = nullptr; }
442 void CreateImplRef(scoped_ptr<SingleReleaseCallbackImpl>* impl_ref) {
443 *impl_ref = main_ref_->holder()->GetCallbackForImplThread();
446 void CapturePostTasksAndWait(base::WaitableEvent* begin_capture,
447 base::WaitableEvent* wait_for_capture,
448 base::WaitableEvent* stop_capture) {
449 begin_capture->Wait();
450 BlockingTaskRunner::CapturePostTasks capture(
451 main_thread_task_runner_.get());
452 wait_for_capture->Signal();
453 stop_capture->Wait();
456 protected:
457 void InitializeOnMain() {
458 main_thread_task_runner_ =
459 BlockingTaskRunner::Create(main_thread_.task_runner());
462 scoped_ptr<TestMailboxHolder::MainThreadReference>
463 main_ref_;
464 base::Thread main_thread_;
465 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
468 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) {
469 scoped_refptr<TextureLayer> test_layer =
470 TextureLayer::CreateForMailbox(nullptr);
471 ASSERT_TRUE(test_layer.get());
473 main_thread_.message_loop()->task_runner()->PostTask(
474 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
475 base::Unretained(this)));
477 Wait(main_thread_);
479 // The texture layer is attached to compositor1, and passes a reference to its
480 // impl tree.
481 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
482 main_thread_.message_loop()->task_runner()->PostTask(
483 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
484 base::Unretained(this), &compositor1));
486 // Then the texture layer is removed and attached to compositor2, and passes a
487 // reference to its impl tree.
488 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
489 main_thread_.message_loop()->task_runner()->PostTask(
490 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
491 base::Unretained(this), &compositor2));
493 Wait(main_thread_);
494 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
496 // The compositors both destroy their impl trees before the main thread layer
497 // is destroyed.
498 compositor1->Run(100, false, main_thread_task_runner_.get());
499 compositor2->Run(200, false, main_thread_task_runner_.get());
501 Wait(main_thread_);
503 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
504 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
506 // The main thread ref is the last one, so the mailbox is released back to the
507 // embedder, with the last sync point provided by the impl trees.
508 EXPECT_CALL(test_data_.mock_callback_,
509 Release(test_data_.mailbox_name1_, 200, false)).Times(1);
511 main_thread_.message_loop()->task_runner()->PostTask(
512 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
513 base::Unretained(this)));
514 Wait(main_thread_);
515 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
518 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) {
519 scoped_refptr<TextureLayer> test_layer =
520 TextureLayer::CreateForMailbox(nullptr);
521 ASSERT_TRUE(test_layer.get());
523 main_thread_.message_loop()->task_runner()->PostTask(
524 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
525 base::Unretained(this)));
527 Wait(main_thread_);
529 // The texture layer is attached to compositor1, and passes a reference to its
530 // impl tree.
531 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
532 main_thread_.message_loop()->task_runner()->PostTask(
533 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
534 base::Unretained(this), &compositor1));
536 // Then the texture layer is removed and attached to compositor2, and passes a
537 // reference to its impl tree.
538 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
539 main_thread_.message_loop()->task_runner()->PostTask(
540 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
541 base::Unretained(this), &compositor2));
543 Wait(main_thread_);
544 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
546 // One compositor destroys their impl tree.
547 compositor1->Run(100, false, main_thread_task_runner_.get());
549 // Then the main thread reference is destroyed.
550 main_thread_.message_loop()->task_runner()->PostTask(
551 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
552 base::Unretained(this)));
554 Wait(main_thread_);
556 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
557 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
559 // The second impl reference is destroyed last, causing the mailbox to be
560 // released back to the embedder with the last sync point from the impl tree.
561 EXPECT_CALL(test_data_.mock_callback_,
562 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
564 compositor2->Run(200, true, main_thread_task_runner_.get());
565 Wait(main_thread_);
566 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
569 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) {
570 scoped_refptr<TextureLayer> test_layer =
571 TextureLayer::CreateForMailbox(nullptr);
572 ASSERT_TRUE(test_layer.get());
574 main_thread_.message_loop()->task_runner()->PostTask(
575 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
576 base::Unretained(this)));
578 Wait(main_thread_);
580 // The texture layer is attached to compositor1, and passes a reference to its
581 // impl tree.
582 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
583 main_thread_.message_loop()->task_runner()->PostTask(
584 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
585 base::Unretained(this), &compositor1));
587 // Then the texture layer is removed and attached to compositor2, and passes a
588 // reference to its impl tree.
589 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
590 main_thread_.message_loop()->task_runner()->PostTask(
591 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
592 base::Unretained(this), &compositor2));
594 Wait(main_thread_);
595 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
597 // The main thread reference is destroyed first.
598 main_thread_.message_loop()->task_runner()->PostTask(
599 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
600 base::Unretained(this)));
602 // One compositor destroys their impl tree.
603 compositor2->Run(200, false, main_thread_task_runner_.get());
605 Wait(main_thread_);
607 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
608 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
610 // The second impl reference is destroyed last, causing the mailbox to be
611 // released back to the embedder with the last sync point from the impl tree.
612 EXPECT_CALL(test_data_.mock_callback_,
613 Release(test_data_.mailbox_name1_, 100, true)).Times(1);
615 compositor1->Run(100, true, main_thread_task_runner_.get());
616 Wait(main_thread_);
617 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
620 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) {
621 scoped_refptr<TextureLayer> test_layer =
622 TextureLayer::CreateForMailbox(nullptr);
623 ASSERT_TRUE(test_layer.get());
625 main_thread_.message_loop()->task_runner()->PostTask(
626 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
627 base::Unretained(this)));
629 Wait(main_thread_);
631 // The texture layer is attached to compositor1, and passes a reference to its
632 // impl tree.
633 scoped_ptr<SingleReleaseCallbackImpl> compositor1;
634 main_thread_.message_loop()->task_runner()->PostTask(
635 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
636 base::Unretained(this), &compositor1));
638 // Then the texture layer is removed and attached to compositor2, and passes a
639 // reference to its impl tree.
640 scoped_ptr<SingleReleaseCallbackImpl> compositor2;
641 main_thread_.message_loop()->task_runner()->PostTask(
642 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
643 base::Unretained(this), &compositor2));
645 Wait(main_thread_);
646 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
648 // The main thread reference is destroyed first.
649 main_thread_.message_loop()->task_runner()->PostTask(
650 FROM_HERE, base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
651 base::Unretained(this)));
653 EXPECT_CALL(test_data_.mock_callback_,
654 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
656 bool manual_reset = false;
657 bool initially_signaled = false;
658 base::WaitableEvent begin_capture(manual_reset, initially_signaled);
659 base::WaitableEvent wait_for_capture(manual_reset, initially_signaled);
660 base::WaitableEvent stop_capture(manual_reset, initially_signaled);
662 // Post a task to start capturing tasks on the main thread. This will block
663 // the main thread until we signal the |stop_capture| event.
664 main_thread_.message_loop()->task_runner()->PostTask(
665 FROM_HERE,
666 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait,
667 base::Unretained(this), &begin_capture, &wait_for_capture,
668 &stop_capture));
670 // Before the main thread capturing starts, one compositor destroys their
671 // impl reference. Since capturing did not start, this gets post-tasked to
672 // the main thread.
673 compositor1->Run(100, false, main_thread_task_runner_.get());
675 // Start capturing on the main thread.
676 begin_capture.Signal();
677 wait_for_capture.Wait();
679 // Meanwhile, the second compositor released its impl reference, but this task
680 // gets shortcutted directly to the main thread. This means the reference is
681 // released before compositor1, whose reference will be released later when
682 // the post-task is serviced. But since it was destroyed _on the impl thread_
683 // last, its sync point values should be used.
684 compositor2->Run(200, true, main_thread_task_runner_.get());
686 stop_capture.Signal();
687 Wait(main_thread_);
689 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
692 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest {
693 public:
694 TextureLayerImplWithMailboxThreadedCallback()
695 : callback_count_(0),
696 commit_count_(0) {}
698 // Make sure callback is received on main and doesn't block the impl thread.
699 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
700 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
701 EXPECT_FALSE(lost_resource);
702 ++callback_count_;
705 void SetMailbox(char mailbox_char) {
706 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
707 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
708 base::Bind(
709 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback,
710 base::Unretained(this)));
711 layer_->SetTextureMailbox(
712 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
713 callback.Pass());
716 void BeginTest() override {
717 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
719 gfx::Size bounds(100, 100);
720 root_ = Layer::Create();
721 root_->SetBounds(bounds);
723 layer_ = TextureLayer::CreateForMailbox(nullptr);
724 layer_->SetIsDrawable(true);
725 layer_->SetBounds(bounds);
727 root_->AddChild(layer_);
728 layer_tree_host()->SetRootLayer(root_);
729 layer_tree_host()->SetViewportSize(bounds);
730 SetMailbox('1');
731 EXPECT_EQ(0, callback_count_);
733 // Case #1: change mailbox before the commit. The old mailbox should be
734 // released immediately.
735 SetMailbox('2');
736 EXPECT_EQ(1, callback_count_);
737 PostSetNeedsCommitToMainThread();
740 void DidCommit() override {
741 ++commit_count_;
742 switch (commit_count_) {
743 case 1:
744 // Case #2: change mailbox after the commit (and draw), where the
745 // layer draws. The old mailbox should be released during the next
746 // commit.
747 SetMailbox('3');
748 EXPECT_EQ(1, callback_count_);
749 break;
750 case 2:
751 EXPECT_EQ(2, callback_count_);
752 // Case #3: change mailbox when the layer doesn't draw. The old
753 // mailbox should be released during the next commit.
754 layer_->SetBounds(gfx::Size());
755 SetMailbox('4');
756 break;
757 case 3:
758 EXPECT_EQ(3, callback_count_);
759 // Case #4: release mailbox that was committed but never drawn. The
760 // old mailbox should be released during the next commit.
761 layer_->SetTextureMailbox(TextureMailbox(), nullptr);
762 break;
763 case 4:
764 if (layer_tree_host()->settings().impl_side_painting) {
765 // With impl painting, the texture mailbox will still be on the impl
766 // thread when the commit finishes, because the layer is not drawble
767 // when it has no texture mailbox, and thus does not block the commit
768 // on activation. So, we wait for activation.
769 // TODO(danakj): fix this. crbug.com/277953
770 layer_tree_host()->SetNeedsCommit();
771 break;
772 } else {
773 ++commit_count_;
775 case 5:
776 EXPECT_EQ(4, callback_count_);
777 // Restore a mailbox for the next step.
778 SetMailbox('5');
779 break;
780 case 6:
781 // Case #5: remove layer from tree. Callback should *not* be called, the
782 // mailbox is returned to the main thread.
783 EXPECT_EQ(4, callback_count_);
784 layer_->RemoveFromParent();
785 break;
786 case 7:
787 if (layer_tree_host()->settings().impl_side_painting) {
788 // With impl painting, the texture mailbox will still be on the impl
789 // thread when the commit finishes, because the layer is not around to
790 // block the commit on activation anymore. So, we wait for activation.
791 // TODO(danakj): fix this. crbug.com/277953
792 layer_tree_host()->SetNeedsCommit();
793 break;
794 } else {
795 ++commit_count_;
797 case 8:
798 EXPECT_EQ(4, callback_count_);
799 // Resetting the mailbox will call the callback now.
800 layer_->SetTextureMailbox(TextureMailbox(), nullptr);
801 EXPECT_EQ(5, callback_count_);
802 EndTest();
803 break;
804 default:
805 NOTREACHED();
806 break;
810 void AfterTest() override {}
812 private:
813 base::ThreadChecker main_thread_;
814 int callback_count_;
815 int commit_count_;
816 scoped_refptr<Layer> root_;
817 scoped_refptr<TextureLayer> layer_;
820 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
821 TextureLayerImplWithMailboxThreadedCallback);
824 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
825 protected:
826 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
828 static void ReleaseCallback(uint32 sync_point, bool lost_resource) {}
830 void SetMailbox(char mailbox_char) {
831 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
832 base::Bind(
833 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
834 layer_->SetTextureMailbox(
835 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
836 callback.Pass());
839 void BeginTest() override {
840 gfx::Size bounds(100, 100);
841 root_ = Layer::Create();
842 root_->SetBounds(bounds);
844 layer_ = TextureLayer::CreateForMailbox(nullptr);
845 layer_->SetIsDrawable(true);
846 layer_->SetBounds(bounds);
848 root_->AddChild(layer_);
849 layer_tree_host()->SetRootLayer(root_);
850 layer_tree_host()->SetViewportSize(bounds);
851 SetMailbox('1');
853 PostSetNeedsCommitToMainThread();
856 void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
857 ++activate_count_;
860 void DidCommit() override {
861 switch (layer_tree_host()->source_frame_number()) {
862 case 1:
863 // The first mailbox has been activated. Set a new mailbox, and
864 // expect the next commit to finish *after* it is activated.
865 SetMailbox('2');
866 break;
867 case 2:
868 // The second mailbox has been activated. Remove the layer from
869 // the tree to cause another commit/activation. The commit should
870 // finish *after* the layer is removed from the active tree.
871 layer_->RemoveFromParent();
872 break;
873 case 3:
874 EndTest();
875 break;
879 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
880 switch (host_impl->active_tree()->source_frame_number()) {
881 case 0: {
882 // The activate for the 1st mailbox should have happened before now.
883 EXPECT_EQ(1, activate_count_);
884 break;
886 case 1: {
887 // The activate for the 2nd mailbox should have happened before now.
888 EXPECT_EQ(2, activate_count_);
889 break;
891 case 2: {
892 // The activate to remove the layer should have happened before now.
893 EXPECT_EQ(3, activate_count_);
894 break;
896 case 3: {
897 NOTREACHED();
898 break;
903 void AfterTest() override {}
905 int activate_count_;
906 scoped_refptr<Layer> root_;
907 scoped_refptr<TextureLayer> layer_;
910 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
911 TextureLayerMailboxIsActivatedDuringCommit);
913 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
914 protected:
915 TextureLayerImplWithMailboxTest()
916 : fake_client_(
917 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
919 void SetUp() override {
920 TextureLayerTest::SetUp();
921 layer_tree_host_ = MockLayerTreeHost::Create(&fake_client_);
922 EXPECT_TRUE(host_impl_.InitializeRenderer(FakeOutputSurface::Create3d()));
925 bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
926 bool will_draw = layer->WillDraw(
927 mode, host_impl_.active_tree()->resource_provider());
928 if (will_draw)
929 layer->DidDraw(host_impl_.active_tree()->resource_provider());
930 return will_draw;
933 FakeLayerTreeHostClient fake_client_;
936 // Test conditions for results of TextureLayerImpl::WillDraw under
937 // different configurations of different mailbox, texture_id, and draw_mode.
938 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
939 EXPECT_CALL(
940 test_data_.mock_callback_,
941 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
942 .Times(AnyNumber());
943 EXPECT_CALL(test_data_.mock_callback_,
944 ReleaseImpl2(test_data_.shared_bitmap_.get(), 0, false, _))
945 .Times(AnyNumber());
946 // Hardware mode.
948 scoped_ptr<TextureLayerImpl> impl_layer =
949 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
950 impl_layer->SetTextureMailbox(
951 test_data_.mailbox1_,
952 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
953 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
957 scoped_ptr<TextureLayerImpl> impl_layer =
958 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
959 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
960 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
964 // Software resource.
965 scoped_ptr<TextureLayerImpl> impl_layer =
966 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
967 impl_layer->SetTextureMailbox(
968 test_data_.mailbox3_,
969 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
970 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
973 // Software mode.
975 scoped_ptr<TextureLayerImpl> impl_layer =
976 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
977 impl_layer->SetTextureMailbox(
978 test_data_.mailbox1_,
979 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
980 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
984 scoped_ptr<TextureLayerImpl> impl_layer =
985 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
986 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
987 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
991 // Software resource.
992 scoped_ptr<TextureLayerImpl> impl_layer =
993 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
994 impl_layer->SetTextureMailbox(
995 test_data_.mailbox3_,
996 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_));
997 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1000 // Resourceless software mode.
1002 scoped_ptr<TextureLayerImpl> impl_layer =
1003 TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1004 impl_layer->SetTextureMailbox(
1005 test_data_.mailbox1_,
1006 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1007 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
1011 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
1012 host_impl_.CreatePendingTree();
1013 scoped_ptr<TextureLayerImpl> pending_layer;
1014 pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1);
1015 ASSERT_TRUE(pending_layer);
1017 scoped_ptr<LayerImpl> active_layer(
1018 pending_layer->CreateLayerImpl(host_impl_.active_tree()));
1019 ASSERT_TRUE(active_layer);
1021 pending_layer->SetTextureMailbox(
1022 test_data_.mailbox1_,
1023 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1025 // Test multiple commits without an activation.
1026 EXPECT_CALL(
1027 test_data_.mock_callback_,
1028 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
1029 .Times(1);
1030 pending_layer->SetTextureMailbox(
1031 test_data_.mailbox2_,
1032 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox2_impl_));
1033 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1035 // Test callback after activation.
1036 pending_layer->PushPropertiesTo(active_layer.get());
1037 active_layer->DidBecomeActive();
1039 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1040 pending_layer->SetTextureMailbox(
1041 test_data_.mailbox1_,
1042 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1043 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1045 EXPECT_CALL(test_data_.mock_callback_,
1046 ReleaseImpl(test_data_.mailbox_name2_, _, false, _)).Times(1);
1047 pending_layer->PushPropertiesTo(active_layer.get());
1048 active_layer->DidBecomeActive();
1049 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1051 // Test resetting the mailbox.
1052 EXPECT_CALL(test_data_.mock_callback_,
1053 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1054 pending_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1055 pending_layer->PushPropertiesTo(active_layer.get());
1056 active_layer->DidBecomeActive();
1057 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1059 // Test destructor.
1060 EXPECT_CALL(
1061 test_data_.mock_callback_,
1062 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _))
1063 .Times(1);
1064 pending_layer->SetTextureMailbox(
1065 test_data_.mailbox1_,
1066 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1069 TEST_F(TextureLayerImplWithMailboxTest,
1070 TestDestructorCallbackOnCreatedResource) {
1071 scoped_ptr<TextureLayerImpl> impl_layer;
1072 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1073 ASSERT_TRUE(impl_layer);
1075 EXPECT_CALL(test_data_.mock_callback_,
1076 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1077 impl_layer->SetTextureMailbox(
1078 test_data_.mailbox1_,
1079 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1080 impl_layer->DidBecomeActive();
1081 EXPECT_TRUE(impl_layer->WillDraw(
1082 DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1083 impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1084 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr);
1087 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1088 ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1089 ResourceId id = provider->CreateResourceFromTextureMailbox(
1090 test_data_.mailbox1_,
1091 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_));
1092 provider->AllocateForTesting(id);
1094 // Transfer some resources to the parent.
1095 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1096 resource_ids_to_transfer.push_back(id);
1097 TransferableResourceArray list;
1098 provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1099 EXPECT_TRUE(provider->InUseByConsumer(id));
1100 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0);
1101 provider->DeleteResource(id);
1102 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1103 EXPECT_CALL(test_data_.mock_callback_,
1104 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1);
1105 ReturnedResourceArray returned;
1106 TransferableResource::ReturnResources(list, &returned);
1107 provider->ReceiveReturnsFromParent(returned);
1110 // Checks that TextureLayer::Update does not cause an extra commit when setting
1111 // the texture mailbox.
1112 class TextureLayerNoExtraCommitForMailboxTest
1113 : public LayerTreeTest,
1114 public TextureLayerClient {
1115 public:
1116 // TextureLayerClient implementation.
1117 bool PrepareTextureMailbox(
1118 TextureMailbox* texture_mailbox,
1119 scoped_ptr<SingleReleaseCallback>* release_callback,
1120 bool use_shared_memory) override {
1121 if (layer_tree_host()->source_frame_number() == 1) {
1122 // Once this has been committed, the mailbox will be released.
1123 *texture_mailbox = TextureMailbox();
1124 return true;
1127 *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1128 *release_callback = SingleReleaseCallback::Create(
1129 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1130 base::Unretained(this)));
1131 return true;
1134 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1135 // Source frame number during callback is the same as the source frame
1136 // on which it was released.
1137 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1138 EndTest();
1141 void SetupTree() override {
1142 scoped_refptr<Layer> root = Layer::Create();
1143 root->SetBounds(gfx::Size(10, 10));
1144 root->SetIsDrawable(true);
1146 texture_layer_ = TextureLayer::CreateForMailbox(this);
1147 texture_layer_->SetBounds(gfx::Size(10, 10));
1148 texture_layer_->SetIsDrawable(true);
1149 root->AddChild(texture_layer_);
1151 layer_tree_host()->SetRootLayer(root);
1152 LayerTreeTest::SetupTree();
1155 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1157 void DidCommitAndDrawFrame() override {
1158 switch (layer_tree_host()->source_frame_number()) {
1159 case 1:
1160 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1161 // Invalidate the texture layer to clear the mailbox before
1162 // ending the test.
1163 texture_layer_->SetNeedsDisplay();
1164 break;
1165 case 2:
1166 break;
1167 default:
1168 NOTREACHED();
1169 break;
1173 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1174 ASSERT_TRUE(result);
1175 DelegatedFrameData* delegated_frame_data =
1176 output_surface()->last_sent_frame().delegated_frame_data.get();
1177 if (!delegated_frame_data)
1178 return;
1180 // Return all resources immediately.
1181 TransferableResourceArray resources_to_return =
1182 output_surface()->resources_held_by_parent();
1184 CompositorFrameAck ack;
1185 for (size_t i = 0; i < resources_to_return.size(); ++i)
1186 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1187 host_impl->ReclaimResources(&ack);
1190 void AfterTest() override {}
1192 private:
1193 scoped_refptr<TextureLayer> texture_layer_;
1196 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1198 // Checks that changing a mailbox in the client for a TextureLayer that's
1199 // invisible correctly works and uses the new mailbox as soon as the layer
1200 // becomes visible (and returns the old one).
1201 class TextureLayerChangeInvisibleMailboxTest
1202 : public LayerTreeTest,
1203 public TextureLayerClient {
1204 public:
1205 TextureLayerChangeInvisibleMailboxTest()
1206 : mailbox_changed_(true),
1207 mailbox_returned_(0),
1208 prepare_called_(0),
1209 commit_count_(0) {
1210 mailbox_ = MakeMailbox('1');
1213 // TextureLayerClient implementation.
1214 bool PrepareTextureMailbox(
1215 TextureMailbox* mailbox,
1216 scoped_ptr<SingleReleaseCallback>* release_callback,
1217 bool use_shared_memory) override {
1218 ++prepare_called_;
1219 if (!mailbox_changed_)
1220 return false;
1221 *mailbox = mailbox_;
1222 *release_callback = SingleReleaseCallback::Create(
1223 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1224 base::Unretained(this)));
1225 return true;
1228 TextureMailbox MakeMailbox(char name) {
1229 return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0);
1232 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1233 ++mailbox_returned_;
1236 void SetupTree() override {
1237 scoped_refptr<Layer> root = Layer::Create();
1238 root->SetBounds(gfx::Size(10, 10));
1239 root->SetIsDrawable(true);
1241 solid_layer_ = SolidColorLayer::Create();
1242 solid_layer_->SetBounds(gfx::Size(10, 10));
1243 solid_layer_->SetIsDrawable(true);
1244 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1245 root->AddChild(solid_layer_);
1247 parent_layer_ = Layer::Create();
1248 parent_layer_->SetBounds(gfx::Size(10, 10));
1249 parent_layer_->SetIsDrawable(true);
1250 root->AddChild(parent_layer_);
1252 texture_layer_ = TextureLayer::CreateForMailbox(this);
1253 texture_layer_->SetBounds(gfx::Size(10, 10));
1254 texture_layer_->SetIsDrawable(true);
1255 parent_layer_->AddChild(texture_layer_);
1257 layer_tree_host()->SetRootLayer(root);
1258 LayerTreeTest::SetupTree();
1261 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1263 void DidCommitAndDrawFrame() override {
1264 ++commit_count_;
1265 switch (commit_count_) {
1266 case 1:
1267 // We should have updated the layer, committing the texture.
1268 EXPECT_EQ(1, prepare_called_);
1269 // Make layer invisible.
1270 parent_layer_->SetOpacity(0.f);
1271 break;
1272 case 2:
1273 // Layer shouldn't have been updated.
1274 EXPECT_EQ(1, prepare_called_);
1275 // Change the texture.
1276 mailbox_ = MakeMailbox('2');
1277 mailbox_changed_ = true;
1278 texture_layer_->SetNeedsDisplay();
1279 // Force a change to make sure we draw a frame.
1280 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1281 break;
1282 case 3:
1283 // Layer shouldn't have been updated.
1284 EXPECT_EQ(1, prepare_called_);
1285 // So the old mailbox isn't returned yet.
1286 EXPECT_EQ(0, mailbox_returned_);
1287 // Make layer visible again.
1288 parent_layer_->SetOpacity(1.f);
1289 break;
1290 case 4:
1291 // Layer should have been updated.
1292 EXPECT_EQ(2, prepare_called_);
1293 // So the old mailbox should have been returned already.
1294 EXPECT_EQ(1, mailbox_returned_);
1295 texture_layer_->ClearClient();
1296 break;
1297 case 5:
1298 EXPECT_EQ(2, mailbox_returned_);
1299 EndTest();
1300 break;
1301 default:
1302 NOTREACHED();
1303 break;
1307 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
1308 ASSERT_TRUE(result);
1309 DelegatedFrameData* delegated_frame_data =
1310 output_surface()->last_sent_frame().delegated_frame_data.get();
1311 if (!delegated_frame_data)
1312 return;
1314 // Return all resources immediately.
1315 TransferableResourceArray resources_to_return =
1316 output_surface()->resources_held_by_parent();
1318 CompositorFrameAck ack;
1319 for (size_t i = 0; i < resources_to_return.size(); ++i)
1320 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1321 host_impl->ReclaimResources(&ack);
1324 void AfterTest() override {}
1326 private:
1327 scoped_refptr<SolidColorLayer> solid_layer_;
1328 scoped_refptr<Layer> parent_layer_;
1329 scoped_refptr<TextureLayer> texture_layer_;
1331 // Used on the main thread.
1332 bool mailbox_changed_;
1333 TextureMailbox mailbox_;
1334 int mailbox_returned_;
1335 int prepare_called_;
1336 int commit_count_;
1339 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1341 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1342 // the mailbox back to TextureLayerClient.
1343 class TextureLayerReleaseResourcesBase
1344 : public LayerTreeTest,
1345 public TextureLayerClient {
1346 public:
1347 // TextureLayerClient implementation.
1348 bool PrepareTextureMailbox(
1349 TextureMailbox* mailbox,
1350 scoped_ptr<SingleReleaseCallback>* release_callback,
1351 bool use_shared_memory) override {
1352 *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1353 *release_callback = SingleReleaseCallback::Create(
1354 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1355 base::Unretained(this)));
1356 return true;
1359 void MailboxReleased(unsigned sync_point, bool lost_resource) {
1360 mailbox_released_ = true;
1363 void SetupTree() override {
1364 LayerTreeTest::SetupTree();
1366 scoped_refptr<TextureLayer> texture_layer =
1367 TextureLayer::CreateForMailbox(this);
1368 texture_layer->SetBounds(gfx::Size(10, 10));
1369 texture_layer->SetIsDrawable(true);
1371 layer_tree_host()->root_layer()->AddChild(texture_layer);
1374 void BeginTest() override {
1375 mailbox_released_ = false;
1376 PostSetNeedsCommitToMainThread();
1379 void DidCommitAndDrawFrame() override { EndTest(); }
1381 void AfterTest() override { EXPECT_TRUE(mailbox_released_); }
1383 private:
1384 bool mailbox_released_;
1387 class TextureLayerReleaseResourcesAfterCommit
1388 : public TextureLayerReleaseResourcesBase {
1389 public:
1390 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
1391 LayerTreeImpl* tree = nullptr;
1392 tree = host_impl->sync_tree();
1393 tree->root_layer()->children()[0]->ReleaseResources();
1397 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1399 class TextureLayerReleaseResourcesAfterActivate
1400 : public TextureLayerReleaseResourcesBase {
1401 public:
1402 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
1403 host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
1407 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
1409 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
1410 public:
1411 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1412 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1413 EXPECT_FALSE(lost_resource);
1414 ++callback_count_;
1415 EndTest();
1418 void SetMailbox(char mailbox_char) {
1419 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1420 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1421 base::Bind(
1422 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
1423 base::Unretained(this)));
1424 layer_->SetTextureMailbox(
1425 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1426 callback.Pass());
1429 void SetupTree() override {
1430 gfx::Size bounds(100, 100);
1431 root_ = Layer::Create();
1432 root_->SetBounds(bounds);
1434 layer_ = TextureLayer::CreateForMailbox(nullptr);
1435 layer_->SetIsDrawable(true);
1436 layer_->SetBounds(bounds);
1438 root_->AddChild(layer_);
1439 layer_tree_host()->SetRootLayer(root_);
1440 layer_tree_host()->SetViewportSize(bounds);
1443 void BeginTest() override {
1444 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1446 callback_count_ = 0;
1448 // Set the mailbox on the main thread.
1449 SetMailbox('1');
1450 EXPECT_EQ(0, callback_count_);
1452 PostSetNeedsCommitToMainThread();
1455 void DidCommitAndDrawFrame() override {
1456 switch (layer_tree_host()->source_frame_number()) {
1457 case 1:
1458 // Delete the TextureLayer on the main thread while the mailbox is in
1459 // the impl tree.
1460 layer_->RemoveFromParent();
1461 layer_ = nullptr;
1462 break;
1466 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1468 private:
1469 base::ThreadChecker main_thread_;
1470 int callback_count_;
1471 scoped_refptr<Layer> root_;
1472 scoped_refptr<TextureLayer> layer_;
1475 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1476 TextureLayerWithMailboxMainThreadDeleted);
1478 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
1479 public:
1480 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1481 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1482 EXPECT_FALSE(lost_resource);
1483 ++callback_count_;
1484 EndTest();
1487 void SetMailbox(char mailbox_char) {
1488 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1489 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1490 base::Bind(
1491 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
1492 base::Unretained(this)));
1493 layer_->SetTextureMailbox(
1494 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1495 callback.Pass());
1498 void SetupTree() override {
1499 gfx::Size bounds(100, 100);
1500 root_ = Layer::Create();
1501 root_->SetBounds(bounds);
1503 layer_ = TextureLayer::CreateForMailbox(nullptr);
1504 layer_->SetIsDrawable(true);
1505 layer_->SetBounds(bounds);
1507 root_->AddChild(layer_);
1508 layer_tree_host()->SetRootLayer(root_);
1509 layer_tree_host()->SetViewportSize(bounds);
1512 void BeginTest() override {
1513 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1515 callback_count_ = 0;
1517 // Set the mailbox on the main thread.
1518 SetMailbox('1');
1519 EXPECT_EQ(0, callback_count_);
1521 PostSetNeedsCommitToMainThread();
1524 void DidCommitAndDrawFrame() override {
1525 switch (layer_tree_host()->source_frame_number()) {
1526 case 1:
1527 // Remove the TextureLayer on the main thread while the mailbox is in
1528 // the impl tree, but don't delete the TextureLayer until after the impl
1529 // tree side is deleted.
1530 layer_->RemoveFromParent();
1531 break;
1532 case 2:
1533 layer_ = nullptr;
1534 break;
1538 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
1540 private:
1541 base::ThreadChecker main_thread_;
1542 int callback_count_;
1543 scoped_refptr<Layer> root_;
1544 scoped_refptr<TextureLayer> layer_;
1547 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1548 TextureLayerWithMailboxImplThreadDeleted);
1550 } // namespace
1551 } // namespace cc