Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / cc / layers / texture_layer_unittest.cc
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:
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:
60   TextureLayerTest()
61       : fake_client_(
62           FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
63         host_impl_(&proxy_) {}
64
65  protected:
66   virtual void SetUp() {
67     layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
68   }
69
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
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
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
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
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
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:
248   FakeTextureLayerClient() {}
249
250   virtual unsigned PrepareTexture() OVERRIDE {
251     return 0;
252   }
253
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
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 {
327   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:
373   virtual ~TestMailboxHolder() {}
374 };
375
376 class TextureLayerWithMailboxTest : public TextureLayerTest {
377  protected:
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
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:
459   TextureLayerMailboxHolderTest()
460       : main_thread_("MAIN") {
461     main_thread_.Start();
462   }
463
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
474   void CreateMainRef() {
475     main_ref_ = TestMailboxHolder::Create(
476         test_data_.mailbox1_,
477         SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass();
478   }
479
480   void ReleaseMainRef() {
481     main_ref_.reset();
482   }
483
484   void CreateImplRef(scoped_ptr<SingleReleaseCallback>* impl_ref) {
485     *impl_ref = main_ref_->holder()->GetCallbackForImplThread();
486   }
487
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
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
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
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
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:
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.
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
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
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
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
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:
888   TextureLayerNoMailboxIsActivatedDuringCommit()
889       : texture_(0u), activate_count_(0) {}
890
891   virtual void BeginTest() OVERRIDE {
892     gfx::Size bounds(100, 100);
893     root_ = Layer::Create();
894     root_->SetAnchorPoint(gfx::PointF());
895     root_->SetBounds(bounds);
896
897     layer_ = TextureLayer::Create(this);
898     layer_->SetIsDrawable(true);
899     layer_->SetAnchorPoint(gfx::PointF());
900     layer_->SetBounds(bounds);
901
902     root_->AddChild(layer_);
903     layer_tree_host()->SetRootLayer(root_);
904     layer_tree_host()->SetViewportSize(bounds);
905
906     PostSetNeedsCommitToMainThread();
907   }
908
909   virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
910       OVERRIDE {
911     scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
912     texture_ = provider->UnboundTestContext3d()->createExternalTexture();
913     return FakeOutputSurface::Create3d(provider).PassAs<OutputSurface>();
914   }
915
916   // TextureLayerClient implementation.
917   virtual unsigned PrepareTexture() OVERRIDE {
918     return texture_;
919   }
920   virtual bool PrepareTextureMailbox(
921       TextureMailbox* mailbox,
922       scoped_ptr<SingleReleaseCallback>* release_callback,
923       bool use_shared_memory) OVERRIDE {
924     return false;
925   }
926
927   virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
928     ++activate_count_;
929   }
930
931   virtual void DidCommit() OVERRIDE {
932     switch (layer_tree_host()->source_frame_number()) {
933       case 1:
934         // The first texture has been activated. Invalidate the layer so it
935         // grabs a new texture id from the client.
936         layer_->SetNeedsDisplay();
937         break;
938       case 2:
939         // The second mailbox has been activated. Remove the layer from
940         // the tree to cause another commit/activation. The commit should
941         // finish *after* the layer is removed from the active tree.
942         layer_->RemoveFromParent();
943         break;
944       case 3:
945         EndTest();
946         break;
947     }
948   }
949
950   virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
951     switch (host_impl->active_tree()->source_frame_number()) {
952       case 2: {
953         // The activate for the 2nd texture should have happened before now.
954         EXPECT_EQ(2, activate_count_);
955         break;
956       }
957       case 3: {
958         // The activate to remove the layer should have happened before now.
959         EXPECT_EQ(3, activate_count_);
960         break;
961       }
962     }
963   }
964
965   virtual void AfterTest() OVERRIDE {}
966
967   unsigned texture_;
968   int activate_count_;
969   scoped_refptr<Layer> root_;
970   scoped_refptr<TextureLayer> layer_;
971 };
972
973 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
974     TextureLayerNoMailboxIsActivatedDuringCommit);
975
976 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
977  protected:
978   TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
979
980   static void ReleaseCallback(unsigned sync_point, bool lost_resource) {}
981
982   void SetMailbox(char mailbox_char) {
983     TextureMailbox mailbox(std::string(64, mailbox_char));
984     scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
985         base::Bind(
986             &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
987     layer_->SetTextureMailbox(mailbox, callback.Pass());
988   }
989
990   virtual void BeginTest() OVERRIDE {
991     gfx::Size bounds(100, 100);
992     root_ = Layer::Create();
993     root_->SetAnchorPoint(gfx::PointF());
994     root_->SetBounds(bounds);
995
996     layer_ = TextureLayer::CreateForMailbox(NULL);
997     layer_->SetIsDrawable(true);
998     layer_->SetAnchorPoint(gfx::PointF());
999     layer_->SetBounds(bounds);
1000
1001     root_->AddChild(layer_);
1002     layer_tree_host()->SetRootLayer(root_);
1003     layer_tree_host()->SetViewportSize(bounds);
1004     SetMailbox('1');
1005
1006     PostSetNeedsCommitToMainThread();
1007   }
1008
1009   virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1010     ++activate_count_;
1011   }
1012
1013   virtual void DidCommit() OVERRIDE {
1014     switch (layer_tree_host()->source_frame_number()) {
1015       case 1:
1016         // The first mailbox has been activated. Set a new mailbox, and
1017         // expect the next commit to finish *after* it is activated.
1018         SetMailbox('2');
1019         break;
1020       case 2:
1021         // The second mailbox has been activated. Remove the layer from
1022         // the tree to cause another commit/activation. The commit should
1023         // finish *after* the layer is removed from the active tree.
1024         layer_->RemoveFromParent();
1025         break;
1026       case 3:
1027         EndTest();
1028         break;
1029     }
1030   }
1031
1032   virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1033     switch (host_impl->active_tree()->source_frame_number()) {
1034       case 2: {
1035         // The activate for the 2nd mailbox should have happened before now.
1036         EXPECT_EQ(2, activate_count_);
1037         break;
1038       }
1039       case 3: {
1040         // The activate to remove the layer should have happened before now.
1041         EXPECT_EQ(3, activate_count_);
1042         break;
1043       }
1044     }
1045   }
1046
1047
1048   virtual void AfterTest() OVERRIDE {}
1049
1050   int activate_count_;
1051   scoped_refptr<Layer> root_;
1052   scoped_refptr<TextureLayer> layer_;
1053 };
1054
1055 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1056     TextureLayerMailboxIsActivatedDuringCommit);
1057
1058 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
1059  protected:
1060   TextureLayerImplWithMailboxTest()
1061       : fake_client_(
1062           FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
1063
1064   virtual void SetUp() {
1065     TextureLayerTest::SetUp();
1066     layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
1067     EXPECT_TRUE(host_impl_.InitializeRenderer(CreateFakeOutputSurface()));
1068   }
1069
1070   bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
1071     bool will_draw = layer->WillDraw(
1072         mode, host_impl_.active_tree()->resource_provider());
1073     if (will_draw)
1074       layer->DidDraw(host_impl_.active_tree()->resource_provider());
1075     return will_draw;
1076   }
1077
1078   CommonMailboxObjects test_data_;
1079   FakeLayerTreeHostClient fake_client_;
1080 };
1081
1082 // Test conditions for results of TextureLayerImpl::WillDraw under
1083 // different configurations of different mailbox, texture_id, and draw_mode.
1084 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
1085   EXPECT_CALL(test_data_.mock_callback_,
1086               Release(test_data_.mailbox_name1_,
1087                       test_data_.sync_point1_,
1088                       false))
1089       .Times(AnyNumber());
1090   EXPECT_CALL(test_data_.mock_callback_,
1091               Release2(test_data_.shared_memory_.get(), 0, false))
1092       .Times(AnyNumber());
1093   // Hardware mode.
1094   {
1095     scoped_ptr<TextureLayerImpl> impl_layer =
1096         TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1097     impl_layer->SetDrawsContent(true);
1098     impl_layer->SetTextureMailbox(
1099         test_data_.mailbox1_,
1100         SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1101     EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1102   }
1103
1104   {
1105     scoped_ptr<TextureLayerImpl> impl_layer =
1106         TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1107     impl_layer->SetDrawsContent(true);
1108     impl_layer->SetTextureMailbox(TextureMailbox(),
1109                                   scoped_ptr<SingleReleaseCallback>());
1110     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1111   }
1112
1113   {
1114     // Software resource.
1115     scoped_ptr<TextureLayerImpl> impl_layer =
1116         TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1117     impl_layer->SetDrawsContent(true);
1118     impl_layer->SetTextureMailbox(
1119         test_data_.mailbox3_,
1120         SingleReleaseCallback::Create(test_data_.release_mailbox3_));
1121     EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1122   }
1123
1124   {
1125     scoped_ptr<TextureLayerImpl> impl_layer =
1126         TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1127     impl_layer->SetDrawsContent(true);
1128     ContextProvider* context_provider =
1129         host_impl_.output_surface()->context_provider();
1130     GLuint texture = 0;
1131     context_provider->ContextGL()->GenTextures(1, &texture);
1132     impl_layer->SetTextureId(texture);
1133     EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1134   }
1135
1136   {
1137     scoped_ptr<TextureLayerImpl> impl_layer =
1138         TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1139     impl_layer->SetDrawsContent(true);
1140     impl_layer->SetTextureId(0);
1141     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1142   }
1143
1144   // Software mode.
1145   {
1146     scoped_ptr<TextureLayerImpl> impl_layer =
1147         TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1148     impl_layer->SetDrawsContent(true);
1149     impl_layer->SetTextureMailbox(
1150         test_data_.mailbox1_,
1151         SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1152     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1153   }
1154
1155   {
1156     scoped_ptr<TextureLayerImpl> impl_layer =
1157         TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1158     impl_layer->SetDrawsContent(true);
1159     impl_layer->SetTextureMailbox(TextureMailbox(),
1160                                   scoped_ptr<SingleReleaseCallback>());
1161     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1162   }
1163
1164   {
1165     // Software resource.
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_.mailbox3_,
1171         SingleReleaseCallback::Create(test_data_.release_mailbox3_));
1172     EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1173   }
1174
1175   {
1176     scoped_ptr<TextureLayerImpl> impl_layer =
1177         TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1178     impl_layer->SetDrawsContent(true);
1179     ContextProvider* context_provider =
1180         host_impl_.output_surface()->context_provider();
1181     GLuint texture = 0;
1182     context_provider->ContextGL()->GenTextures(1, &texture);
1183     impl_layer->SetTextureId(texture);
1184     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1185   }
1186
1187   {
1188     scoped_ptr<TextureLayerImpl> impl_layer =
1189         TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1190     impl_layer->SetDrawsContent(true);
1191     impl_layer->SetTextureId(0);
1192     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1193   }
1194
1195   // Resourceless software mode.
1196   {
1197     scoped_ptr<TextureLayerImpl> impl_layer =
1198         TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1199     impl_layer->SetDrawsContent(true);
1200     impl_layer->SetTextureMailbox(
1201         test_data_.mailbox1_,
1202         SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1203     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
1204   }
1205
1206   {
1207     scoped_ptr<TextureLayerImpl> impl_layer =
1208         TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1209     impl_layer->SetDrawsContent(true);
1210     ContextProvider* context_provider =
1211         host_impl_.output_surface()->context_provider();
1212     GLuint texture = 0;
1213     context_provider->ContextGL()->GenTextures(1, &texture);
1214     impl_layer->SetTextureId(texture);
1215     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
1216   }
1217 }
1218
1219 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
1220   host_impl_.CreatePendingTree();
1221   scoped_ptr<TextureLayerImpl> pending_layer;
1222   pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1, true);
1223   ASSERT_TRUE(pending_layer);
1224
1225   scoped_ptr<LayerImpl> active_layer(
1226       pending_layer->CreateLayerImpl(host_impl_.active_tree()));
1227   ASSERT_TRUE(active_layer);
1228
1229   pending_layer->SetTextureMailbox(
1230       test_data_.mailbox1_,
1231       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1232
1233   // Test multiple commits without an activation.
1234   EXPECT_CALL(test_data_.mock_callback_,
1235               Release(test_data_.mailbox_name1_,
1236                       test_data_.sync_point1_,
1237                       false))
1238       .Times(1);
1239   pending_layer->SetTextureMailbox(
1240       test_data_.mailbox2_,
1241       SingleReleaseCallback::Create(test_data_.release_mailbox2_));
1242   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1243
1244   // Test callback after activation.
1245   pending_layer->PushPropertiesTo(active_layer.get());
1246   active_layer->DidBecomeActive();
1247
1248   EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1249   pending_layer->SetTextureMailbox(
1250       test_data_.mailbox1_,
1251       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1252   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1253
1254   EXPECT_CALL(test_data_.mock_callback_,
1255               Release(test_data_.mailbox_name2_, _, false))
1256       .Times(1);
1257   pending_layer->PushPropertiesTo(active_layer.get());
1258   active_layer->DidBecomeActive();
1259   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1260
1261   // Test resetting the mailbox.
1262   EXPECT_CALL(test_data_.mock_callback_,
1263               Release(test_data_.mailbox_name1_, _, false))
1264       .Times(1);
1265   pending_layer->SetTextureMailbox(TextureMailbox(),
1266                                    scoped_ptr<SingleReleaseCallback>());
1267   pending_layer->PushPropertiesTo(active_layer.get());
1268   active_layer->DidBecomeActive();
1269   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1270
1271   // Test destructor.
1272   EXPECT_CALL(test_data_.mock_callback_,
1273               Release(test_data_.mailbox_name1_,
1274                       test_data_.sync_point1_,
1275                       false))
1276       .Times(1);
1277   pending_layer->SetTextureMailbox(
1278       test_data_.mailbox1_,
1279       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1280 }
1281
1282 TEST_F(TextureLayerImplWithMailboxTest,
1283        TestDestructorCallbackOnCreatedResource) {
1284   scoped_ptr<TextureLayerImpl> impl_layer;
1285   impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1286   ASSERT_TRUE(impl_layer);
1287
1288   EXPECT_CALL(test_data_.mock_callback_,
1289               Release(test_data_.mailbox_name1_, _, false))
1290       .Times(1);
1291   impl_layer->SetTextureMailbox(
1292       test_data_.mailbox1_,
1293       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1294   impl_layer->SetDrawsContent(true);
1295   impl_layer->DidBecomeActive();
1296   EXPECT_TRUE(impl_layer->WillDraw(
1297       DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1298   impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1299   impl_layer->SetTextureMailbox(TextureMailbox(),
1300                                 scoped_ptr<SingleReleaseCallback>());
1301 }
1302
1303 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1304   ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1305   ResourceProvider::ResourceId id =
1306       provider->CreateResourceFromTextureMailbox(
1307           test_data_.mailbox1_,
1308           SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1309   provider->AllocateForTesting(id);
1310
1311   // Transfer some resources to the parent.
1312   ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1313   resource_ids_to_transfer.push_back(id);
1314   TransferableResourceArray list;
1315   provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1316   EXPECT_TRUE(provider->InUseByConsumer(id));
1317   EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1318   provider->DeleteResource(id);
1319   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1320   EXPECT_CALL(test_data_.mock_callback_,
1321               Release(test_data_.mailbox_name1_, _, false))
1322       .Times(1);
1323   ReturnedResourceArray returned;
1324   TransferableResource::ReturnResources(list, &returned);
1325   provider->ReceiveReturnsFromParent(returned);
1326 }
1327
1328 // Check that ClearClient correctly clears the state so that the impl side
1329 // doesn't try to use a texture that could have been destroyed.
1330 class TextureLayerClientTest
1331     : public LayerTreeTest,
1332       public TextureLayerClient {
1333  public:
1334   TextureLayerClientTest()
1335       : texture_(0),
1336         commit_count_(0),
1337         expected_used_textures_on_draw_(0),
1338         expected_used_textures_on_commit_(0) {}
1339
1340   virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
1341       OVERRIDE {
1342     scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
1343     texture_ = provider->UnboundTestContext3d()->createExternalTexture();
1344     return FakeOutputSurface::Create3d(provider).PassAs<OutputSurface>();
1345   }
1346
1347   virtual unsigned PrepareTexture() OVERRIDE { return texture_; }
1348
1349   virtual bool PrepareTextureMailbox(
1350       TextureMailbox* mailbox,
1351       scoped_ptr<SingleReleaseCallback>* release_callback,
1352       bool use_shared_memory) OVERRIDE {
1353     return false;
1354   }
1355
1356   virtual void SetupTree() OVERRIDE {
1357     scoped_refptr<Layer> root = Layer::Create();
1358     root->SetBounds(gfx::Size(10, 10));
1359     root->SetAnchorPoint(gfx::PointF());
1360     root->SetIsDrawable(true);
1361
1362     texture_layer_ = TextureLayer::Create(this);
1363     texture_layer_->SetBounds(gfx::Size(10, 10));
1364     texture_layer_->SetAnchorPoint(gfx::PointF());
1365     texture_layer_->SetIsDrawable(true);
1366     root->AddChild(texture_layer_);
1367
1368     layer_tree_host()->SetRootLayer(root);
1369     LayerTreeTest::SetupTree();
1370     {
1371       base::AutoLock lock(lock_);
1372       expected_used_textures_on_commit_ = 1;
1373     }
1374   }
1375
1376   virtual void BeginTest() OVERRIDE {
1377     PostSetNeedsCommitToMainThread();
1378   }
1379
1380   virtual void DidCommitAndDrawFrame() OVERRIDE {
1381     ++commit_count_;
1382     switch (commit_count_) {
1383       case 1:
1384         texture_layer_->ClearClient();
1385         texture_layer_->SetNeedsDisplay();
1386         {
1387           base::AutoLock lock(lock_);
1388           expected_used_textures_on_commit_ = 0;
1389         }
1390         break;
1391       case 2:
1392         EndTest();
1393         break;
1394       default:
1395         NOTREACHED();
1396         break;
1397     }
1398   }
1399
1400   virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1401     base::AutoLock lock(lock_);
1402     expected_used_textures_on_draw_ = expected_used_textures_on_commit_;
1403   }
1404
1405   virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1406                                      LayerTreeHostImpl::FrameData* frame_data,
1407                                      bool result) OVERRIDE {
1408     ContextForImplThread(host_impl)->ResetUsedTextures();
1409     return true;
1410   }
1411
1412   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1413                                    bool result) OVERRIDE {
1414     ASSERT_TRUE(result);
1415     EXPECT_EQ(expected_used_textures_on_draw_,
1416               ContextForImplThread(host_impl)->NumUsedTextures());
1417   }
1418
1419   virtual void AfterTest() OVERRIDE {}
1420
1421  private:
1422   TestWebGraphicsContext3D* ContextForImplThread(LayerTreeHostImpl* host_impl) {
1423     return static_cast<TestContextProvider*>(
1424         host_impl->output_surface()->context_provider().get())->TestContext3d();
1425   }
1426
1427   scoped_refptr<TextureLayer> texture_layer_;
1428   unsigned texture_;
1429   int commit_count_;
1430
1431   // Used only on thread.
1432   unsigned expected_used_textures_on_draw_;
1433
1434   // Used on either thread, protected by lock_.
1435   base::Lock lock_;
1436   unsigned expected_used_textures_on_commit_;
1437 };
1438
1439 // The TextureLayerClient does not use mailboxes, so can't use a delegating
1440 // renderer.
1441 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerClientTest);
1442
1443
1444 // Checks that changing a texture in the client for a TextureLayer that's
1445 // invisible correctly works without drawing a deleted texture. See
1446 // crbug.com/266628
1447 class TextureLayerChangeInvisibleTest
1448     : public LayerTreeTest,
1449       public TextureLayerClient {
1450  public:
1451   TextureLayerChangeInvisibleTest()
1452       : texture_(0u),
1453         prepare_called_(0),
1454         commit_count_(0),
1455         expected_texture_on_draw_(0) {}
1456
1457   virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
1458       OVERRIDE {
1459     scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
1460     texture_ = provider->UnboundTestContext3d()->createExternalTexture();
1461     return FakeOutputSurface::Create3d(provider).PassAs<OutputSurface>();
1462   }
1463
1464   // TextureLayerClient implementation.
1465   virtual unsigned PrepareTexture() OVERRIDE {
1466     ++prepare_called_;
1467     return texture_;
1468   }
1469   virtual bool PrepareTextureMailbox(
1470       TextureMailbox* mailbox,
1471       scoped_ptr<SingleReleaseCallback>* release_callback,
1472       bool use_shared_memory) OVERRIDE {
1473     return false;
1474   }
1475
1476   virtual void SetupTree() OVERRIDE {
1477     scoped_refptr<Layer> root = Layer::Create();
1478     root->SetBounds(gfx::Size(10, 10));
1479     root->SetAnchorPoint(gfx::PointF());
1480     root->SetIsDrawable(true);
1481
1482     solid_layer_ = SolidColorLayer::Create();
1483     solid_layer_->SetBounds(gfx::Size(10, 10));
1484     solid_layer_->SetIsDrawable(true);
1485     solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1486     root->AddChild(solid_layer_);
1487
1488     parent_layer_ = Layer::Create();
1489     parent_layer_->SetBounds(gfx::Size(10, 10));
1490     parent_layer_->SetIsDrawable(true);
1491     root->AddChild(parent_layer_);
1492
1493     texture_layer_ = TextureLayer::Create(this);
1494     texture_layer_->SetBounds(gfx::Size(10, 10));
1495     texture_layer_->SetAnchorPoint(gfx::PointF());
1496     texture_layer_->SetIsDrawable(true);
1497     parent_layer_->AddChild(texture_layer_);
1498
1499     layer_tree_host()->SetRootLayer(root);
1500     LayerTreeTest::SetupTree();
1501   }
1502
1503   virtual void BeginTest() OVERRIDE {
1504     PostSetNeedsCommitToMainThread();
1505   }
1506
1507   virtual void DidCommitAndDrawFrame() OVERRIDE {
1508     ++commit_count_;
1509     switch (commit_count_) {
1510       case 1:
1511         // We should have updated the layer, committing the texture.
1512         EXPECT_EQ(1, prepare_called_);
1513         // Make layer invisible.
1514         parent_layer_->SetOpacity(0.f);
1515         break;
1516       case 2: {
1517         // Layer shouldn't have been updated.
1518         EXPECT_EQ(1, prepare_called_);
1519         texture_layer_->SetNeedsDisplay();
1520         // Force a change to make sure we draw a frame.
1521         solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1522         break;
1523       }
1524       case 3:
1525         EXPECT_EQ(1, prepare_called_);
1526         // Make layer visible again.
1527         parent_layer_->SetOpacity(1.f);
1528         break;
1529       case 4: {
1530         // Layer should have been updated.
1531         EXPECT_EQ(2, prepare_called_);
1532         texture_layer_->ClearClient();
1533         texture_ = 0;
1534         break;
1535       }
1536       case 5:
1537         EndTest();
1538         break;
1539       default:
1540         NOTREACHED();
1541         break;
1542     }
1543   }
1544
1545   virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1546     ASSERT_TRUE(proxy()->IsMainThreadBlocked());
1547     // This is the only texture that can be drawn this frame.
1548     expected_texture_on_draw_ = texture_;
1549   }
1550
1551   virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1552                                      LayerTreeHostImpl::FrameData* frame_data,
1553                                      bool result) OVERRIDE {
1554     ContextForImplThread(host_impl)->ResetUsedTextures();
1555     return true;
1556   }
1557
1558   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1559                                    bool result) OVERRIDE {
1560     ASSERT_TRUE(result);
1561     TestWebGraphicsContext3D* context = ContextForImplThread(host_impl);
1562     int used_textures = context->NumUsedTextures();
1563     switch (host_impl->active_tree()->source_frame_number()) {
1564       case 0:
1565         EXPECT_EQ(1, used_textures);
1566         EXPECT_TRUE(context->UsedTexture(expected_texture_on_draw_));
1567         break;
1568       case 1:
1569       case 2:
1570         EXPECT_EQ(0, used_textures);
1571         break;
1572       case 3:
1573         EXPECT_EQ(1, used_textures);
1574         EXPECT_TRUE(context->UsedTexture(expected_texture_on_draw_));
1575         break;
1576       default:
1577         break;
1578     }
1579   }
1580
1581   virtual void AfterTest() OVERRIDE {}
1582
1583  private:
1584   TestWebGraphicsContext3D* ContextForImplThread(LayerTreeHostImpl* host_impl) {
1585     return static_cast<TestContextProvider*>(
1586         host_impl->output_surface()->context_provider().get())->TestContext3d();
1587   }
1588
1589   scoped_refptr<SolidColorLayer> solid_layer_;
1590   scoped_refptr<Layer> parent_layer_;
1591   scoped_refptr<TextureLayer> texture_layer_;
1592
1593   // Used on the main thread, and on the impl thread while the main thread is
1594   // blocked.
1595   unsigned texture_;
1596
1597   // Used on the main thread.
1598   int prepare_called_;
1599   int commit_count_;
1600
1601   // Used on the compositor thread.
1602   unsigned expected_texture_on_draw_;
1603 };
1604
1605 // The TextureLayerChangeInvisibleTest does not use mailboxes, so can't use a
1606 // delegating renderer.
1607 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerChangeInvisibleTest);
1608
1609 // Checks that TextureLayer::Update does not cause an extra commit when setting
1610 // the texture mailbox.
1611 class TextureLayerNoExtraCommitForMailboxTest
1612     : public LayerTreeTest,
1613       public TextureLayerClient {
1614  public:
1615   // TextureLayerClient implementation.
1616   virtual unsigned PrepareTexture() OVERRIDE {
1617     NOTREACHED();
1618     return 0;
1619   }
1620   virtual bool PrepareTextureMailbox(
1621       TextureMailbox* mailbox,
1622       scoped_ptr<SingleReleaseCallback>* release_callback,
1623       bool use_shared_memory) OVERRIDE {
1624     if (layer_tree_host()->source_frame_number() == 1) {
1625       *mailbox = TextureMailbox();
1626       return true;
1627     }
1628
1629     *mailbox = TextureMailbox(std::string(64, '1'));
1630     *release_callback = SingleReleaseCallback::Create(
1631         base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1632                    base::Unretained(this)));
1633     return true;
1634   }
1635
1636   void MailboxReleased(unsigned sync_point, bool lost_resource) {
1637     EXPECT_EQ(2, layer_tree_host()->source_frame_number());
1638     EndTest();
1639   }
1640
1641   virtual void SetupTree() OVERRIDE {
1642     scoped_refptr<Layer> root = Layer::Create();
1643     root->SetBounds(gfx::Size(10, 10));
1644     root->SetAnchorPoint(gfx::PointF());
1645     root->SetIsDrawable(true);
1646
1647     texture_layer_ = TextureLayer::CreateForMailbox(this);
1648     texture_layer_->SetBounds(gfx::Size(10, 10));
1649     texture_layer_->SetAnchorPoint(gfx::PointF());
1650     texture_layer_->SetIsDrawable(true);
1651     root->AddChild(texture_layer_);
1652
1653     layer_tree_host()->SetRootLayer(root);
1654     LayerTreeTest::SetupTree();
1655   }
1656
1657   virtual void BeginTest() OVERRIDE {
1658     PostSetNeedsCommitToMainThread();
1659   }
1660
1661   virtual void DidCommitAndDrawFrame() OVERRIDE {
1662     switch (layer_tree_host()->source_frame_number()) {
1663       case 1:
1664         EXPECT_FALSE(proxy()->CommitPendingForTesting());
1665         // Invalidate the texture layer to clear the mailbox before
1666         // ending the test.
1667         texture_layer_->SetNeedsDisplay();
1668         break;
1669       case 2:
1670         break;
1671       default:
1672         NOTREACHED();
1673         break;
1674     }
1675   }
1676
1677   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1678                                    bool result) OVERRIDE {
1679     ASSERT_TRUE(result);
1680     DelegatedFrameData* delegated_frame_data =
1681         output_surface()->last_sent_frame().delegated_frame_data.get();
1682     if (!delegated_frame_data)
1683       return;
1684
1685     // Return all resources immediately.
1686     TransferableResourceArray resources_to_return =
1687         output_surface()->resources_held_by_parent();
1688
1689     CompositorFrameAck ack;
1690     for (size_t i = 0; i < resources_to_return.size(); ++i)
1691       output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1692     host_impl->ReclaimResources(&ack);
1693     host_impl->OnSwapBuffersComplete();
1694   }
1695
1696   virtual void AfterTest() OVERRIDE {}
1697
1698  private:
1699   scoped_refptr<TextureLayer> texture_layer_;
1700 };
1701
1702 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1703
1704 // Checks that changing a mailbox in the client for a TextureLayer that's
1705 // invisible correctly works and uses the new mailbox as soon as the layer
1706 // becomes visible (and returns the old one).
1707 class TextureLayerChangeInvisibleMailboxTest
1708     : public LayerTreeTest,
1709       public TextureLayerClient {
1710  public:
1711   TextureLayerChangeInvisibleMailboxTest()
1712       : mailbox_changed_(true),
1713         mailbox_returned_(0),
1714         prepare_called_(0),
1715         commit_count_(0) {
1716     mailbox_ = MakeMailbox('1');
1717   }
1718
1719   // TextureLayerClient implementation.
1720   virtual unsigned PrepareTexture() OVERRIDE {
1721     NOTREACHED();
1722     return 0;
1723   }
1724
1725   virtual bool PrepareTextureMailbox(
1726       TextureMailbox* mailbox,
1727       scoped_ptr<SingleReleaseCallback>* release_callback,
1728       bool use_shared_memory) OVERRIDE {
1729     ++prepare_called_;
1730     if (!mailbox_changed_)
1731       return false;
1732     *mailbox = mailbox_;
1733     *release_callback = SingleReleaseCallback::Create(
1734         base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1735                    base::Unretained(this)));
1736     return true;
1737   }
1738
1739   TextureMailbox MakeMailbox(char name) {
1740     return TextureMailbox(std::string(64, name));
1741   }
1742
1743   void MailboxReleased(unsigned sync_point, bool lost_resource) {
1744     ++mailbox_returned_;
1745   }
1746
1747   virtual void SetupTree() OVERRIDE {
1748     scoped_refptr<Layer> root = Layer::Create();
1749     root->SetBounds(gfx::Size(10, 10));
1750     root->SetAnchorPoint(gfx::PointF());
1751     root->SetIsDrawable(true);
1752
1753     solid_layer_ = SolidColorLayer::Create();
1754     solid_layer_->SetBounds(gfx::Size(10, 10));
1755     solid_layer_->SetIsDrawable(true);
1756     solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1757     root->AddChild(solid_layer_);
1758
1759     parent_layer_ = Layer::Create();
1760     parent_layer_->SetBounds(gfx::Size(10, 10));
1761     parent_layer_->SetIsDrawable(true);
1762     root->AddChild(parent_layer_);
1763
1764     texture_layer_ = TextureLayer::CreateForMailbox(this);
1765     texture_layer_->SetBounds(gfx::Size(10, 10));
1766     texture_layer_->SetAnchorPoint(gfx::PointF());
1767     texture_layer_->SetIsDrawable(true);
1768     parent_layer_->AddChild(texture_layer_);
1769
1770     layer_tree_host()->SetRootLayer(root);
1771     LayerTreeTest::SetupTree();
1772   }
1773
1774   virtual void BeginTest() OVERRIDE {
1775     PostSetNeedsCommitToMainThread();
1776   }
1777
1778   virtual void DidCommitAndDrawFrame() OVERRIDE {
1779     ++commit_count_;
1780     switch (commit_count_) {
1781       case 1:
1782         // We should have updated the layer, committing the texture.
1783         EXPECT_EQ(1, prepare_called_);
1784         // Make layer invisible.
1785         parent_layer_->SetOpacity(0.f);
1786         break;
1787       case 2:
1788         // Layer shouldn't have been updated.
1789         EXPECT_EQ(1, prepare_called_);
1790         // Change the texture.
1791         mailbox_ = MakeMailbox('2');
1792         mailbox_changed_ = true;
1793         texture_layer_->SetNeedsDisplay();
1794         // Force a change to make sure we draw a frame.
1795         solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1796         break;
1797       case 3:
1798         // Layer shouldn't have been updated.
1799         EXPECT_EQ(1, prepare_called_);
1800         // So the old mailbox isn't returned yet.
1801         EXPECT_EQ(0, mailbox_returned_);
1802         // Make layer visible again.
1803         parent_layer_->SetOpacity(1.f);
1804         break;
1805       case 4:
1806         // Layer should have been updated.
1807         EXPECT_EQ(2, prepare_called_);
1808         // So the old mailbox should have been returned already.
1809         EXPECT_EQ(1, mailbox_returned_);
1810         texture_layer_->ClearClient();
1811         break;
1812       case 5:
1813         EXPECT_EQ(2, mailbox_returned_);
1814         EndTest();
1815         break;
1816       default:
1817         NOTREACHED();
1818         break;
1819     }
1820   }
1821
1822   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1823                                    bool result) OVERRIDE {
1824     ASSERT_TRUE(result);
1825     DelegatedFrameData* delegated_frame_data =
1826         output_surface()->last_sent_frame().delegated_frame_data.get();
1827     if (!delegated_frame_data)
1828       return;
1829
1830     // Return all resources immediately.
1831     TransferableResourceArray resources_to_return =
1832         output_surface()->resources_held_by_parent();
1833
1834     CompositorFrameAck ack;
1835     for (size_t i = 0; i < resources_to_return.size(); ++i)
1836       output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1837     host_impl->ReclaimResources(&ack);
1838     host_impl->OnSwapBuffersComplete();
1839   }
1840
1841   virtual void AfterTest() OVERRIDE {}
1842
1843  private:
1844   scoped_refptr<SolidColorLayer> solid_layer_;
1845   scoped_refptr<Layer> parent_layer_;
1846   scoped_refptr<TextureLayer> texture_layer_;
1847
1848   // Used on the main thread.
1849   bool mailbox_changed_;
1850   TextureMailbox mailbox_;
1851   int mailbox_returned_;
1852   int prepare_called_;
1853   int commit_count_;
1854 };
1855
1856 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1857
1858 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1859 // the mailbox back to TextureLayerClient.
1860 class TextureLayerReleaseResourcesBase
1861     : public LayerTreeTest,
1862       public TextureLayerClient {
1863  public:
1864   // TextureLayerClient implementation.
1865   virtual unsigned PrepareTexture() OVERRIDE {
1866     NOTREACHED();
1867     return 0;
1868   }
1869   virtual bool PrepareTextureMailbox(
1870       TextureMailbox* mailbox,
1871       scoped_ptr<SingleReleaseCallback>* release_callback,
1872       bool use_shared_memory) OVERRIDE {
1873     *mailbox = TextureMailbox(std::string(64, '1'));
1874     *release_callback = SingleReleaseCallback::Create(
1875         base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1876                    base::Unretained(this)));
1877     return true;
1878   }
1879
1880   void MailboxReleased(unsigned sync_point, bool lost_resource) {
1881     mailbox_released_ = true;
1882   }
1883
1884   virtual void SetupTree() OVERRIDE {
1885     LayerTreeTest::SetupTree();
1886
1887     scoped_refptr<TextureLayer> texture_layer =
1888         TextureLayer::CreateForMailbox(this);
1889     texture_layer->SetBounds(gfx::Size(10, 10));
1890     texture_layer->SetAnchorPoint(gfx::PointF());
1891     texture_layer->SetIsDrawable(true);
1892
1893     layer_tree_host()->root_layer()->AddChild(texture_layer);
1894   }
1895
1896   virtual void BeginTest() OVERRIDE {
1897     mailbox_released_ = false;
1898     PostSetNeedsCommitToMainThread();
1899   }
1900
1901   virtual void DidCommitAndDrawFrame() OVERRIDE {
1902     EndTest();
1903   }
1904
1905   virtual void AfterTest() OVERRIDE {
1906     EXPECT_TRUE(mailbox_released_);
1907   }
1908
1909  private:
1910   bool mailbox_released_;
1911 };
1912
1913 class TextureLayerReleaseResourcesAfterCommit
1914     : public TextureLayerReleaseResourcesBase {
1915  public:
1916   virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1917     LayerTreeImpl* tree = NULL;
1918     if (host_impl->settings().impl_side_painting)
1919       tree = host_impl->pending_tree();
1920     else
1921       tree = host_impl->active_tree();
1922     tree->root_layer()->children()[0]->ReleaseResources();
1923   }
1924 };
1925
1926 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1927
1928 class TextureLayerReleaseResourcesAfterActivate
1929     : public TextureLayerReleaseResourcesBase {
1930  public:
1931   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1932     host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
1933   }
1934 };
1935
1936 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
1937
1938 // Test recovering from a lost context.
1939 class TextureLayerLostContextTest
1940     : public LayerTreeTest,
1941       public TextureLayerClient {
1942  public:
1943   TextureLayerLostContextTest()
1944       : context_lost_(false),
1945         draw_count_(0) {}
1946
1947   virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
1948       OVERRIDE {
1949     return CreateFakeOutputSurface();
1950   }
1951
1952   virtual unsigned PrepareTexture() OVERRIDE {
1953     if (draw_count_ == 0)
1954       context_lost_ = true;
1955     if (context_lost_)
1956       return 0u;
1957     return 1u;
1958   }
1959
1960   virtual bool PrepareTextureMailbox(
1961       TextureMailbox* mailbox,
1962       scoped_ptr<SingleReleaseCallback>* release_callback,
1963       bool use_shared_memory) OVERRIDE {
1964     return false;
1965   }
1966
1967   virtual void SetupTree() OVERRIDE {
1968     scoped_refptr<Layer> root = Layer::Create();
1969     root->SetBounds(gfx::Size(10, 10));
1970     root->SetIsDrawable(true);
1971
1972     texture_layer_ = TextureLayer::Create(this);
1973     texture_layer_->SetBounds(gfx::Size(10, 10));
1974     texture_layer_->SetIsDrawable(true);
1975     root->AddChild(texture_layer_);
1976
1977     layer_tree_host()->SetRootLayer(root);
1978     LayerTreeTest::SetupTree();
1979   }
1980
1981   virtual void BeginTest() OVERRIDE {
1982     PostSetNeedsCommitToMainThread();
1983   }
1984
1985   virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1986                                      LayerTreeHostImpl::FrameData* frame_data,
1987                                      bool result) OVERRIDE {
1988     LayerImpl* root = host_impl->RootLayer();
1989     TextureLayerImpl* texture_layer =
1990         static_cast<TextureLayerImpl*>(root->children()[0]);
1991     if (++draw_count_ == 1)
1992       EXPECT_EQ(0u, texture_layer->texture_id());
1993     else
1994       EXPECT_EQ(1u, texture_layer->texture_id());
1995     return true;
1996   }
1997
1998   virtual void DidCommitAndDrawFrame() OVERRIDE {
1999     EndTest();
2000   }
2001
2002   virtual void AfterTest() OVERRIDE {}
2003
2004  private:
2005   scoped_refptr<TextureLayer> texture_layer_;
2006   bool context_lost_;
2007   int draw_count_;
2008 };
2009
2010 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerLostContextTest);
2011
2012 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
2013  public:
2014   void ReleaseCallback(unsigned sync_point, bool lost_resource) {
2015     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2016     EXPECT_FALSE(lost_resource);
2017     ++callback_count_;
2018     EndTest();
2019   }
2020
2021   void SetMailbox(char mailbox_char) {
2022     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2023     TextureMailbox mailbox(std::string(64, mailbox_char));
2024     scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2025         base::Bind(
2026             &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
2027             base::Unretained(this)));
2028     layer_->SetTextureMailbox(mailbox, callback.Pass());
2029   }
2030
2031   virtual void SetupTree() OVERRIDE {
2032     gfx::Size bounds(100, 100);
2033     root_ = Layer::Create();
2034     root_->SetAnchorPoint(gfx::PointF());
2035     root_->SetBounds(bounds);
2036
2037     layer_ = TextureLayer::CreateForMailbox(NULL);
2038     layer_->SetIsDrawable(true);
2039     layer_->SetAnchorPoint(gfx::PointF());
2040     layer_->SetBounds(bounds);
2041
2042     root_->AddChild(layer_);
2043     layer_tree_host()->SetRootLayer(root_);
2044     layer_tree_host()->SetViewportSize(bounds);
2045   }
2046
2047   virtual void BeginTest() OVERRIDE {
2048     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2049
2050     callback_count_ = 0;
2051
2052     // Set the mailbox on the main thread.
2053     SetMailbox('1');
2054     EXPECT_EQ(0, callback_count_);
2055
2056     PostSetNeedsCommitToMainThread();
2057   }
2058
2059   virtual void DidCommitAndDrawFrame() OVERRIDE {
2060     switch (layer_tree_host()->source_frame_number()) {
2061       case 1:
2062         // Delete the TextureLayer on the main thread while the mailbox is in
2063         // the impl tree.
2064         layer_->RemoveFromParent();
2065         layer_ = NULL;
2066         break;
2067     }
2068   }
2069
2070   virtual void AfterTest() OVERRIDE {
2071     EXPECT_EQ(1, callback_count_);
2072   }
2073
2074  private:
2075   base::ThreadChecker main_thread_;
2076   int callback_count_;
2077   scoped_refptr<Layer> root_;
2078   scoped_refptr<TextureLayer> layer_;
2079 };
2080
2081 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
2082     TextureLayerWithMailboxMainThreadDeleted);
2083
2084 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
2085  public:
2086   void ReleaseCallback(unsigned sync_point, bool lost_resource) {
2087     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2088     EXPECT_FALSE(lost_resource);
2089     ++callback_count_;
2090     EndTest();
2091   }
2092
2093   void SetMailbox(char mailbox_char) {
2094     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2095     TextureMailbox mailbox(std::string(64, mailbox_char));
2096     scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2097         base::Bind(
2098             &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
2099             base::Unretained(this)));
2100     layer_->SetTextureMailbox(mailbox, callback.Pass());
2101   }
2102
2103   virtual void SetupTree() OVERRIDE {
2104     gfx::Size bounds(100, 100);
2105     root_ = Layer::Create();
2106     root_->SetAnchorPoint(gfx::PointF());
2107     root_->SetBounds(bounds);
2108
2109     layer_ = TextureLayer::CreateForMailbox(NULL);
2110     layer_->SetIsDrawable(true);
2111     layer_->SetAnchorPoint(gfx::PointF());
2112     layer_->SetBounds(bounds);
2113
2114     root_->AddChild(layer_);
2115     layer_tree_host()->SetRootLayer(root_);
2116     layer_tree_host()->SetViewportSize(bounds);
2117   }
2118
2119   virtual void BeginTest() OVERRIDE {
2120     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2121
2122     callback_count_ = 0;
2123
2124     // Set the mailbox on the main thread.
2125     SetMailbox('1');
2126     EXPECT_EQ(0, callback_count_);
2127
2128     PostSetNeedsCommitToMainThread();
2129   }
2130
2131   virtual void DidCommitAndDrawFrame() OVERRIDE {
2132     switch (layer_tree_host()->source_frame_number()) {
2133       case 1:
2134         // Remove the TextureLayer on the main thread while the mailbox is in
2135         // the impl tree, but don't delete the TextureLayer until after the impl
2136         // tree side is deleted.
2137         layer_->RemoveFromParent();
2138         break;
2139       case 2:
2140         layer_ = NULL;
2141         break;
2142     }
2143   }
2144
2145   virtual void AfterTest() OVERRIDE {
2146     EXPECT_EQ(1, callback_count_);
2147   }
2148
2149  private:
2150   base::ThreadChecker main_thread_;
2151   int callback_count_;
2152   scoped_refptr<Layer> root_;
2153   scoped_refptr<TextureLayer> layer_;
2154 };
2155
2156 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
2157     TextureLayerWithMailboxImplThreadDeleted);
2158
2159 }  // namespace
2160 }  // namespace cc