• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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