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