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.
4
5 #include "cc/layers/texture_layer.h"
6
7 #include <algorithm>
8 #include <string>
9
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/thread.h"
14 #include "base/time/time.h"
15 #include "cc/layers/solid_color_layer.h"
16 #include "cc/layers/texture_layer_client.h"
17 #include "cc/layers/texture_layer_impl.h"
18 #include "cc/output/compositor_frame_ack.h"
19 #include "cc/output/context_provider.h"
20 #include "cc/resources/returned_resource.h"
21 #include "cc/test/fake_impl_proxy.h"
22 #include "cc/test/fake_layer_tree_host_client.h"
23 #include "cc/test/fake_layer_tree_host_impl.h"
24 #include "cc/test/fake_output_surface.h"
25 #include "cc/test/layer_test_common.h"
26 #include "cc/test/layer_tree_test.h"
27 #include "cc/test/test_web_graphics_context_3d.h"
28 #include "cc/trees/blocking_task_runner.h"
29 #include "cc/trees/layer_tree_host.h"
30 #include "cc/trees/layer_tree_impl.h"
31 #include "cc/trees/single_thread_proxy.h"
32 #include "gpu/GLES2/gl2extchromium.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35
36 using ::testing::Mock;
37 using ::testing::_;
38 using ::testing::AtLeast;
39 using ::testing::AnyNumber;
40
41 namespace cc {
42 namespace {
43
44 class MockLayerTreeHost : public LayerTreeHost {
45 public:
MockLayerTreeHost(FakeLayerTreeHostClient * client)46 explicit MockLayerTreeHost(FakeLayerTreeHostClient* client)
47 : LayerTreeHost(client, NULL, LayerTreeSettings()) {
48 InitializeSingleThreaded(client);
49 }
50
51 MOCK_METHOD0(AcquireLayerTextures, void());
52 MOCK_METHOD0(SetNeedsCommit, void());
53 MOCK_METHOD0(SetNeedsUpdateLayers, void());
54 MOCK_METHOD0(StartRateLimiter, void());
55 MOCK_METHOD0(StopRateLimiter, void());
56 };
57
58 class TextureLayerTest : public testing::Test {
59 public:
TextureLayerTest()60 TextureLayerTest()
61 : fake_client_(
62 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
63 host_impl_(&proxy_) {}
64
65 protected:
SetUp()66 virtual void SetUp() {
67 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
68 }
69
TearDown()70 virtual void TearDown() {
71 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
72 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
73 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
74
75 layer_tree_host_->SetRootLayer(NULL);
76 layer_tree_host_.reset();
77 }
78
79 scoped_ptr<MockLayerTreeHost> layer_tree_host_;
80 FakeImplProxy proxy_;
81 FakeLayerTreeHostClient fake_client_;
82 FakeLayerTreeHostImpl host_impl_;
83 };
84
TEST_F(TextureLayerTest,SyncImplWhenChangingTextureId)85 TEST_F(TextureLayerTest, SyncImplWhenChangingTextureId) {
86 scoped_refptr<TextureLayer> test_layer = TextureLayer::Create(NULL);
87 ASSERT_TRUE(test_layer.get());
88
89 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
90 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
91 layer_tree_host_->SetRootLayer(test_layer);
92 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
93 EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get());
94
95 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
96 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
97 test_layer->SetTextureId(1);
98 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
99
100 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AtLeast(1));
101 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
102 test_layer->SetTextureId(2);
103 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
104
105 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AtLeast(1));
106 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
107 test_layer->SetTextureId(0);
108 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
109 }
110
TEST_F(TextureLayerTest,SyncImplWhenDrawing)111 TEST_F(TextureLayerTest, SyncImplWhenDrawing) {
112 gfx::RectF dirty_rect(0.f, 0.f, 1.f, 1.f);
113
114 scoped_refptr<TextureLayer> test_layer = TextureLayer::Create(NULL);
115 ASSERT_TRUE(test_layer.get());
116 scoped_ptr<TextureLayerImpl> impl_layer;
117 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
118 ASSERT_TRUE(impl_layer);
119
120 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
121 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
122 layer_tree_host_->SetRootLayer(test_layer);
123 test_layer->SetTextureId(1);
124 test_layer->SetIsDrawable(true);
125 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
126 EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get());
127
128 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(1);
129 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(0);
130 test_layer->WillModifyTexture();
131 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
132
133 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
134 EXPECT_CALL(*layer_tree_host_, SetNeedsUpdateLayers()).Times(1);
135 test_layer->SetNeedsDisplayRect(dirty_rect);
136 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
137
138 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
139 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
140 test_layer->PushPropertiesTo(impl_layer.get()); // fake commit
141 test_layer->SetIsDrawable(false);
142 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
143
144 // Verify that non-drawable layers don't signal the compositor,
145 // except for the first draw after last commit, which must acquire
146 // the texture.
147 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(1);
148 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(0);
149 test_layer->WillModifyTexture();
150 test_layer->SetNeedsDisplayRect(dirty_rect);
151 test_layer->PushPropertiesTo(impl_layer.get()); // fake commit
152 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
153
154 // Second draw with layer in non-drawable state: no texture
155 // acquisition.
156 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
157 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(0);
158 test_layer->WillModifyTexture();
159 test_layer->SetNeedsDisplayRect(dirty_rect);
160 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
161 }
162
TEST_F(TextureLayerTest,SyncImplWhenRemovingFromTree)163 TEST_F(TextureLayerTest, SyncImplWhenRemovingFromTree) {
164 scoped_refptr<Layer> root_layer = Layer::Create();
165 ASSERT_TRUE(root_layer.get());
166 scoped_refptr<Layer> child_layer = Layer::Create();
167 ASSERT_TRUE(child_layer.get());
168 root_layer->AddChild(child_layer);
169 scoped_refptr<TextureLayer> test_layer = TextureLayer::Create(NULL);
170 ASSERT_TRUE(test_layer.get());
171 test_layer->SetTextureId(0);
172 child_layer->AddChild(test_layer);
173
174 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
175 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
176 layer_tree_host_->SetRootLayer(root_layer);
177 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
178
179 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
180 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
181 test_layer->RemoveFromParent();
182 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
183
184 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
185 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
186 child_layer->AddChild(test_layer);
187 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
188
189 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
190 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
191 test_layer->SetTextureId(1);
192 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
193
194 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AtLeast(1));
195 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
196 test_layer->RemoveFromParent();
197 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
198 }
199
TEST_F(TextureLayerTest,CheckPropertyChangeCausesCorrectBehavior)200 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) {
201 scoped_refptr<TextureLayer> test_layer = TextureLayer::Create(NULL);
202 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer));
203
204 // Test properties that should call SetNeedsCommit. All properties need to
205 // be set to new values in order for SetNeedsCommit to be called.
206 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false));
207 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV(
208 gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f)));
209 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity(
210 0.5f, 0.5f, 0.5f, 0.5f));
211 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false));
212 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true));
213 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetTextureId(1));
214
215 // Calling SetTextureId can call AcquireLayerTextures.
216 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
217 }
218
TEST_F(TextureLayerTest,VisibleContentOpaqueRegion)219 TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) {
220 const gfx::Size layer_bounds(100, 100);
221 const gfx::Rect layer_rect(layer_bounds);
222 const Region layer_region(layer_rect);
223
224 scoped_refptr<TextureLayer> layer = TextureLayer::Create(NULL);
225 layer->SetBounds(layer_bounds);
226 layer->draw_properties().visible_content_rect = layer_rect;
227 layer->SetBlendBackgroundColor(true);
228
229 // Verify initial conditions.
230 EXPECT_FALSE(layer->contents_opaque());
231 EXPECT_EQ(0u, layer->background_color());
232 EXPECT_EQ(Region().ToString(),
233 layer->VisibleContentOpaqueRegion().ToString());
234
235 // Opaque background.
236 layer->SetBackgroundColor(SK_ColorWHITE);
237 EXPECT_EQ(layer_region.ToString(),
238 layer->VisibleContentOpaqueRegion().ToString());
239
240 // Transparent background.
241 layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
242 EXPECT_EQ(Region().ToString(),
243 layer->VisibleContentOpaqueRegion().ToString());
244 }
245
246 class FakeTextureLayerClient : public TextureLayerClient {
247 public:
FakeTextureLayerClient()248 FakeTextureLayerClient() {}
249
PrepareTexture()250 virtual unsigned PrepareTexture() OVERRIDE {
251 return 0;
252 }
253
PrepareTextureMailbox(TextureMailbox * mailbox,scoped_ptr<SingleReleaseCallback> * release_callback,bool use_shared_memory)254 virtual bool PrepareTextureMailbox(
255 TextureMailbox* mailbox,
256 scoped_ptr<SingleReleaseCallback>* release_callback,
257 bool use_shared_memory) OVERRIDE {
258 *mailbox = TextureMailbox();
259 *release_callback = scoped_ptr<SingleReleaseCallback>();
260 return true;
261 }
262
263 private:
264 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient);
265 };
266
TEST_F(TextureLayerTest,RateLimiter)267 TEST_F(TextureLayerTest, RateLimiter) {
268 FakeTextureLayerClient client;
269 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(
270 &client);
271 test_layer->SetIsDrawable(true);
272 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
273 layer_tree_host_->SetRootLayer(test_layer);
274
275 // Don't rate limit until we invalidate.
276 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
277 test_layer->SetRateLimitContext(true);
278 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
279
280 // Do rate limit after we invalidate.
281 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
282 test_layer->SetNeedsDisplay();
283 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
284
285 // Stop rate limiter when we don't want it any more.
286 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
287 test_layer->SetRateLimitContext(false);
288 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
289
290 // Or we clear the client.
291 test_layer->SetRateLimitContext(true);
292 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
293 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
294 test_layer->ClearClient();
295 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
296
297 // Reset to a layer with a client, that started the rate limiter.
298 test_layer = TextureLayer::CreateForMailbox(
299 &client);
300 test_layer->SetIsDrawable(true);
301 test_layer->SetRateLimitContext(true);
302 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
303 layer_tree_host_->SetRootLayer(test_layer);
304 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
305 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
306 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
307 test_layer->SetNeedsDisplay();
308 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
309
310 // Stop rate limiter when we're removed from the tree.
311 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
312 layer_tree_host_->SetRootLayer(NULL);
313 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
314 }
315
316 class MockMailboxCallback {
317 public:
318 MOCK_METHOD3(Release, void(const std::string& mailbox,
319 unsigned sync_point,
320 bool lost_resource));
321 MOCK_METHOD3(Release2, void(base::SharedMemory* shared_memory,
322 unsigned sync_point,
323 bool lost_resource));
324 };
325
326 struct CommonMailboxObjects {
CommonMailboxObjectscc::__anon6c6d13890111::CommonMailboxObjects327 CommonMailboxObjects()
328 : mailbox_name1_(64, '1'),
329 mailbox_name2_(64, '2'),
330 sync_point1_(1),
331 sync_point2_(2),
332 shared_memory_(new base::SharedMemory) {
333 release_mailbox1_ = base::Bind(&MockMailboxCallback::Release,
334 base::Unretained(&mock_callback_),
335 mailbox_name1_);
336 release_mailbox2_ = base::Bind(&MockMailboxCallback::Release,
337 base::Unretained(&mock_callback_),
338 mailbox_name2_);
339 gpu::Mailbox m1;
340 m1.SetName(reinterpret_cast<const int8*>(mailbox_name1_.data()));
341 mailbox1_ = TextureMailbox(m1, sync_point1_);
342 gpu::Mailbox m2;
343 m2.SetName(reinterpret_cast<const int8*>(mailbox_name2_.data()));
344 mailbox2_ = TextureMailbox(m2, sync_point2_);
345
346 gfx::Size size(128, 128);
347 EXPECT_TRUE(shared_memory_->CreateAndMapAnonymous(4 * size.GetArea()));
348 release_mailbox3_ = base::Bind(&MockMailboxCallback::Release2,
349 base::Unretained(&mock_callback_),
350 shared_memory_.get());
351 mailbox3_ = TextureMailbox(shared_memory_.get(), size);
352 }
353
354 std::string mailbox_name1_;
355 std::string mailbox_name2_;
356 MockMailboxCallback mock_callback_;
357 ReleaseCallback release_mailbox1_;
358 ReleaseCallback release_mailbox2_;
359 ReleaseCallback release_mailbox3_;
360 TextureMailbox mailbox1_;
361 TextureMailbox mailbox2_;
362 TextureMailbox mailbox3_;
363 unsigned sync_point1_;
364 unsigned sync_point2_;
365 scoped_ptr<base::SharedMemory> shared_memory_;
366 };
367
368 class TestMailboxHolder : public TextureLayer::MailboxHolder {
369 public:
370 using TextureLayer::MailboxHolder::Create;
371
372 protected:
~TestMailboxHolder()373 virtual ~TestMailboxHolder() {}
374 };
375
376 class TextureLayerWithMailboxTest : public TextureLayerTest {
377 protected:
TearDown()378 virtual void TearDown() {
379 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
380 EXPECT_CALL(test_data_.mock_callback_,
381 Release(test_data_.mailbox_name1_,
382 test_data_.sync_point1_,
383 false)).Times(1);
384 TextureLayerTest::TearDown();
385 }
386
387 CommonMailboxObjects test_data_;
388 };
389
TEST_F(TextureLayerWithMailboxTest,ReplaceMailboxOnMainThreadBeforeCommit)390 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
391 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
392 ASSERT_TRUE(test_layer.get());
393
394 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
395 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
396 layer_tree_host_->SetRootLayer(test_layer);
397 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
398
399 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
400 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
401 test_layer->SetTextureMailbox(
402 test_data_.mailbox1_,
403 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
404 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
405
406 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
407 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
408 EXPECT_CALL(test_data_.mock_callback_,
409 Release(test_data_.mailbox_name1_,
410 test_data_.sync_point1_,
411 false))
412 .Times(1);
413 test_layer->SetTextureMailbox(
414 test_data_.mailbox2_,
415 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
416 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
417 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
418
419 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
420 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
421 EXPECT_CALL(test_data_.mock_callback_,
422 Release(test_data_.mailbox_name2_,
423 test_data_.sync_point2_,
424 false))
425 .Times(1);
426 test_layer->SetTextureMailbox(TextureMailbox(),
427 scoped_ptr<SingleReleaseCallback>());
428 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
429 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
430
431 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
432 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
433 test_layer->SetTextureMailbox(
434 test_data_.mailbox3_,
435 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
436 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
437 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
438
439 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
440 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
441 EXPECT_CALL(test_data_.mock_callback_,
442 Release2(test_data_.shared_memory_.get(),
443 0, false))
444 .Times(1);
445 test_layer->SetTextureMailbox(TextureMailbox(),
446 scoped_ptr<SingleReleaseCallback>());
447 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
448 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
449
450 // Test destructor.
451 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
452 test_layer->SetTextureMailbox(
453 test_data_.mailbox1_,
454 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
455 }
456
457 class TextureLayerMailboxHolderTest : public TextureLayerTest {
458 public:
TextureLayerMailboxHolderTest()459 TextureLayerMailboxHolderTest()
460 : main_thread_("MAIN") {
461 main_thread_.Start();
462 }
463
Wait(const base::Thread & thread)464 void Wait(const base::Thread& thread) {
465 bool manual_reset = false;
466 bool initially_signaled = false;
467 base::WaitableEvent event(manual_reset, initially_signaled);
468 thread.message_loop()->PostTask(
469 FROM_HERE,
470 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
471 event.Wait();
472 }
473
CreateMainRef()474 void CreateMainRef() {
475 main_ref_ = TestMailboxHolder::Create(
476 test_data_.mailbox1_,
477 SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass();
478 }
479
ReleaseMainRef()480 void ReleaseMainRef() {
481 main_ref_.reset();
482 }
483
CreateImplRef(scoped_ptr<SingleReleaseCallback> * impl_ref)484 void CreateImplRef(scoped_ptr<SingleReleaseCallback>* impl_ref) {
485 *impl_ref = main_ref_->holder()->GetCallbackForImplThread();
486 }
487
CapturePostTasksAndWait(base::WaitableEvent * begin_capture,base::WaitableEvent * wait_for_capture,base::WaitableEvent * stop_capture)488 void CapturePostTasksAndWait(base::WaitableEvent* begin_capture,
489 base::WaitableEvent* wait_for_capture,
490 base::WaitableEvent* stop_capture) {
491 begin_capture->Wait();
492 BlockingTaskRunner::CapturePostTasks capture;
493 wait_for_capture->Signal();
494 stop_capture->Wait();
495 }
496
497 protected:
498 scoped_ptr<TestMailboxHolder::MainThreadReference>
499 main_ref_;
500 base::Thread main_thread_;
501 CommonMailboxObjects test_data_;
502 };
503
TEST_F(TextureLayerMailboxHolderTest,TwoCompositors_BothReleaseThenMain)504 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) {
505 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
506 ASSERT_TRUE(test_layer.get());
507
508 main_thread_.message_loop()->PostTask(
509 FROM_HERE,
510 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
511 base::Unretained(this)));
512
513 Wait(main_thread_);
514
515 // The texture layer is attached to compositor1, and passes a reference to its
516 // impl tree.
517 scoped_ptr<SingleReleaseCallback> compositor1;
518 main_thread_.message_loop()->PostTask(
519 FROM_HERE,
520 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
521 base::Unretained(this),
522 &compositor1));
523
524 // Then the texture layer is removed and attached to compositor2, and passes a
525 // reference to its impl tree.
526 scoped_ptr<SingleReleaseCallback> compositor2;
527 main_thread_.message_loop()->PostTask(
528 FROM_HERE,
529 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
530 base::Unretained(this),
531 &compositor2));
532
533 Wait(main_thread_);
534 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
535
536 // The compositors both destroy their impl trees before the main thread layer
537 // is destroyed.
538 compositor1->Run(100, false);
539 compositor2->Run(200, false);
540
541 Wait(main_thread_);
542
543 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
544 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
545
546 // The main thread ref is the last one, so the mailbox is released back to the
547 // embedder, with the last sync point provided by the impl trees.
548 EXPECT_CALL(test_data_.mock_callback_,
549 Release(test_data_.mailbox_name1_, 200, false)).Times(1);
550
551 main_thread_.message_loop()->PostTask(
552 FROM_HERE,
553 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
554 base::Unretained(this)));
555 Wait(main_thread_);
556 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
557 }
558
TEST_F(TextureLayerMailboxHolderTest,TwoCompositors_MainReleaseBetween)559 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) {
560 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
561 ASSERT_TRUE(test_layer.get());
562
563 main_thread_.message_loop()->PostTask(
564 FROM_HERE,
565 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
566 base::Unretained(this)));
567
568 Wait(main_thread_);
569
570 // The texture layer is attached to compositor1, and passes a reference to its
571 // impl tree.
572 scoped_ptr<SingleReleaseCallback> compositor1;
573 main_thread_.message_loop()->PostTask(
574 FROM_HERE,
575 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
576 base::Unretained(this),
577 &compositor1));
578
579 // Then the texture layer is removed and attached to compositor2, and passes a
580 // reference to its impl tree.
581 scoped_ptr<SingleReleaseCallback> compositor2;
582 main_thread_.message_loop()->PostTask(
583 FROM_HERE,
584 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
585 base::Unretained(this),
586 &compositor2));
587
588 Wait(main_thread_);
589 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
590
591 // One compositor destroys their impl tree.
592 compositor1->Run(100, false);
593
594 // Then the main thread reference is destroyed.
595 main_thread_.message_loop()->PostTask(
596 FROM_HERE,
597 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
598 base::Unretained(this)));
599
600 Wait(main_thread_);
601
602 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
603 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
604
605 // The second impl reference is destroyed last, causing the mailbox to be
606 // released back to the embedder with the last sync point from the impl tree.
607 EXPECT_CALL(test_data_.mock_callback_,
608 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
609
610 compositor2->Run(200, true);
611 Wait(main_thread_);
612 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
613 }
614
TEST_F(TextureLayerMailboxHolderTest,TwoCompositors_MainReleasedFirst)615 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) {
616 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
617 ASSERT_TRUE(test_layer.get());
618
619 main_thread_.message_loop()->PostTask(
620 FROM_HERE,
621 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
622 base::Unretained(this)));
623
624 Wait(main_thread_);
625
626 // The texture layer is attached to compositor1, and passes a reference to its
627 // impl tree.
628 scoped_ptr<SingleReleaseCallback> compositor1;
629 main_thread_.message_loop()->PostTask(
630 FROM_HERE,
631 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
632 base::Unretained(this),
633 &compositor1));
634
635 // Then the texture layer is removed and attached to compositor2, and passes a
636 // reference to its impl tree.
637 scoped_ptr<SingleReleaseCallback> compositor2;
638 main_thread_.message_loop()->PostTask(
639 FROM_HERE,
640 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
641 base::Unretained(this),
642 &compositor2));
643
644 Wait(main_thread_);
645 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
646
647 // The main thread reference is destroyed first.
648 main_thread_.message_loop()->PostTask(
649 FROM_HERE,
650 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
651 base::Unretained(this)));
652
653 // One compositor destroys their impl tree.
654 compositor2->Run(200, false);
655
656 Wait(main_thread_);
657
658 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
659 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
660
661 // The second impl reference is destroyed last, causing the mailbox to be
662 // released back to the embedder with the last sync point from the impl tree.
663 EXPECT_CALL(test_data_.mock_callback_,
664 Release(test_data_.mailbox_name1_, 100, true)).Times(1);
665
666 compositor1->Run(100, true);
667 Wait(main_thread_);
668 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
669 }
670
TEST_F(TextureLayerMailboxHolderTest,TwoCompositors_SecondImplRefShortcut)671 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) {
672 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
673 ASSERT_TRUE(test_layer.get());
674
675 main_thread_.message_loop()->PostTask(
676 FROM_HERE,
677 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
678 base::Unretained(this)));
679
680 Wait(main_thread_);
681
682 // The texture layer is attached to compositor1, and passes a reference to its
683 // impl tree.
684 scoped_ptr<SingleReleaseCallback> compositor1;
685 main_thread_.message_loop()->PostTask(
686 FROM_HERE,
687 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
688 base::Unretained(this),
689 &compositor1));
690
691 // Then the texture layer is removed and attached to compositor2, and passes a
692 // reference to its impl tree.
693 scoped_ptr<SingleReleaseCallback> compositor2;
694 main_thread_.message_loop()->PostTask(
695 FROM_HERE,
696 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
697 base::Unretained(this),
698 &compositor2));
699
700 Wait(main_thread_);
701 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
702
703 // The main thread reference is destroyed first.
704 main_thread_.message_loop()->PostTask(
705 FROM_HERE,
706 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
707 base::Unretained(this)));
708
709 EXPECT_CALL(test_data_.mock_callback_,
710 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
711
712 bool manual_reset = false;
713 bool initially_signaled = false;
714 base::WaitableEvent begin_capture(manual_reset, initially_signaled);
715 base::WaitableEvent wait_for_capture(manual_reset, initially_signaled);
716 base::WaitableEvent stop_capture(manual_reset, initially_signaled);
717
718 // Post a task to start capturing tasks on the main thread. This will block
719 // the main thread until we signal the |stop_capture| event.
720 main_thread_.message_loop()->PostTask(
721 FROM_HERE,
722 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait,
723 base::Unretained(this),
724 &begin_capture,
725 &wait_for_capture,
726 &stop_capture));
727
728 // Before the main thread capturing starts, one compositor destroys their
729 // impl reference. Since capturing did not start, this gets post-tasked to
730 // the main thread.
731 compositor1->Run(100, false);
732
733 // Start capturing on the main thread.
734 begin_capture.Signal();
735 wait_for_capture.Wait();
736
737 // Meanwhile, the second compositor released its impl reference, but this task
738 // gets shortcutted directly to the main thread. This means the reference is
739 // released before compositor1, whose reference will be released later when
740 // the post-task is serviced. But since it was destroyed _on the impl thread_
741 // last, its sync point values should be used.
742 compositor2->Run(200, true);
743
744 stop_capture.Signal();
745 Wait(main_thread_);
746
747 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
748 }
749
750 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest {
751 public:
TextureLayerImplWithMailboxThreadedCallback()752 TextureLayerImplWithMailboxThreadedCallback()
753 : callback_count_(0),
754 commit_count_(0) {}
755
756 // Make sure callback is received on main and doesn't block the impl thread.
ReleaseCallback(unsigned sync_point,bool lost_resource)757 void ReleaseCallback(unsigned sync_point, bool lost_resource) {
758 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
759 EXPECT_FALSE(lost_resource);
760 ++callback_count_;
761 }
762
SetMailbox(char mailbox_char)763 void SetMailbox(char mailbox_char) {
764 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
765 TextureMailbox mailbox(std::string(64, mailbox_char));
766 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
767 base::Bind(
768 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback,
769 base::Unretained(this)));
770 layer_->SetTextureMailbox(mailbox, callback.Pass());
771 }
772
BeginTest()773 virtual void BeginTest() OVERRIDE {
774 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
775
776 gfx::Size bounds(100, 100);
777 root_ = Layer::Create();
778 root_->SetAnchorPoint(gfx::PointF());
779 root_->SetBounds(bounds);
780
781 layer_ = TextureLayer::CreateForMailbox(NULL);
782 layer_->SetIsDrawable(true);
783 layer_->SetAnchorPoint(gfx::PointF());
784 layer_->SetBounds(bounds);
785
786 root_->AddChild(layer_);
787 layer_tree_host()->SetRootLayer(root_);
788 layer_tree_host()->SetViewportSize(bounds);
789 SetMailbox('1');
790 EXPECT_EQ(0, callback_count_);
791
792 // Case #1: change mailbox before the commit. The old mailbox should be
793 // released immediately.
794 SetMailbox('2');
795 EXPECT_EQ(1, callback_count_);
796 PostSetNeedsCommitToMainThread();
797 }
798
DidCommit()799 virtual void DidCommit() OVERRIDE {
800 ++commit_count_;
801 switch (commit_count_) {
802 case 1:
803 // Case #2: change mailbox after the commit (and draw), where the
804 // layer draws. The old mailbox should be released during the next
805 // commit.
806 SetMailbox('3');
807 EXPECT_EQ(1, callback_count_);
808 break;
809 case 2:
810 EXPECT_EQ(2, callback_count_);
811 // Case #3: change mailbox when the layer doesn't draw. The old
812 // mailbox should be released during the next commit.
813 layer_->SetBounds(gfx::Size());
814 SetMailbox('4');
815 break;
816 case 3:
817 EXPECT_EQ(3, callback_count_);
818 // Case #4: release mailbox that was committed but never drawn. The
819 // old mailbox should be released during the next commit.
820 layer_->SetTextureMailbox(TextureMailbox(),
821 scoped_ptr<SingleReleaseCallback>());
822 break;
823 case 4:
824 if (layer_tree_host()->settings().impl_side_painting) {
825 // With impl painting, the texture mailbox will still be on the impl
826 // thread when the commit finishes, because the layer is not drawble
827 // when it has no texture mailbox, and thus does not block the commit
828 // on activation. So, we wait for activation.
829 // TODO(danakj): fix this. crbug.com/277953
830 layer_tree_host()->SetNeedsCommit();
831 break;
832 } else {
833 ++commit_count_;
834 }
835 case 5:
836 EXPECT_EQ(4, callback_count_);
837 // Restore a mailbox for the next step.
838 SetMailbox('5');
839 break;
840 case 6:
841 // Case #5: remove layer from tree. Callback should *not* be called, the
842 // mailbox is returned to the main thread.
843 EXPECT_EQ(4, callback_count_);
844 layer_->RemoveFromParent();
845 break;
846 case 7:
847 if (layer_tree_host()->settings().impl_side_painting) {
848 // With impl painting, the texture mailbox will still be on the impl
849 // thread when the commit finishes, because the layer is not around to
850 // block the commit on activation anymore. So, we wait for activation.
851 // TODO(danakj): fix this. crbug.com/277953
852 layer_tree_host()->SetNeedsCommit();
853 break;
854 } else {
855 ++commit_count_;
856 }
857 case 8:
858 EXPECT_EQ(4, callback_count_);
859 // Resetting the mailbox will call the callback now.
860 layer_->SetTextureMailbox(TextureMailbox(),
861 scoped_ptr<SingleReleaseCallback>());
862 EXPECT_EQ(5, callback_count_);
863 EndTest();
864 break;
865 default:
866 NOTREACHED();
867 break;
868 }
869 }
870
AfterTest()871 virtual void AfterTest() OVERRIDE {}
872
873 private:
874 base::ThreadChecker main_thread_;
875 int callback_count_;
876 int commit_count_;
877 scoped_refptr<Layer> root_;
878 scoped_refptr<TextureLayer> layer_;
879 };
880
881 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
882 TextureLayerImplWithMailboxThreadedCallback);
883
884
885 class TextureLayerNoMailboxIsActivatedDuringCommit : public LayerTreeTest,
886 public TextureLayerClient {
887 protected:
TextureLayerNoMailboxIsActivatedDuringCommit()888 TextureLayerNoMailboxIsActivatedDuringCommit()
889 : wait_thread_("WAIT"),
890 wait_event_(false, false),
891 texture_(0u) {
892 wait_thread_.Start();
893 }
894
BeginTest()895 virtual void BeginTest() OVERRIDE {
896 activate_count_ = 0;
897
898 gfx::Size bounds(100, 100);
899 root_ = Layer::Create();
900 root_->SetAnchorPoint(gfx::PointF());
901 root_->SetBounds(bounds);
902
903 layer_ = TextureLayer::Create(this);
904 layer_->SetIsDrawable(true);
905 layer_->SetAnchorPoint(gfx::PointF());
906 layer_->SetBounds(bounds);
907
908 root_->AddChild(layer_);
909 layer_tree_host()->SetRootLayer(root_);
910 layer_tree_host()->SetViewportSize(bounds);
911
912 PostSetNeedsCommitToMainThread();
913 }
914
CreateOutputSurface(bool fallback)915 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
916 OVERRIDE {
917 scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
918 texture_ = provider->UnboundTestContext3d()->createExternalTexture();
919 return FakeOutputSurface::Create3d(provider).PassAs<OutputSurface>();
920 }
921
922 // TextureLayerClient implementation.
PrepareTexture()923 virtual unsigned PrepareTexture() OVERRIDE {
924 return texture_;
925 }
PrepareTextureMailbox(TextureMailbox * mailbox,scoped_ptr<SingleReleaseCallback> * release_callback,bool use_shared_memory)926 virtual bool PrepareTextureMailbox(
927 TextureMailbox* mailbox,
928 scoped_ptr<SingleReleaseCallback>* release_callback,
929 bool use_shared_memory) OVERRIDE {
930 return false;
931 }
932
WillActivateTreeOnThread(LayerTreeHostImpl * impl)933 virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
934 // Slow down activation so the main thread DidCommit() will run if
935 // not blocked.
936 wait_thread_.message_loop()->PostDelayedTask(
937 FROM_HERE,
938 base::Bind(&base::WaitableEvent::Signal,
939 base::Unretained(&wait_event_)),
940 base::TimeDelta::FromMilliseconds(10));
941 wait_event_.Wait();
942
943 base::AutoLock lock(activate_lock_);
944 ++activate_count_;
945 }
946
DidActivateTreeOnThread(LayerTreeHostImpl * impl)947 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
948 // The main thread is awake now, and will run DidCommit() immediately.
949 // Run DidActivate() afterwards by posting it now.
950 proxy()->MainThreadTaskRunner()->PostTask(
951 FROM_HERE,
952 base::Bind(&TextureLayerNoMailboxIsActivatedDuringCommit::DidActivate,
953 base::Unretained(this)));
954 }
955
DidActivate()956 void DidActivate() {
957 base::AutoLock lock(activate_lock_);
958 switch (activate_count_) {
959 case 1:
960 // The first texture has been activated. Invalidate the layer so it
961 // grabs a new texture id from the client.
962 layer_->SetNeedsDisplay();
963 // So this commit number should complete after the second activate.
964 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
965 break;
966 case 2:
967 // The second mailbox has been activated. Remove the layer from
968 // the tree to cause another commit/activation. The commit should
969 // finish *after* the layer is removed from the active tree.
970 layer_->RemoveFromParent();
971 // So this commit number should complete after the third activate.
972 EXPECT_EQ(2, layer_tree_host()->source_frame_number());
973 break;
974 case 3:
975 EndTest();
976 break;
977 }
978 }
979
DidCommit()980 virtual void DidCommit() OVERRIDE {
981 switch (layer_tree_host()->source_frame_number()) {
982 case 2: {
983 // The activate for the 2nd texture should have happened before now.
984 base::AutoLock lock(activate_lock_);
985 EXPECT_EQ(2, activate_count_);
986 break;
987 }
988 case 3: {
989 // The activate to remove the layer should have happened before now.
990 base::AutoLock lock(activate_lock_);
991 EXPECT_EQ(3, activate_count_);
992 break;
993 }
994 }
995 }
996
997
AfterTest()998 virtual void AfterTest() OVERRIDE {}
999
1000 base::Thread wait_thread_;
1001 base::WaitableEvent wait_event_;
1002 base::Lock activate_lock_;
1003 unsigned texture_;
1004 int activate_count_;
1005 scoped_refptr<Layer> root_;
1006 scoped_refptr<TextureLayer> layer_;
1007 };
1008
1009 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1010 TextureLayerNoMailboxIsActivatedDuringCommit);
1011
1012 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
1013 protected:
TextureLayerMailboxIsActivatedDuringCommit()1014 TextureLayerMailboxIsActivatedDuringCommit()
1015 : wait_thread_("WAIT"),
1016 wait_event_(false, false) {
1017 wait_thread_.Start();
1018 }
1019
ReleaseCallback(unsigned sync_point,bool lost_resource)1020 static void ReleaseCallback(unsigned sync_point, bool lost_resource) {}
1021
SetMailbox(char mailbox_char)1022 void SetMailbox(char mailbox_char) {
1023 TextureMailbox mailbox(std::string(64, mailbox_char));
1024 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1025 base::Bind(
1026 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
1027 layer_->SetTextureMailbox(mailbox, callback.Pass());
1028 }
1029
BeginTest()1030 virtual void BeginTest() OVERRIDE {
1031 activate_count_ = 0;
1032
1033 gfx::Size bounds(100, 100);
1034 root_ = Layer::Create();
1035 root_->SetAnchorPoint(gfx::PointF());
1036 root_->SetBounds(bounds);
1037
1038 layer_ = TextureLayer::CreateForMailbox(NULL);
1039 layer_->SetIsDrawable(true);
1040 layer_->SetAnchorPoint(gfx::PointF());
1041 layer_->SetBounds(bounds);
1042
1043 root_->AddChild(layer_);
1044 layer_tree_host()->SetRootLayer(root_);
1045 layer_tree_host()->SetViewportSize(bounds);
1046 SetMailbox('1');
1047
1048 PostSetNeedsCommitToMainThread();
1049 }
1050
WillActivateTreeOnThread(LayerTreeHostImpl * impl)1051 virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1052 // Slow down activation so the main thread DidCommit() will run if
1053 // not blocked.
1054 wait_thread_.message_loop()->PostDelayedTask(
1055 FROM_HERE,
1056 base::Bind(&base::WaitableEvent::Signal,
1057 base::Unretained(&wait_event_)),
1058 base::TimeDelta::FromMilliseconds(10));
1059 wait_event_.Wait();
1060
1061 base::AutoLock lock(activate_lock_);
1062 ++activate_count_;
1063 }
1064
DidActivateTreeOnThread(LayerTreeHostImpl * impl)1065 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1066 // The main thread is awake now, and will run DidCommit() immediately.
1067 // Run DidActivate() afterwards by posting it now.
1068 proxy()->MainThreadTaskRunner()->PostTask(
1069 FROM_HERE,
1070 base::Bind(&TextureLayerMailboxIsActivatedDuringCommit::DidActivate,
1071 base::Unretained(this)));
1072 }
1073
DidActivate()1074 void DidActivate() {
1075 base::AutoLock lock(activate_lock_);
1076 switch (activate_count_) {
1077 case 1:
1078 // The first mailbox has been activated. Set a new mailbox, and
1079 // expect the next commit to finish *after* it is activated.
1080 SetMailbox('2');
1081 // So this commit number should complete after the second activate.
1082 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1083 break;
1084 case 2:
1085 // The second mailbox has been activated. Remove the layer from
1086 // the tree to cause another commit/activation. The commit should
1087 // finish *after* the layer is removed from the active tree.
1088 layer_->RemoveFromParent();
1089 // So this commit number should complete after the third activate.
1090 EXPECT_EQ(2, layer_tree_host()->source_frame_number());
1091 break;
1092 case 3:
1093 EndTest();
1094 break;
1095 }
1096 }
1097
DidCommit()1098 virtual void DidCommit() OVERRIDE {
1099 switch (layer_tree_host()->source_frame_number()) {
1100 case 2: {
1101 // The activate for the 2nd mailbox should have happened before now.
1102 base::AutoLock lock(activate_lock_);
1103 EXPECT_EQ(2, activate_count_);
1104 break;
1105 }
1106 case 3: {
1107 // The activate to remove the layer should have happened before now.
1108 base::AutoLock lock(activate_lock_);
1109 EXPECT_EQ(3, activate_count_);
1110 break;
1111 }
1112 }
1113 }
1114
1115
AfterTest()1116 virtual void AfterTest() OVERRIDE {}
1117
1118 base::Thread wait_thread_;
1119 base::WaitableEvent wait_event_;
1120 base::Lock activate_lock_;
1121 int activate_count_;
1122 scoped_refptr<Layer> root_;
1123 scoped_refptr<TextureLayer> layer_;
1124 };
1125
1126 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1127 TextureLayerMailboxIsActivatedDuringCommit);
1128
1129 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
1130 protected:
TextureLayerImplWithMailboxTest()1131 TextureLayerImplWithMailboxTest()
1132 : fake_client_(
1133 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
1134
SetUp()1135 virtual void SetUp() {
1136 TextureLayerTest::SetUp();
1137 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
1138 EXPECT_TRUE(host_impl_.InitializeRenderer(CreateFakeOutputSurface()));
1139 }
1140
WillDraw(TextureLayerImpl * layer,DrawMode mode)1141 bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
1142 bool will_draw = layer->WillDraw(
1143 mode, host_impl_.active_tree()->resource_provider());
1144 if (will_draw)
1145 layer->DidDraw(host_impl_.active_tree()->resource_provider());
1146 return will_draw;
1147 }
1148
1149 CommonMailboxObjects test_data_;
1150 FakeLayerTreeHostClient fake_client_;
1151 };
1152
1153 // Test conditions for results of TextureLayerImpl::WillDraw under
1154 // different configurations of different mailbox, texture_id, and draw_mode.
TEST_F(TextureLayerImplWithMailboxTest,TestWillDraw)1155 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
1156 EXPECT_CALL(test_data_.mock_callback_,
1157 Release(test_data_.mailbox_name1_,
1158 test_data_.sync_point1_,
1159 false))
1160 .Times(AnyNumber());
1161 EXPECT_CALL(test_data_.mock_callback_,
1162 Release2(test_data_.shared_memory_.get(), 0, false))
1163 .Times(AnyNumber());
1164 // Hardware mode.
1165 {
1166 scoped_ptr<TextureLayerImpl> impl_layer =
1167 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1168 impl_layer->SetDrawsContent(true);
1169 impl_layer->SetTextureMailbox(
1170 test_data_.mailbox1_,
1171 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1172 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1173 }
1174
1175 {
1176 scoped_ptr<TextureLayerImpl> impl_layer =
1177 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1178 impl_layer->SetDrawsContent(true);
1179 impl_layer->SetTextureMailbox(TextureMailbox(),
1180 scoped_ptr<SingleReleaseCallback>());
1181 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1182 }
1183
1184 {
1185 // Software resource.
1186 scoped_ptr<TextureLayerImpl> impl_layer =
1187 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1188 impl_layer->SetDrawsContent(true);
1189 impl_layer->SetTextureMailbox(
1190 test_data_.mailbox3_,
1191 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
1192 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1193 }
1194
1195 {
1196 scoped_ptr<TextureLayerImpl> impl_layer =
1197 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1198 impl_layer->SetDrawsContent(true);
1199 ContextProvider* context_provider =
1200 host_impl_.output_surface()->context_provider();
1201 unsigned texture =
1202 context_provider->Context3d()->createTexture();
1203 impl_layer->set_texture_id(texture);
1204 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1205 }
1206
1207 {
1208 scoped_ptr<TextureLayerImpl> impl_layer =
1209 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1210 impl_layer->SetDrawsContent(true);
1211 impl_layer->set_texture_id(0);
1212 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1213 }
1214
1215 // Software mode.
1216 {
1217 scoped_ptr<TextureLayerImpl> impl_layer =
1218 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1219 impl_layer->SetDrawsContent(true);
1220 impl_layer->SetTextureMailbox(
1221 test_data_.mailbox1_,
1222 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1223 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1224 }
1225
1226 {
1227 scoped_ptr<TextureLayerImpl> impl_layer =
1228 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1229 impl_layer->SetDrawsContent(true);
1230 impl_layer->SetTextureMailbox(TextureMailbox(),
1231 scoped_ptr<SingleReleaseCallback>());
1232 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1233 }
1234
1235 {
1236 // Software resource.
1237 scoped_ptr<TextureLayerImpl> impl_layer =
1238 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1239 impl_layer->SetDrawsContent(true);
1240 impl_layer->SetTextureMailbox(
1241 test_data_.mailbox3_,
1242 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
1243 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1244 }
1245
1246 {
1247 scoped_ptr<TextureLayerImpl> impl_layer =
1248 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1249 impl_layer->SetDrawsContent(true);
1250 ContextProvider* context_provider =
1251 host_impl_.output_surface()->context_provider();
1252 unsigned texture =
1253 context_provider->Context3d()->createTexture();
1254 impl_layer->set_texture_id(texture);
1255 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1256 }
1257
1258 {
1259 scoped_ptr<TextureLayerImpl> impl_layer =
1260 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1261 impl_layer->SetDrawsContent(true);
1262 impl_layer->set_texture_id(0);
1263 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1264 }
1265
1266 // Resourceless software mode.
1267 {
1268 scoped_ptr<TextureLayerImpl> impl_layer =
1269 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1270 impl_layer->SetDrawsContent(true);
1271 impl_layer->SetTextureMailbox(
1272 test_data_.mailbox1_,
1273 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1274 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
1275 }
1276
1277 {
1278 scoped_ptr<TextureLayerImpl> impl_layer =
1279 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1280 impl_layer->SetDrawsContent(true);
1281 ContextProvider* context_provider =
1282 host_impl_.output_surface()->context_provider();
1283 unsigned texture =
1284 context_provider->Context3d()->createTexture();
1285 impl_layer->set_texture_id(texture);
1286 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
1287 }
1288 }
1289
TEST_F(TextureLayerImplWithMailboxTest,TestImplLayerCallbacks)1290 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
1291 host_impl_.CreatePendingTree();
1292 scoped_ptr<TextureLayerImpl> pending_layer;
1293 pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1, true);
1294 ASSERT_TRUE(pending_layer);
1295
1296 scoped_ptr<LayerImpl> active_layer(
1297 pending_layer->CreateLayerImpl(host_impl_.active_tree()));
1298 ASSERT_TRUE(active_layer);
1299
1300 pending_layer->SetTextureMailbox(
1301 test_data_.mailbox1_,
1302 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1303
1304 // Test multiple commits without an activation.
1305 EXPECT_CALL(test_data_.mock_callback_,
1306 Release(test_data_.mailbox_name1_,
1307 test_data_.sync_point1_,
1308 false))
1309 .Times(1);
1310 pending_layer->SetTextureMailbox(
1311 test_data_.mailbox2_,
1312 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
1313 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1314
1315 // Test callback after activation.
1316 pending_layer->PushPropertiesTo(active_layer.get());
1317 active_layer->DidBecomeActive();
1318
1319 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1320 pending_layer->SetTextureMailbox(
1321 test_data_.mailbox1_,
1322 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1323 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1324
1325 EXPECT_CALL(test_data_.mock_callback_,
1326 Release(test_data_.mailbox_name2_, _, false))
1327 .Times(1);
1328 pending_layer->PushPropertiesTo(active_layer.get());
1329 active_layer->DidBecomeActive();
1330 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1331
1332 // Test resetting the mailbox.
1333 EXPECT_CALL(test_data_.mock_callback_,
1334 Release(test_data_.mailbox_name1_, _, false))
1335 .Times(1);
1336 pending_layer->SetTextureMailbox(TextureMailbox(),
1337 scoped_ptr<SingleReleaseCallback>());
1338 pending_layer->PushPropertiesTo(active_layer.get());
1339 active_layer->DidBecomeActive();
1340 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1341
1342 // Test destructor.
1343 EXPECT_CALL(test_data_.mock_callback_,
1344 Release(test_data_.mailbox_name1_,
1345 test_data_.sync_point1_,
1346 false))
1347 .Times(1);
1348 pending_layer->SetTextureMailbox(
1349 test_data_.mailbox1_,
1350 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1351 }
1352
TEST_F(TextureLayerImplWithMailboxTest,TestDestructorCallbackOnCreatedResource)1353 TEST_F(TextureLayerImplWithMailboxTest,
1354 TestDestructorCallbackOnCreatedResource) {
1355 scoped_ptr<TextureLayerImpl> impl_layer;
1356 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1357 ASSERT_TRUE(impl_layer);
1358
1359 EXPECT_CALL(test_data_.mock_callback_,
1360 Release(test_data_.mailbox_name1_, _, false))
1361 .Times(1);
1362 impl_layer->SetTextureMailbox(
1363 test_data_.mailbox1_,
1364 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1365 impl_layer->SetDrawsContent(true);
1366 impl_layer->DidBecomeActive();
1367 EXPECT_TRUE(impl_layer->WillDraw(
1368 DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1369 impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1370 impl_layer->SetTextureMailbox(TextureMailbox(),
1371 scoped_ptr<SingleReleaseCallback>());
1372 }
1373
TEST_F(TextureLayerImplWithMailboxTest,TestCallbackOnInUseResource)1374 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1375 ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1376 ResourceProvider::ResourceId id =
1377 provider->CreateResourceFromTextureMailbox(
1378 test_data_.mailbox1_,
1379 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1380 provider->AllocateForTesting(id);
1381
1382 // Transfer some resources to the parent.
1383 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1384 resource_ids_to_transfer.push_back(id);
1385 TransferableResourceArray list;
1386 provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1387 EXPECT_TRUE(provider->InUseByConsumer(id));
1388 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1389 provider->DeleteResource(id);
1390 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1391 EXPECT_CALL(test_data_.mock_callback_,
1392 Release(test_data_.mailbox_name1_, _, false))
1393 .Times(1);
1394 ReturnedResourceArray returned;
1395 TransferableResource::ReturnResources(list, &returned);
1396 provider->ReceiveReturnsFromParent(returned);
1397 }
1398
1399 // Check that ClearClient correctly clears the state so that the impl side
1400 // doesn't try to use a texture that could have been destroyed.
1401 class TextureLayerClientTest
1402 : public LayerTreeTest,
1403 public TextureLayerClient {
1404 public:
TextureLayerClientTest()1405 TextureLayerClientTest()
1406 : texture_(0),
1407 commit_count_(0),
1408 expected_used_textures_on_draw_(0),
1409 expected_used_textures_on_commit_(0) {}
1410
CreateOutputSurface(bool fallback)1411 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
1412 OVERRIDE {
1413 scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
1414 texture_ = provider->UnboundTestContext3d()->createExternalTexture();
1415 return FakeOutputSurface::Create3d(provider).PassAs<OutputSurface>();
1416 }
1417
PrepareTexture()1418 virtual unsigned PrepareTexture() OVERRIDE { return texture_; }
1419
PrepareTextureMailbox(TextureMailbox * mailbox,scoped_ptr<SingleReleaseCallback> * release_callback,bool use_shared_memory)1420 virtual bool PrepareTextureMailbox(
1421 TextureMailbox* mailbox,
1422 scoped_ptr<SingleReleaseCallback>* release_callback,
1423 bool use_shared_memory) OVERRIDE {
1424 return false;
1425 }
1426
SetupTree()1427 virtual void SetupTree() OVERRIDE {
1428 scoped_refptr<Layer> root = Layer::Create();
1429 root->SetBounds(gfx::Size(10, 10));
1430 root->SetAnchorPoint(gfx::PointF());
1431 root->SetIsDrawable(true);
1432
1433 texture_layer_ = TextureLayer::Create(this);
1434 texture_layer_->SetBounds(gfx::Size(10, 10));
1435 texture_layer_->SetAnchorPoint(gfx::PointF());
1436 texture_layer_->SetIsDrawable(true);
1437 root->AddChild(texture_layer_);
1438
1439 layer_tree_host()->SetRootLayer(root);
1440 LayerTreeTest::SetupTree();
1441 {
1442 base::AutoLock lock(lock_);
1443 expected_used_textures_on_commit_ = 1;
1444 }
1445 }
1446
BeginTest()1447 virtual void BeginTest() OVERRIDE {
1448 PostSetNeedsCommitToMainThread();
1449 }
1450
DidCommitAndDrawFrame()1451 virtual void DidCommitAndDrawFrame() OVERRIDE {
1452 ++commit_count_;
1453 switch (commit_count_) {
1454 case 1:
1455 texture_layer_->ClearClient();
1456 texture_layer_->SetNeedsDisplay();
1457 {
1458 base::AutoLock lock(lock_);
1459 expected_used_textures_on_commit_ = 0;
1460 }
1461 break;
1462 case 2:
1463 EndTest();
1464 break;
1465 default:
1466 NOTREACHED();
1467 break;
1468 }
1469 }
1470
BeginCommitOnThread(LayerTreeHostImpl * host_impl)1471 virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1472 base::AutoLock lock(lock_);
1473 expected_used_textures_on_draw_ = expected_used_textures_on_commit_;
1474 }
1475
PrepareToDrawOnThread(LayerTreeHostImpl * host_impl,LayerTreeHostImpl::FrameData * frame_data,bool result)1476 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1477 LayerTreeHostImpl::FrameData* frame_data,
1478 bool result) OVERRIDE {
1479 ContextForImplThread(host_impl)->ResetUsedTextures();
1480 return true;
1481 }
1482
SwapBuffersOnThread(LayerTreeHostImpl * host_impl,bool result)1483 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1484 bool result) OVERRIDE {
1485 ASSERT_TRUE(result);
1486 EXPECT_EQ(expected_used_textures_on_draw_,
1487 ContextForImplThread(host_impl)->NumUsedTextures());
1488 }
1489
AfterTest()1490 virtual void AfterTest() OVERRIDE {}
1491
1492 private:
ContextForImplThread(LayerTreeHostImpl * host_impl)1493 TestWebGraphicsContext3D* ContextForImplThread(LayerTreeHostImpl* host_impl) {
1494 return static_cast<TestWebGraphicsContext3D*>(
1495 host_impl->output_surface()->context_provider()->Context3d());
1496 }
1497
1498 scoped_refptr<TextureLayer> texture_layer_;
1499 unsigned texture_;
1500 int commit_count_;
1501
1502 // Used only on thread.
1503 unsigned expected_used_textures_on_draw_;
1504
1505 // Used on either thread, protected by lock_.
1506 base::Lock lock_;
1507 unsigned expected_used_textures_on_commit_;
1508 };
1509
1510 // The TextureLayerClient does not use mailboxes, so can't use a delegating
1511 // renderer.
1512 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerClientTest);
1513
1514
1515 // Checks that changing a texture in the client for a TextureLayer that's
1516 // invisible correctly works without drawing a deleted texture. See
1517 // crbug.com/266628
1518 class TextureLayerChangeInvisibleTest
1519 : public LayerTreeTest,
1520 public TextureLayerClient {
1521 public:
TextureLayerChangeInvisibleTest()1522 TextureLayerChangeInvisibleTest()
1523 : texture_(0u),
1524 prepare_called_(0),
1525 commit_count_(0),
1526 expected_texture_on_draw_(0) {}
1527
CreateOutputSurface(bool fallback)1528 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
1529 OVERRIDE {
1530 scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
1531 texture_ = provider->UnboundTestContext3d()->createExternalTexture();
1532 return FakeOutputSurface::Create3d(provider).PassAs<OutputSurface>();
1533 }
1534
1535 // TextureLayerClient implementation.
PrepareTexture()1536 virtual unsigned PrepareTexture() OVERRIDE {
1537 ++prepare_called_;
1538 return texture_;
1539 }
PrepareTextureMailbox(TextureMailbox * mailbox,scoped_ptr<SingleReleaseCallback> * release_callback,bool use_shared_memory)1540 virtual bool PrepareTextureMailbox(
1541 TextureMailbox* mailbox,
1542 scoped_ptr<SingleReleaseCallback>* release_callback,
1543 bool use_shared_memory) OVERRIDE {
1544 return false;
1545 }
1546
SetupTree()1547 virtual void SetupTree() OVERRIDE {
1548 scoped_refptr<Layer> root = Layer::Create();
1549 root->SetBounds(gfx::Size(10, 10));
1550 root->SetAnchorPoint(gfx::PointF());
1551 root->SetIsDrawable(true);
1552
1553 solid_layer_ = SolidColorLayer::Create();
1554 solid_layer_->SetBounds(gfx::Size(10, 10));
1555 solid_layer_->SetIsDrawable(true);
1556 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1557 root->AddChild(solid_layer_);
1558
1559 parent_layer_ = Layer::Create();
1560 parent_layer_->SetBounds(gfx::Size(10, 10));
1561 parent_layer_->SetIsDrawable(true);
1562 root->AddChild(parent_layer_);
1563
1564 texture_layer_ = TextureLayer::Create(this);
1565 texture_layer_->SetBounds(gfx::Size(10, 10));
1566 texture_layer_->SetAnchorPoint(gfx::PointF());
1567 texture_layer_->SetIsDrawable(true);
1568 parent_layer_->AddChild(texture_layer_);
1569
1570 layer_tree_host()->SetRootLayer(root);
1571 LayerTreeTest::SetupTree();
1572 }
1573
BeginTest()1574 virtual void BeginTest() OVERRIDE {
1575 PostSetNeedsCommitToMainThread();
1576 }
1577
DidCommitAndDrawFrame()1578 virtual void DidCommitAndDrawFrame() OVERRIDE {
1579 ++commit_count_;
1580 switch (commit_count_) {
1581 case 1:
1582 // We should have updated the layer, committing the texture.
1583 EXPECT_EQ(1, prepare_called_);
1584 // Make layer invisible.
1585 parent_layer_->SetOpacity(0.f);
1586 break;
1587 case 2: {
1588 // Layer shouldn't have been updated.
1589 EXPECT_EQ(1, prepare_called_);
1590 texture_layer_->SetNeedsDisplay();
1591 // Force a change to make sure we draw a frame.
1592 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1593 break;
1594 }
1595 case 3:
1596 EXPECT_EQ(1, prepare_called_);
1597 // Make layer visible again.
1598 parent_layer_->SetOpacity(1.f);
1599 break;
1600 case 4: {
1601 // Layer should have been updated.
1602 EXPECT_EQ(2, prepare_called_);
1603 texture_layer_->ClearClient();
1604 texture_ = 0;
1605 break;
1606 }
1607 case 5:
1608 EndTest();
1609 break;
1610 default:
1611 NOTREACHED();
1612 break;
1613 }
1614 }
1615
BeginCommitOnThread(LayerTreeHostImpl * host_impl)1616 virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1617 ASSERT_TRUE(proxy()->IsMainThreadBlocked());
1618 // This is the only texture that can be drawn this frame.
1619 expected_texture_on_draw_ = texture_;
1620 }
1621
PrepareToDrawOnThread(LayerTreeHostImpl * host_impl,LayerTreeHostImpl::FrameData * frame_data,bool result)1622 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1623 LayerTreeHostImpl::FrameData* frame_data,
1624 bool result) OVERRIDE {
1625 ContextForImplThread(host_impl)->ResetUsedTextures();
1626 return true;
1627 }
1628
SwapBuffersOnThread(LayerTreeHostImpl * host_impl,bool result)1629 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1630 bool result) OVERRIDE {
1631 ASSERT_TRUE(result);
1632 TestWebGraphicsContext3D* context = ContextForImplThread(host_impl);
1633 int used_textures = context->NumUsedTextures();
1634 switch (host_impl->active_tree()->source_frame_number()) {
1635 case 0:
1636 EXPECT_EQ(1, used_textures);
1637 EXPECT_TRUE(context->UsedTexture(expected_texture_on_draw_));
1638 break;
1639 case 1:
1640 case 2:
1641 EXPECT_EQ(0, used_textures);
1642 break;
1643 case 3:
1644 EXPECT_EQ(1, used_textures);
1645 EXPECT_TRUE(context->UsedTexture(expected_texture_on_draw_));
1646 break;
1647 default:
1648 break;
1649 }
1650 }
1651
AfterTest()1652 virtual void AfterTest() OVERRIDE {}
1653
1654 private:
ContextForImplThread(LayerTreeHostImpl * host_impl)1655 TestWebGraphicsContext3D* ContextForImplThread(LayerTreeHostImpl* host_impl) {
1656 return static_cast<TestWebGraphicsContext3D*>(
1657 host_impl->output_surface()->context_provider()->Context3d());
1658 }
1659
1660 scoped_refptr<SolidColorLayer> solid_layer_;
1661 scoped_refptr<Layer> parent_layer_;
1662 scoped_refptr<TextureLayer> texture_layer_;
1663
1664 // Used on the main thread, and on the impl thread while the main thread is
1665 // blocked.
1666 unsigned texture_;
1667
1668 // Used on the main thread.
1669 int prepare_called_;
1670 int commit_count_;
1671
1672 // Used on the compositor thread.
1673 unsigned expected_texture_on_draw_;
1674 };
1675
1676 // The TextureLayerChangeInvisibleTest does not use mailboxes, so can't use a
1677 // delegating renderer.
1678 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerChangeInvisibleTest);
1679
1680 // Checks that TextureLayer::Update does not cause an extra commit when setting
1681 // the texture mailbox.
1682 class TextureLayerNoExtraCommitForMailboxTest
1683 : public LayerTreeTest,
1684 public TextureLayerClient {
1685 public:
1686 // TextureLayerClient implementation.
PrepareTexture()1687 virtual unsigned PrepareTexture() OVERRIDE {
1688 NOTREACHED();
1689 return 0;
1690 }
PrepareTextureMailbox(TextureMailbox * mailbox,scoped_ptr<SingleReleaseCallback> * release_callback,bool use_shared_memory)1691 virtual bool PrepareTextureMailbox(
1692 TextureMailbox* mailbox,
1693 scoped_ptr<SingleReleaseCallback>* release_callback,
1694 bool use_shared_memory) OVERRIDE {
1695 if (layer_tree_host()->source_frame_number() == 1) {
1696 *mailbox = TextureMailbox();
1697 return true;
1698 }
1699
1700 *mailbox = TextureMailbox(std::string(64, '1'));
1701 *release_callback = SingleReleaseCallback::Create(
1702 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1703 base::Unretained(this)));
1704 return true;
1705 }
1706
MailboxReleased(unsigned sync_point,bool lost_resource)1707 void MailboxReleased(unsigned sync_point, bool lost_resource) {
1708 EXPECT_EQ(2, layer_tree_host()->source_frame_number());
1709 EndTest();
1710 }
1711
SetupTree()1712 virtual void SetupTree() OVERRIDE {
1713 scoped_refptr<Layer> root = Layer::Create();
1714 root->SetBounds(gfx::Size(10, 10));
1715 root->SetAnchorPoint(gfx::PointF());
1716 root->SetIsDrawable(true);
1717
1718 texture_layer_ = TextureLayer::CreateForMailbox(this);
1719 texture_layer_->SetBounds(gfx::Size(10, 10));
1720 texture_layer_->SetAnchorPoint(gfx::PointF());
1721 texture_layer_->SetIsDrawable(true);
1722 root->AddChild(texture_layer_);
1723
1724 layer_tree_host()->SetRootLayer(root);
1725 LayerTreeTest::SetupTree();
1726 }
1727
BeginTest()1728 virtual void BeginTest() OVERRIDE {
1729 PostSetNeedsCommitToMainThread();
1730 }
1731
DidCommitAndDrawFrame()1732 virtual void DidCommitAndDrawFrame() OVERRIDE {
1733 switch (layer_tree_host()->source_frame_number()) {
1734 case 1:
1735 EXPECT_FALSE(proxy()->CommitPendingForTesting());
1736 // Invalidate the texture layer to clear the mailbox before
1737 // ending the test.
1738 texture_layer_->SetNeedsDisplay();
1739 break;
1740 case 2:
1741 break;
1742 default:
1743 NOTREACHED();
1744 break;
1745 }
1746 }
1747
SwapBuffersOnThread(LayerTreeHostImpl * host_impl,bool result)1748 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1749 bool result) OVERRIDE {
1750 ASSERT_TRUE(result);
1751 DelegatedFrameData* delegated_frame_data =
1752 output_surface()->last_sent_frame().delegated_frame_data.get();
1753 if (!delegated_frame_data)
1754 return;
1755
1756 // Return all resources immediately.
1757 TransferableResourceArray resources_to_return =
1758 output_surface()->resources_held_by_parent();
1759
1760 CompositorFrameAck ack;
1761 for (size_t i = 0; i < resources_to_return.size(); ++i)
1762 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1763 host_impl->ReclaimResources(&ack);
1764 host_impl->OnSwapBuffersComplete();
1765 }
1766
AfterTest()1767 virtual void AfterTest() OVERRIDE {}
1768
1769 private:
1770 scoped_refptr<TextureLayer> texture_layer_;
1771 };
1772
1773 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1774
1775 // Checks that changing a mailbox in the client for a TextureLayer that's
1776 // invisible correctly works and uses the new mailbox as soon as the layer
1777 // becomes visible (and returns the old one).
1778 class TextureLayerChangeInvisibleMailboxTest
1779 : public LayerTreeTest,
1780 public TextureLayerClient {
1781 public:
TextureLayerChangeInvisibleMailboxTest()1782 TextureLayerChangeInvisibleMailboxTest()
1783 : mailbox_changed_(true),
1784 mailbox_returned_(0),
1785 prepare_called_(0),
1786 commit_count_(0) {
1787 mailbox_ = MakeMailbox('1');
1788 }
1789
1790 // TextureLayerClient implementation.
PrepareTexture()1791 virtual unsigned PrepareTexture() OVERRIDE {
1792 NOTREACHED();
1793 return 0;
1794 }
1795
PrepareTextureMailbox(TextureMailbox * mailbox,scoped_ptr<SingleReleaseCallback> * release_callback,bool use_shared_memory)1796 virtual bool PrepareTextureMailbox(
1797 TextureMailbox* mailbox,
1798 scoped_ptr<SingleReleaseCallback>* release_callback,
1799 bool use_shared_memory) OVERRIDE {
1800 ++prepare_called_;
1801 if (!mailbox_changed_)
1802 return false;
1803 *mailbox = mailbox_;
1804 *release_callback = SingleReleaseCallback::Create(
1805 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1806 base::Unretained(this)));
1807 return true;
1808 }
1809
MakeMailbox(char name)1810 TextureMailbox MakeMailbox(char name) {
1811 return TextureMailbox(std::string(64, name));
1812 }
1813
MailboxReleased(unsigned sync_point,bool lost_resource)1814 void MailboxReleased(unsigned sync_point, bool lost_resource) {
1815 ++mailbox_returned_;
1816 }
1817
SetupTree()1818 virtual void SetupTree() OVERRIDE {
1819 scoped_refptr<Layer> root = Layer::Create();
1820 root->SetBounds(gfx::Size(10, 10));
1821 root->SetAnchorPoint(gfx::PointF());
1822 root->SetIsDrawable(true);
1823
1824 solid_layer_ = SolidColorLayer::Create();
1825 solid_layer_->SetBounds(gfx::Size(10, 10));
1826 solid_layer_->SetIsDrawable(true);
1827 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1828 root->AddChild(solid_layer_);
1829
1830 parent_layer_ = Layer::Create();
1831 parent_layer_->SetBounds(gfx::Size(10, 10));
1832 parent_layer_->SetIsDrawable(true);
1833 root->AddChild(parent_layer_);
1834
1835 texture_layer_ = TextureLayer::CreateForMailbox(this);
1836 texture_layer_->SetBounds(gfx::Size(10, 10));
1837 texture_layer_->SetAnchorPoint(gfx::PointF());
1838 texture_layer_->SetIsDrawable(true);
1839 parent_layer_->AddChild(texture_layer_);
1840
1841 layer_tree_host()->SetRootLayer(root);
1842 LayerTreeTest::SetupTree();
1843 }
1844
BeginTest()1845 virtual void BeginTest() OVERRIDE {
1846 PostSetNeedsCommitToMainThread();
1847 }
1848
DidCommitAndDrawFrame()1849 virtual void DidCommitAndDrawFrame() OVERRIDE {
1850 ++commit_count_;
1851 switch (commit_count_) {
1852 case 1:
1853 // We should have updated the layer, committing the texture.
1854 EXPECT_EQ(1, prepare_called_);
1855 // Make layer invisible.
1856 parent_layer_->SetOpacity(0.f);
1857 break;
1858 case 2:
1859 // Layer shouldn't have been updated.
1860 EXPECT_EQ(1, prepare_called_);
1861 // Change the texture.
1862 mailbox_ = MakeMailbox('2');
1863 mailbox_changed_ = true;
1864 texture_layer_->SetNeedsDisplay();
1865 // Force a change to make sure we draw a frame.
1866 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1867 break;
1868 case 3:
1869 // Layer shouldn't have been updated.
1870 EXPECT_EQ(1, prepare_called_);
1871 // So the old mailbox isn't returned yet.
1872 EXPECT_EQ(0, mailbox_returned_);
1873 // Make layer visible again.
1874 parent_layer_->SetOpacity(1.f);
1875 break;
1876 case 4:
1877 // Layer should have been updated.
1878 EXPECT_EQ(2, prepare_called_);
1879 // So the old mailbox should have been returned already.
1880 EXPECT_EQ(1, mailbox_returned_);
1881 texture_layer_->ClearClient();
1882 break;
1883 case 5:
1884 EXPECT_EQ(2, mailbox_returned_);
1885 EndTest();
1886 break;
1887 default:
1888 NOTREACHED();
1889 break;
1890 }
1891 }
1892
SwapBuffersOnThread(LayerTreeHostImpl * host_impl,bool result)1893 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1894 bool result) OVERRIDE {
1895 ASSERT_TRUE(result);
1896 DelegatedFrameData* delegated_frame_data =
1897 output_surface()->last_sent_frame().delegated_frame_data.get();
1898 if (!delegated_frame_data)
1899 return;
1900
1901 // Return all resources immediately.
1902 TransferableResourceArray resources_to_return =
1903 output_surface()->resources_held_by_parent();
1904
1905 CompositorFrameAck ack;
1906 for (size_t i = 0; i < resources_to_return.size(); ++i)
1907 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1908 host_impl->ReclaimResources(&ack);
1909 host_impl->OnSwapBuffersComplete();
1910 }
1911
AfterTest()1912 virtual void AfterTest() OVERRIDE {}
1913
1914 private:
1915 scoped_refptr<SolidColorLayer> solid_layer_;
1916 scoped_refptr<Layer> parent_layer_;
1917 scoped_refptr<TextureLayer> texture_layer_;
1918
1919 // Used on the main thread.
1920 bool mailbox_changed_;
1921 TextureMailbox mailbox_;
1922 int mailbox_returned_;
1923 int prepare_called_;
1924 int commit_count_;
1925 };
1926
1927 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1928
1929 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1930 // the mailbox back to TextureLayerClient.
1931 class TextureLayerReleaseResourcesBase
1932 : public LayerTreeTest,
1933 public TextureLayerClient {
1934 public:
1935 // TextureLayerClient implementation.
PrepareTexture()1936 virtual unsigned PrepareTexture() OVERRIDE {
1937 NOTREACHED();
1938 return 0;
1939 }
PrepareTextureMailbox(TextureMailbox * mailbox,scoped_ptr<SingleReleaseCallback> * release_callback,bool use_shared_memory)1940 virtual bool PrepareTextureMailbox(
1941 TextureMailbox* mailbox,
1942 scoped_ptr<SingleReleaseCallback>* release_callback,
1943 bool use_shared_memory) OVERRIDE {
1944 *mailbox = TextureMailbox(std::string(64, '1'));
1945 *release_callback = SingleReleaseCallback::Create(
1946 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1947 base::Unretained(this)));
1948 return true;
1949 }
1950
MailboxReleased(unsigned sync_point,bool lost_resource)1951 void MailboxReleased(unsigned sync_point, bool lost_resource) {
1952 mailbox_released_ = true;
1953 }
1954
SetupTree()1955 virtual void SetupTree() OVERRIDE {
1956 LayerTreeTest::SetupTree();
1957
1958 scoped_refptr<TextureLayer> texture_layer =
1959 TextureLayer::CreateForMailbox(this);
1960 texture_layer->SetBounds(gfx::Size(10, 10));
1961 texture_layer->SetAnchorPoint(gfx::PointF());
1962 texture_layer->SetIsDrawable(true);
1963
1964 layer_tree_host()->root_layer()->AddChild(texture_layer);
1965 }
1966
BeginTest()1967 virtual void BeginTest() OVERRIDE {
1968 mailbox_released_ = false;
1969 PostSetNeedsCommitToMainThread();
1970 }
1971
DidCommitAndDrawFrame()1972 virtual void DidCommitAndDrawFrame() OVERRIDE {
1973 EndTest();
1974 }
1975
AfterTest()1976 virtual void AfterTest() OVERRIDE {
1977 EXPECT_TRUE(mailbox_released_);
1978 }
1979
1980 private:
1981 bool mailbox_released_;
1982 };
1983
1984 class TextureLayerReleaseResourcesAfterCommit
1985 : public TextureLayerReleaseResourcesBase {
1986 public:
CommitCompleteOnThread(LayerTreeHostImpl * host_impl)1987 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1988 LayerTreeImpl* tree = NULL;
1989 if (host_impl->settings().impl_side_painting)
1990 tree = host_impl->pending_tree();
1991 else
1992 tree = host_impl->active_tree();
1993 tree->root_layer()->children()[0]->ReleaseResources();
1994 }
1995 };
1996
1997 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1998
1999 class TextureLayerReleaseResourcesAfterActivate
2000 : public TextureLayerReleaseResourcesBase {
2001 public:
DidActivateTreeOnThread(LayerTreeHostImpl * host_impl)2002 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
2003 host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
2004 }
2005 };
2006
2007 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
2008
2009 // Test recovering from a lost context.
2010 class TextureLayerLostContextTest
2011 : public LayerTreeTest,
2012 public TextureLayerClient {
2013 public:
TextureLayerLostContextTest()2014 TextureLayerLostContextTest()
2015 : context_lost_(false),
2016 draw_count_(0) {}
2017
CreateOutputSurface(bool fallback)2018 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
2019 OVERRIDE {
2020 return CreateFakeOutputSurface();
2021 }
2022
PrepareTexture()2023 virtual unsigned PrepareTexture() OVERRIDE {
2024 if (draw_count_ == 0)
2025 context_lost_ = true;
2026 if (context_lost_)
2027 return 0u;
2028 return 1u;
2029 }
2030
PrepareTextureMailbox(TextureMailbox * mailbox,scoped_ptr<SingleReleaseCallback> * release_callback,bool use_shared_memory)2031 virtual bool PrepareTextureMailbox(
2032 TextureMailbox* mailbox,
2033 scoped_ptr<SingleReleaseCallback>* release_callback,
2034 bool use_shared_memory) OVERRIDE {
2035 return false;
2036 }
2037
SetupTree()2038 virtual void SetupTree() OVERRIDE {
2039 scoped_refptr<Layer> root = Layer::Create();
2040 root->SetBounds(gfx::Size(10, 10));
2041 root->SetIsDrawable(true);
2042
2043 texture_layer_ = TextureLayer::Create(this);
2044 texture_layer_->SetBounds(gfx::Size(10, 10));
2045 texture_layer_->SetIsDrawable(true);
2046 root->AddChild(texture_layer_);
2047
2048 layer_tree_host()->SetRootLayer(root);
2049 LayerTreeTest::SetupTree();
2050 }
2051
BeginTest()2052 virtual void BeginTest() OVERRIDE {
2053 PostSetNeedsCommitToMainThread();
2054 }
2055
PrepareToDrawOnThread(LayerTreeHostImpl * host_impl,LayerTreeHostImpl::FrameData * frame_data,bool result)2056 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
2057 LayerTreeHostImpl::FrameData* frame_data,
2058 bool result) OVERRIDE {
2059 LayerImpl* root = host_impl->RootLayer();
2060 TextureLayerImpl* texture_layer =
2061 static_cast<TextureLayerImpl*>(root->children()[0]);
2062 if (++draw_count_ == 1)
2063 EXPECT_EQ(0u, texture_layer->texture_id());
2064 else
2065 EXPECT_EQ(1u, texture_layer->texture_id());
2066 return true;
2067 }
2068
DidCommitAndDrawFrame()2069 virtual void DidCommitAndDrawFrame() OVERRIDE {
2070 EndTest();
2071 }
2072
AfterTest()2073 virtual void AfterTest() OVERRIDE {}
2074
2075 private:
2076 scoped_refptr<TextureLayer> texture_layer_;
2077 bool context_lost_;
2078 int draw_count_;
2079 };
2080
2081 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerLostContextTest);
2082
2083 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
2084 public:
ReleaseCallback(unsigned sync_point,bool lost_resource)2085 void ReleaseCallback(unsigned sync_point, bool lost_resource) {
2086 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2087 EXPECT_FALSE(lost_resource);
2088 ++callback_count_;
2089 EndTest();
2090 }
2091
SetMailbox(char mailbox_char)2092 void SetMailbox(char mailbox_char) {
2093 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2094 TextureMailbox mailbox(std::string(64, mailbox_char));
2095 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2096 base::Bind(
2097 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
2098 base::Unretained(this)));
2099 layer_->SetTextureMailbox(mailbox, callback.Pass());
2100 }
2101
SetupTree()2102 virtual void SetupTree() OVERRIDE {
2103 gfx::Size bounds(100, 100);
2104 root_ = Layer::Create();
2105 root_->SetAnchorPoint(gfx::PointF());
2106 root_->SetBounds(bounds);
2107
2108 layer_ = TextureLayer::CreateForMailbox(NULL);
2109 layer_->SetIsDrawable(true);
2110 layer_->SetAnchorPoint(gfx::PointF());
2111 layer_->SetBounds(bounds);
2112
2113 root_->AddChild(layer_);
2114 layer_tree_host()->SetRootLayer(root_);
2115 layer_tree_host()->SetViewportSize(bounds);
2116 }
2117
BeginTest()2118 virtual void BeginTest() OVERRIDE {
2119 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2120
2121 callback_count_ = 0;
2122
2123 // Set the mailbox on the main thread.
2124 SetMailbox('1');
2125 EXPECT_EQ(0, callback_count_);
2126
2127 PostSetNeedsCommitToMainThread();
2128 }
2129
DidCommitAndDrawFrame()2130 virtual void DidCommitAndDrawFrame() OVERRIDE {
2131 switch (layer_tree_host()->source_frame_number()) {
2132 case 1:
2133 // Delete the TextureLayer on the main thread while the mailbox is in
2134 // the impl tree.
2135 layer_->RemoveFromParent();
2136 layer_ = NULL;
2137 break;
2138 }
2139 }
2140
AfterTest()2141 virtual void AfterTest() OVERRIDE {
2142 EXPECT_EQ(1, callback_count_);
2143 }
2144
2145 private:
2146 base::ThreadChecker main_thread_;
2147 int callback_count_;
2148 scoped_refptr<Layer> root_;
2149 scoped_refptr<TextureLayer> layer_;
2150 };
2151
2152 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
2153 TextureLayerWithMailboxMainThreadDeleted);
2154
2155 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
2156 public:
ReleaseCallback(unsigned sync_point,bool lost_resource)2157 void ReleaseCallback(unsigned sync_point, bool lost_resource) {
2158 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2159 EXPECT_FALSE(lost_resource);
2160 ++callback_count_;
2161 EndTest();
2162 }
2163
SetMailbox(char mailbox_char)2164 void SetMailbox(char mailbox_char) {
2165 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2166 TextureMailbox mailbox(std::string(64, mailbox_char));
2167 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2168 base::Bind(
2169 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
2170 base::Unretained(this)));
2171 layer_->SetTextureMailbox(mailbox, callback.Pass());
2172 }
2173
SetupTree()2174 virtual void SetupTree() OVERRIDE {
2175 gfx::Size bounds(100, 100);
2176 root_ = Layer::Create();
2177 root_->SetAnchorPoint(gfx::PointF());
2178 root_->SetBounds(bounds);
2179
2180 layer_ = TextureLayer::CreateForMailbox(NULL);
2181 layer_->SetIsDrawable(true);
2182 layer_->SetAnchorPoint(gfx::PointF());
2183 layer_->SetBounds(bounds);
2184
2185 root_->AddChild(layer_);
2186 layer_tree_host()->SetRootLayer(root_);
2187 layer_tree_host()->SetViewportSize(bounds);
2188 }
2189
BeginTest()2190 virtual void BeginTest() OVERRIDE {
2191 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2192
2193 callback_count_ = 0;
2194
2195 // Set the mailbox on the main thread.
2196 SetMailbox('1');
2197 EXPECT_EQ(0, callback_count_);
2198
2199 PostSetNeedsCommitToMainThread();
2200 }
2201
DidCommitAndDrawFrame()2202 virtual void DidCommitAndDrawFrame() OVERRIDE {
2203 switch (layer_tree_host()->source_frame_number()) {
2204 case 1:
2205 // Remove the TextureLayer on the main thread while the mailbox is in
2206 // the impl tree, but don't delete the TextureLayer until after the impl
2207 // tree side is deleted.
2208 layer_->RemoveFromParent();
2209 break;
2210 case 2:
2211 layer_ = NULL;
2212 break;
2213 }
2214 }
2215
AfterTest()2216 virtual void AfterTest() OVERRIDE {
2217 EXPECT_EQ(1, callback_count_);
2218 }
2219
2220 private:
2221 base::ThreadChecker main_thread_;
2222 int callback_count_;
2223 scoped_refptr<Layer> root_;
2224 scoped_refptr<TextureLayer> layer_;
2225 };
2226
2227 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
2228 TextureLayerWithMailboxImplThreadDeleted);
2229
2230 } // namespace
2231 } // namespace cc
2232