97b52f457b00c7ec96a9378771ae70f508ee28de
[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 using ::testing::InvokeWithoutArgs;
41
42 namespace cc {
43 namespace {
44
45 gpu::Mailbox MailboxFromChar(char value) {
46   gpu::Mailbox mailbox;
47   memset(mailbox.name, value, sizeof(mailbox.name));
48   return mailbox;
49 }
50
51 class MockLayerTreeHost : public LayerTreeHost {
52  public:
53   explicit MockLayerTreeHost(FakeLayerTreeHostClient* client)
54       : LayerTreeHost(client, NULL, LayerTreeSettings()) {
55     InitializeSingleThreaded(client);
56   }
57
58   MOCK_METHOD0(SetNeedsCommit, void());
59   MOCK_METHOD0(SetNeedsUpdateLayers, void());
60   MOCK_METHOD0(StartRateLimiter, void());
61   MOCK_METHOD0(StopRateLimiter, void());
62 };
63
64 class FakeTextureLayerClient : public TextureLayerClient {
65  public:
66   FakeTextureLayerClient() : mailbox_changed_(true) {}
67
68   virtual bool PrepareTextureMailbox(
69       TextureMailbox* mailbox,
70       scoped_ptr<SingleReleaseCallback>* release_callback,
71       bool use_shared_memory) OVERRIDE {
72     if (!mailbox_changed_)
73       return false;
74
75     *mailbox = mailbox_;
76     *release_callback = release_callback_.Pass();
77     mailbox_changed_ = false;
78     return true;
79   }
80
81   void set_mailbox(const TextureMailbox& mailbox,
82                    scoped_ptr<SingleReleaseCallback> release_callback) {
83     mailbox_ = mailbox;
84     release_callback_ = release_callback.Pass();
85     mailbox_changed_ = true;
86   }
87
88  private:
89   TextureMailbox mailbox_;
90   scoped_ptr<SingleReleaseCallback> release_callback_;
91   bool mailbox_changed_;
92   DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient);
93 };
94
95 class MockMailboxCallback {
96  public:
97   MOCK_METHOD3(Release,
98                void(const gpu::Mailbox& mailbox,
99                     uint32 sync_point,
100                     bool lost_resource));
101   MOCK_METHOD3(Release2,
102                void(base::SharedMemory* shared_memory,
103                     uint32 sync_point,
104                     bool lost_resource));
105 };
106
107 struct CommonMailboxObjects {
108   CommonMailboxObjects()
109       : mailbox_name1_(MailboxFromChar('1')),
110         mailbox_name2_(MailboxFromChar('2')),
111         sync_point1_(1),
112         sync_point2_(2),
113         shared_memory_(new base::SharedMemory) {
114     release_mailbox1_ = base::Bind(&MockMailboxCallback::Release,
115                                    base::Unretained(&mock_callback_),
116                                    mailbox_name1_);
117     release_mailbox2_ = base::Bind(&MockMailboxCallback::Release,
118                                    base::Unretained(&mock_callback_),
119                                    mailbox_name2_);
120     const uint32 arbitrary_target1 = GL_TEXTURE_2D;
121     const uint32 arbitrary_target2 = GL_TEXTURE_EXTERNAL_OES;
122     mailbox1_ = TextureMailbox(mailbox_name1_, arbitrary_target1, sync_point1_);
123     mailbox2_ = TextureMailbox(mailbox_name2_, arbitrary_target2, sync_point2_);
124     gfx::Size size(128, 128);
125     EXPECT_TRUE(shared_memory_->CreateAndMapAnonymous(4 * size.GetArea()));
126     release_mailbox3_ = base::Bind(&MockMailboxCallback::Release2,
127                                    base::Unretained(&mock_callback_),
128                                    shared_memory_.get());
129     mailbox3_ = TextureMailbox(shared_memory_.get(), size);
130   }
131
132   gpu::Mailbox mailbox_name1_;
133   gpu::Mailbox mailbox_name2_;
134   MockMailboxCallback mock_callback_;
135   ReleaseCallback release_mailbox1_;
136   ReleaseCallback release_mailbox2_;
137   ReleaseCallback release_mailbox3_;
138   TextureMailbox mailbox1_;
139   TextureMailbox mailbox2_;
140   TextureMailbox mailbox3_;
141   uint32 sync_point1_;
142   uint32 sync_point2_;
143   scoped_ptr<base::SharedMemory> shared_memory_;
144 };
145
146 class TextureLayerTest : public testing::Test {
147  public:
148   TextureLayerTest()
149       : fake_client_(
150             FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
151         host_impl_(&proxy_, &shared_bitmap_manager_) {}
152
153  protected:
154   virtual void SetUp() {
155     layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
156     EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
157     layer_tree_host_->SetViewportSize(gfx::Size(10, 10));
158     Mock::VerifyAndClearExpectations(layer_tree_host_.get());
159   }
160
161   virtual void TearDown() {
162     Mock::VerifyAndClearExpectations(layer_tree_host_.get());
163     EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
164
165     layer_tree_host_->SetRootLayer(NULL);
166     layer_tree_host_.reset();
167   }
168
169   scoped_ptr<MockLayerTreeHost> layer_tree_host_;
170   FakeImplProxy proxy_;
171   FakeLayerTreeHostClient fake_client_;
172   TestSharedBitmapManager shared_bitmap_manager_;
173   FakeLayerTreeHostImpl host_impl_;
174 };
175
176 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) {
177   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
178   EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer));
179
180   // Test properties that should call SetNeedsCommit.  All properties need to
181   // be set to new values in order for SetNeedsCommit to be called.
182   EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false));
183   EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV(
184       gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f)));
185   EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity(
186       0.5f, 0.5f, 0.5f, 0.5f));
187   EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false));
188   EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true));
189 }
190
191 TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) {
192   const gfx::Size layer_bounds(100, 100);
193   const gfx::Rect layer_rect(layer_bounds);
194   const Region layer_region(layer_rect);
195
196   scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(NULL);
197   layer->SetBounds(layer_bounds);
198   layer->draw_properties().visible_content_rect = layer_rect;
199   layer->SetBlendBackgroundColor(true);
200
201   // Verify initial conditions.
202   EXPECT_FALSE(layer->contents_opaque());
203   EXPECT_EQ(0u, layer->background_color());
204   EXPECT_EQ(Region().ToString(),
205             layer->VisibleContentOpaqueRegion().ToString());
206
207   // Opaque background.
208   layer->SetBackgroundColor(SK_ColorWHITE);
209   EXPECT_EQ(layer_region.ToString(),
210             layer->VisibleContentOpaqueRegion().ToString());
211
212   // Transparent background.
213   layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
214   EXPECT_EQ(Region().ToString(),
215             layer->VisibleContentOpaqueRegion().ToString());
216 }
217
218 TEST_F(TextureLayerTest, RateLimiter) {
219   FakeTextureLayerClient client;
220   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(
221       &client);
222   test_layer->SetIsDrawable(true);
223   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
224   layer_tree_host_->SetRootLayer(test_layer);
225
226   // Don't rate limit until we invalidate.
227   EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
228   test_layer->SetRateLimitContext(true);
229   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
230
231   // Do rate limit after we invalidate.
232   EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
233   test_layer->SetNeedsDisplay();
234   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
235
236   // Stop rate limiter when we don't want it any more.
237   EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
238   test_layer->SetRateLimitContext(false);
239   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
240
241   // Or we clear the client.
242   test_layer->SetRateLimitContext(true);
243   EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
244   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
245   test_layer->ClearClient();
246   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
247
248   // Reset to a layer with a client, that started the rate limiter.
249   test_layer = TextureLayer::CreateForMailbox(
250       &client);
251   test_layer->SetIsDrawable(true);
252   test_layer->SetRateLimitContext(true);
253   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
254   layer_tree_host_->SetRootLayer(test_layer);
255   EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
256   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
257   EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
258   test_layer->SetNeedsDisplay();
259   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
260
261   // Stop rate limiter when we're removed from the tree.
262   EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
263   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
264   layer_tree_host_->SetRootLayer(NULL);
265   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
266 }
267
268 class TestMailboxHolder : public TextureLayer::TextureMailboxHolder {
269  public:
270   using TextureLayer::TextureMailboxHolder::Create;
271
272  protected:
273   virtual ~TestMailboxHolder() {}
274 };
275
276 class TextureLayerWithMailboxTest : public TextureLayerTest {
277  protected:
278   virtual void TearDown() {
279     Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
280     EXPECT_CALL(test_data_.mock_callback_,
281                 Release(test_data_.mailbox_name1_,
282                         test_data_.sync_point1_,
283                         false)).Times(1);
284     TextureLayerTest::TearDown();
285   }
286
287   CommonMailboxObjects test_data_;
288 };
289
290 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
291   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
292   ASSERT_TRUE(test_layer.get());
293
294   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
295   layer_tree_host_->SetRootLayer(test_layer);
296   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
297
298   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
299   test_layer->SetTextureMailbox(
300       test_data_.mailbox1_,
301       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
302   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
303
304   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
305   EXPECT_CALL(test_data_.mock_callback_,
306               Release(test_data_.mailbox_name1_,
307                       test_data_.sync_point1_,
308                       false))
309       .Times(1);
310   test_layer->SetTextureMailbox(
311       test_data_.mailbox2_,
312       SingleReleaseCallback::Create(test_data_.release_mailbox2_));
313   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
314   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
315
316   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
317   EXPECT_CALL(test_data_.mock_callback_,
318               Release(test_data_.mailbox_name2_,
319                       test_data_.sync_point2_,
320                       false))
321       .Times(1);
322   test_layer->SetTextureMailbox(TextureMailbox(),
323                                 scoped_ptr<SingleReleaseCallback>());
324   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
325   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
326
327   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
328   test_layer->SetTextureMailbox(
329       test_data_.mailbox3_,
330       SingleReleaseCallback::Create(test_data_.release_mailbox3_));
331   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
332   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
333
334   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
335   EXPECT_CALL(test_data_.mock_callback_,
336               Release2(test_data_.shared_memory_.get(),
337                        0, false))
338       .Times(1);
339   test_layer->SetTextureMailbox(TextureMailbox(),
340                                 scoped_ptr<SingleReleaseCallback>());
341   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
342   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
343
344   // Test destructor.
345   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
346   test_layer->SetTextureMailbox(
347       test_data_.mailbox1_,
348       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
349 }
350
351 TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) {
352   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
353   ASSERT_TRUE(test_layer.get());
354
355   // These use the same gpu::Mailbox, but different sync points.
356   TextureMailbox mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D, 1);
357   TextureMailbox mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D, 2);
358
359   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
360   layer_tree_host_->SetRootLayer(test_layer);
361   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
362
363   // Set the mailbox the first time. It should cause a commit.
364   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
365   test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox1);
366   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
367
368   // Set the mailbox again with a new sync point, as the backing texture has
369   // been updated. It should cause a new commit.
370   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
371   test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox2);
372   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
373 }
374
375 class TextureLayerMailboxHolderTest : public TextureLayerTest {
376  public:
377   TextureLayerMailboxHolderTest()
378       : main_thread_("MAIN") {
379     main_thread_.Start();
380   }
381
382   void Wait(const base::Thread& thread) {
383     bool manual_reset = false;
384     bool initially_signaled = false;
385     base::WaitableEvent event(manual_reset, initially_signaled);
386     thread.message_loop()->PostTask(
387         FROM_HERE,
388         base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
389     event.Wait();
390   }
391
392   void CreateMainRef() {
393     main_ref_ = TestMailboxHolder::Create(
394         test_data_.mailbox1_,
395         SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass();
396   }
397
398   void ReleaseMainRef() {
399     main_ref_.reset();
400   }
401
402   void CreateImplRef(scoped_ptr<SingleReleaseCallback>* impl_ref) {
403     *impl_ref = main_ref_->holder()->GetCallbackForImplThread();
404   }
405
406   void CapturePostTasksAndWait(base::WaitableEvent* begin_capture,
407                                base::WaitableEvent* wait_for_capture,
408                                base::WaitableEvent* stop_capture) {
409     begin_capture->Wait();
410     BlockingTaskRunner::CapturePostTasks capture;
411     wait_for_capture->Signal();
412     stop_capture->Wait();
413   }
414
415  protected:
416   scoped_ptr<TestMailboxHolder::MainThreadReference>
417       main_ref_;
418   base::Thread main_thread_;
419   CommonMailboxObjects test_data_;
420 };
421
422 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) {
423   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
424   ASSERT_TRUE(test_layer.get());
425
426   main_thread_.message_loop()->PostTask(
427       FROM_HERE,
428       base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
429                  base::Unretained(this)));
430
431   Wait(main_thread_);
432
433   // The texture layer is attached to compositor1, and passes a reference to its
434   // impl tree.
435   scoped_ptr<SingleReleaseCallback> compositor1;
436   main_thread_.message_loop()->PostTask(
437       FROM_HERE,
438       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
439                  base::Unretained(this),
440                  &compositor1));
441
442   // Then the texture layer is removed and attached to compositor2, and passes a
443   // reference to its impl tree.
444   scoped_ptr<SingleReleaseCallback> compositor2;
445   main_thread_.message_loop()->PostTask(
446       FROM_HERE,
447       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
448                  base::Unretained(this),
449                  &compositor2));
450
451   Wait(main_thread_);
452   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
453
454   // The compositors both destroy their impl trees before the main thread layer
455   // is destroyed.
456   compositor1->Run(100, false);
457   compositor2->Run(200, false);
458
459   Wait(main_thread_);
460
461   EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
462   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
463
464   // The main thread ref is the last one, so the mailbox is released back to the
465   // embedder, with the last sync point provided by the impl trees.
466   EXPECT_CALL(test_data_.mock_callback_,
467               Release(test_data_.mailbox_name1_, 200, false)).Times(1);
468
469   main_thread_.message_loop()->PostTask(
470       FROM_HERE,
471       base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
472                  base::Unretained(this)));
473   Wait(main_thread_);
474   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
475 }
476
477 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) {
478   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
479   ASSERT_TRUE(test_layer.get());
480
481   main_thread_.message_loop()->PostTask(
482       FROM_HERE,
483       base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
484                  base::Unretained(this)));
485
486   Wait(main_thread_);
487
488   // The texture layer is attached to compositor1, and passes a reference to its
489   // impl tree.
490   scoped_ptr<SingleReleaseCallback> compositor1;
491   main_thread_.message_loop()->PostTask(
492       FROM_HERE,
493       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
494                  base::Unretained(this),
495                  &compositor1));
496
497   // Then the texture layer is removed and attached to compositor2, and passes a
498   // reference to its impl tree.
499   scoped_ptr<SingleReleaseCallback> compositor2;
500   main_thread_.message_loop()->PostTask(
501       FROM_HERE,
502       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
503                  base::Unretained(this),
504                  &compositor2));
505
506   Wait(main_thread_);
507   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
508
509   // One compositor destroys their impl tree.
510   compositor1->Run(100, false);
511
512   // Then the main thread reference is destroyed.
513   main_thread_.message_loop()->PostTask(
514       FROM_HERE,
515       base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
516                  base::Unretained(this)));
517
518   Wait(main_thread_);
519
520   EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
521   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
522
523   // The second impl reference is destroyed last, causing the mailbox to be
524   // released back to the embedder with the last sync point from the impl tree.
525   EXPECT_CALL(test_data_.mock_callback_,
526               Release(test_data_.mailbox_name1_, 200, true)).Times(1);
527
528   compositor2->Run(200, true);
529   Wait(main_thread_);
530   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
531 }
532
533 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) {
534   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
535   ASSERT_TRUE(test_layer.get());
536
537   main_thread_.message_loop()->PostTask(
538       FROM_HERE,
539       base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
540                  base::Unretained(this)));
541
542   Wait(main_thread_);
543
544   // The texture layer is attached to compositor1, and passes a reference to its
545   // impl tree.
546   scoped_ptr<SingleReleaseCallback> compositor1;
547   main_thread_.message_loop()->PostTask(
548       FROM_HERE,
549       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
550                  base::Unretained(this),
551                  &compositor1));
552
553   // Then the texture layer is removed and attached to compositor2, and passes a
554   // reference to its impl tree.
555   scoped_ptr<SingleReleaseCallback> compositor2;
556   main_thread_.message_loop()->PostTask(
557       FROM_HERE,
558       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
559                  base::Unretained(this),
560                  &compositor2));
561
562   Wait(main_thread_);
563   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
564
565   // The main thread reference is destroyed first.
566   main_thread_.message_loop()->PostTask(
567       FROM_HERE,
568       base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
569                  base::Unretained(this)));
570
571   // One compositor destroys their impl tree.
572   compositor2->Run(200, false);
573
574   Wait(main_thread_);
575
576   EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
577   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
578
579   // The second impl reference is destroyed last, causing the mailbox to be
580   // released back to the embedder with the last sync point from the impl tree.
581   EXPECT_CALL(test_data_.mock_callback_,
582               Release(test_data_.mailbox_name1_, 100, true)).Times(1);
583
584   compositor1->Run(100, true);
585   Wait(main_thread_);
586   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
587 }
588
589 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) {
590   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
591   ASSERT_TRUE(test_layer.get());
592
593   main_thread_.message_loop()->PostTask(
594       FROM_HERE,
595       base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
596                  base::Unretained(this)));
597
598   Wait(main_thread_);
599
600   // The texture layer is attached to compositor1, and passes a reference to its
601   // impl tree.
602   scoped_ptr<SingleReleaseCallback> compositor1;
603   main_thread_.message_loop()->PostTask(
604       FROM_HERE,
605       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
606                  base::Unretained(this),
607                  &compositor1));
608
609   // Then the texture layer is removed and attached to compositor2, and passes a
610   // reference to its impl tree.
611   scoped_ptr<SingleReleaseCallback> compositor2;
612   main_thread_.message_loop()->PostTask(
613       FROM_HERE,
614       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
615                  base::Unretained(this),
616                  &compositor2));
617
618   Wait(main_thread_);
619   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
620
621   // The main thread reference is destroyed first.
622   main_thread_.message_loop()->PostTask(
623       FROM_HERE,
624       base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
625                  base::Unretained(this)));
626
627   EXPECT_CALL(test_data_.mock_callback_,
628               Release(test_data_.mailbox_name1_, 200, true)).Times(1);
629
630   bool manual_reset = false;
631   bool initially_signaled = false;
632   base::WaitableEvent begin_capture(manual_reset, initially_signaled);
633   base::WaitableEvent wait_for_capture(manual_reset, initially_signaled);
634   base::WaitableEvent stop_capture(manual_reset, initially_signaled);
635
636   // Post a task to start capturing tasks on the main thread. This will block
637   // the main thread until we signal the |stop_capture| event.
638   main_thread_.message_loop()->PostTask(
639       FROM_HERE,
640       base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait,
641                  base::Unretained(this),
642                  &begin_capture,
643                  &wait_for_capture,
644                  &stop_capture));
645
646   // Before the main thread capturing starts, one compositor destroys their
647   // impl reference. Since capturing did not start, this gets post-tasked to
648   // the main thread.
649   compositor1->Run(100, false);
650
651   // Start capturing on the main thread.
652   begin_capture.Signal();
653   wait_for_capture.Wait();
654
655   // Meanwhile, the second compositor released its impl reference, but this task
656   // gets shortcutted directly to the main thread. This means the reference is
657   // released before compositor1, whose reference will be released later when
658   // the post-task is serviced. But since it was destroyed _on the impl thread_
659   // last, its sync point values should be used.
660   compositor2->Run(200, true);
661
662   stop_capture.Signal();
663   Wait(main_thread_);
664
665   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
666 }
667
668 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest {
669  public:
670   TextureLayerImplWithMailboxThreadedCallback()
671       : callback_count_(0),
672         commit_count_(0) {}
673
674   // Make sure callback is received on main and doesn't block the impl thread.
675   void ReleaseCallback(uint32 sync_point, bool lost_resource) {
676     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
677     EXPECT_FALSE(lost_resource);
678     ++callback_count_;
679   }
680
681   void SetMailbox(char mailbox_char) {
682     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
683     scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
684         base::Bind(
685             &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback,
686             base::Unretained(this)));
687     layer_->SetTextureMailbox(
688         TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
689         callback.Pass());
690   }
691
692   virtual void BeginTest() OVERRIDE {
693     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
694
695     gfx::Size bounds(100, 100);
696     root_ = Layer::Create();
697     root_->SetAnchorPoint(gfx::PointF());
698     root_->SetBounds(bounds);
699
700     layer_ = TextureLayer::CreateForMailbox(NULL);
701     layer_->SetIsDrawable(true);
702     layer_->SetAnchorPoint(gfx::PointF());
703     layer_->SetBounds(bounds);
704
705     root_->AddChild(layer_);
706     layer_tree_host()->SetRootLayer(root_);
707     layer_tree_host()->SetViewportSize(bounds);
708     SetMailbox('1');
709     EXPECT_EQ(0, callback_count_);
710
711     // Case #1: change mailbox before the commit. The old mailbox should be
712     // released immediately.
713     SetMailbox('2');
714     EXPECT_EQ(1, callback_count_);
715     PostSetNeedsCommitToMainThread();
716   }
717
718   virtual void DidCommit() OVERRIDE {
719     ++commit_count_;
720     switch (commit_count_) {
721       case 1:
722         // Case #2: change mailbox after the commit (and draw), where the
723         // layer draws. The old mailbox should be released during the next
724         // commit.
725         SetMailbox('3');
726         EXPECT_EQ(1, callback_count_);
727         break;
728       case 2:
729         EXPECT_EQ(2, callback_count_);
730         // Case #3: change mailbox when the layer doesn't draw. The old
731         // mailbox should be released during the next commit.
732         layer_->SetBounds(gfx::Size());
733         SetMailbox('4');
734         break;
735       case 3:
736         EXPECT_EQ(3, callback_count_);
737         // Case #4: release mailbox that was committed but never drawn. The
738         // old mailbox should be released during the next commit.
739         layer_->SetTextureMailbox(TextureMailbox(),
740                                   scoped_ptr<SingleReleaseCallback>());
741         break;
742       case 4:
743         if (layer_tree_host()->settings().impl_side_painting) {
744           // With impl painting, the texture mailbox will still be on the impl
745           // thread when the commit finishes, because the layer is not drawble
746           // when it has no texture mailbox, and thus does not block the commit
747           // on activation. So, we wait for activation.
748           // TODO(danakj): fix this. crbug.com/277953
749           layer_tree_host()->SetNeedsCommit();
750           break;
751         } else {
752           ++commit_count_;
753         }
754       case 5:
755         EXPECT_EQ(4, callback_count_);
756         // Restore a mailbox for the next step.
757         SetMailbox('5');
758         break;
759       case 6:
760         // Case #5: remove layer from tree. Callback should *not* be called, the
761         // mailbox is returned to the main thread.
762         EXPECT_EQ(4, callback_count_);
763         layer_->RemoveFromParent();
764         break;
765       case 7:
766         if (layer_tree_host()->settings().impl_side_painting) {
767           // With impl painting, the texture mailbox will still be on the impl
768           // thread when the commit finishes, because the layer is not around to
769           // block the commit on activation anymore. So, we wait for activation.
770           // TODO(danakj): fix this. crbug.com/277953
771           layer_tree_host()->SetNeedsCommit();
772           break;
773         } else {
774           ++commit_count_;
775         }
776       case 8:
777         EXPECT_EQ(4, callback_count_);
778         // Resetting the mailbox will call the callback now.
779         layer_->SetTextureMailbox(TextureMailbox(),
780                                   scoped_ptr<SingleReleaseCallback>());
781         EXPECT_EQ(5, callback_count_);
782         EndTest();
783         break;
784       default:
785         NOTREACHED();
786         break;
787     }
788   }
789
790   virtual void AfterTest() OVERRIDE {}
791
792  private:
793   base::ThreadChecker main_thread_;
794   int callback_count_;
795   int commit_count_;
796   scoped_refptr<Layer> root_;
797   scoped_refptr<TextureLayer> layer_;
798 };
799
800 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
801     TextureLayerImplWithMailboxThreadedCallback);
802
803
804 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
805  protected:
806   TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
807
808   static void ReleaseCallback(uint32 sync_point, bool lost_resource) {}
809
810   void SetMailbox(char mailbox_char) {
811     scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
812         base::Bind(
813             &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
814     layer_->SetTextureMailbox(
815         TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
816         callback.Pass());
817   }
818
819   virtual void BeginTest() OVERRIDE {
820     gfx::Size bounds(100, 100);
821     root_ = Layer::Create();
822     root_->SetAnchorPoint(gfx::PointF());
823     root_->SetBounds(bounds);
824
825     layer_ = TextureLayer::CreateForMailbox(NULL);
826     layer_->SetIsDrawable(true);
827     layer_->SetAnchorPoint(gfx::PointF());
828     layer_->SetBounds(bounds);
829
830     root_->AddChild(layer_);
831     layer_tree_host()->SetRootLayer(root_);
832     layer_tree_host()->SetViewportSize(bounds);
833     SetMailbox('1');
834
835     PostSetNeedsCommitToMainThread();
836   }
837
838   virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
839     ++activate_count_;
840   }
841
842   virtual void DidCommit() OVERRIDE {
843     switch (layer_tree_host()->source_frame_number()) {
844       case 1:
845         // The first mailbox has been activated. Set a new mailbox, and
846         // expect the next commit to finish *after* it is activated.
847         SetMailbox('2');
848         break;
849       case 2:
850         // The second mailbox has been activated. Remove the layer from
851         // the tree to cause another commit/activation. The commit should
852         // finish *after* the layer is removed from the active tree.
853         layer_->RemoveFromParent();
854         break;
855       case 3:
856         EndTest();
857         break;
858     }
859   }
860
861   virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
862     switch (host_impl->active_tree()->source_frame_number()) {
863       case 2: {
864         // The activate for the 2nd mailbox should have happened before now.
865         EXPECT_EQ(2, activate_count_);
866         break;
867       }
868       case 3: {
869         // The activate to remove the layer should have happened before now.
870         EXPECT_EQ(3, activate_count_);
871         break;
872       }
873     }
874   }
875
876
877   virtual void AfterTest() OVERRIDE {}
878
879   int activate_count_;
880   scoped_refptr<Layer> root_;
881   scoped_refptr<TextureLayer> layer_;
882 };
883
884 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
885     TextureLayerMailboxIsActivatedDuringCommit);
886
887 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
888  protected:
889   TextureLayerImplWithMailboxTest()
890       : fake_client_(
891           FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
892
893   virtual void SetUp() {
894     TextureLayerTest::SetUp();
895     layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
896     EXPECT_TRUE(host_impl_.InitializeRenderer(
897         FakeOutputSurface::Create3d().PassAs<OutputSurface>()));
898   }
899
900   bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
901     bool will_draw = layer->WillDraw(
902         mode, host_impl_.active_tree()->resource_provider());
903     if (will_draw)
904       layer->DidDraw(host_impl_.active_tree()->resource_provider());
905     return will_draw;
906   }
907
908   CommonMailboxObjects test_data_;
909   FakeLayerTreeHostClient fake_client_;
910 };
911
912 // Test conditions for results of TextureLayerImpl::WillDraw under
913 // different configurations of different mailbox, texture_id, and draw_mode.
914 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
915   EXPECT_CALL(test_data_.mock_callback_,
916               Release(test_data_.mailbox_name1_,
917                       test_data_.sync_point1_,
918                       false))
919       .Times(AnyNumber());
920   EXPECT_CALL(test_data_.mock_callback_,
921               Release2(test_data_.shared_memory_.get(), 0, false))
922       .Times(AnyNumber());
923   // Hardware mode.
924   {
925     scoped_ptr<TextureLayerImpl> impl_layer =
926         TextureLayerImpl::Create(host_impl_.active_tree(), 1);
927     impl_layer->SetDrawsContent(true);
928     impl_layer->SetTextureMailbox(
929         test_data_.mailbox1_,
930         SingleReleaseCallback::Create(test_data_.release_mailbox1_));
931     EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
932   }
933
934   {
935     scoped_ptr<TextureLayerImpl> impl_layer =
936         TextureLayerImpl::Create(host_impl_.active_tree(), 1);
937     impl_layer->SetDrawsContent(true);
938     impl_layer->SetTextureMailbox(TextureMailbox(),
939                                   scoped_ptr<SingleReleaseCallback>());
940     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
941   }
942
943   {
944     // Software resource.
945     scoped_ptr<TextureLayerImpl> impl_layer =
946         TextureLayerImpl::Create(host_impl_.active_tree(), 1);
947     impl_layer->SetDrawsContent(true);
948     impl_layer->SetTextureMailbox(
949         test_data_.mailbox3_,
950         SingleReleaseCallback::Create(test_data_.release_mailbox3_));
951     EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
952   }
953
954   // Software mode.
955   {
956     scoped_ptr<TextureLayerImpl> impl_layer =
957         TextureLayerImpl::Create(host_impl_.active_tree(), 1);
958     impl_layer->SetDrawsContent(true);
959     impl_layer->SetTextureMailbox(
960         test_data_.mailbox1_,
961         SingleReleaseCallback::Create(test_data_.release_mailbox1_));
962     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
963   }
964
965   {
966     scoped_ptr<TextureLayerImpl> impl_layer =
967         TextureLayerImpl::Create(host_impl_.active_tree(), 1);
968     impl_layer->SetDrawsContent(true);
969     impl_layer->SetTextureMailbox(TextureMailbox(),
970                                   scoped_ptr<SingleReleaseCallback>());
971     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
972   }
973
974   {
975     // Software resource.
976     scoped_ptr<TextureLayerImpl> impl_layer =
977         TextureLayerImpl::Create(host_impl_.active_tree(), 1);
978     impl_layer->SetDrawsContent(true);
979     impl_layer->SetTextureMailbox(
980         test_data_.mailbox3_,
981         SingleReleaseCallback::Create(test_data_.release_mailbox3_));
982     EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
983   }
984
985   // Resourceless software mode.
986   {
987     scoped_ptr<TextureLayerImpl> impl_layer =
988         TextureLayerImpl::Create(host_impl_.active_tree(), 1);
989     impl_layer->SetDrawsContent(true);
990     impl_layer->SetTextureMailbox(
991         test_data_.mailbox1_,
992         SingleReleaseCallback::Create(test_data_.release_mailbox1_));
993     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
994   }
995 }
996
997 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
998   host_impl_.CreatePendingTree();
999   scoped_ptr<TextureLayerImpl> pending_layer;
1000   pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1);
1001   ASSERT_TRUE(pending_layer);
1002
1003   scoped_ptr<LayerImpl> active_layer(
1004       pending_layer->CreateLayerImpl(host_impl_.active_tree()));
1005   ASSERT_TRUE(active_layer);
1006
1007   pending_layer->SetTextureMailbox(
1008       test_data_.mailbox1_,
1009       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1010
1011   // Test multiple commits without an activation.
1012   EXPECT_CALL(test_data_.mock_callback_,
1013               Release(test_data_.mailbox_name1_,
1014                       test_data_.sync_point1_,
1015                       false))
1016       .Times(1);
1017   pending_layer->SetTextureMailbox(
1018       test_data_.mailbox2_,
1019       SingleReleaseCallback::Create(test_data_.release_mailbox2_));
1020   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1021
1022   // Test callback after activation.
1023   pending_layer->PushPropertiesTo(active_layer.get());
1024   active_layer->DidBecomeActive();
1025
1026   EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1027   pending_layer->SetTextureMailbox(
1028       test_data_.mailbox1_,
1029       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1030   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1031
1032   EXPECT_CALL(test_data_.mock_callback_,
1033               Release(test_data_.mailbox_name2_, _, false))
1034       .Times(1);
1035   pending_layer->PushPropertiesTo(active_layer.get());
1036   active_layer->DidBecomeActive();
1037   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1038
1039   // Test resetting the mailbox.
1040   EXPECT_CALL(test_data_.mock_callback_,
1041               Release(test_data_.mailbox_name1_, _, false))
1042       .Times(1);
1043   pending_layer->SetTextureMailbox(TextureMailbox(),
1044                                    scoped_ptr<SingleReleaseCallback>());
1045   pending_layer->PushPropertiesTo(active_layer.get());
1046   active_layer->DidBecomeActive();
1047   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1048
1049   // Test destructor.
1050   EXPECT_CALL(test_data_.mock_callback_,
1051               Release(test_data_.mailbox_name1_,
1052                       test_data_.sync_point1_,
1053                       false))
1054       .Times(1);
1055   pending_layer->SetTextureMailbox(
1056       test_data_.mailbox1_,
1057       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1058 }
1059
1060 TEST_F(TextureLayerImplWithMailboxTest,
1061        TestDestructorCallbackOnCreatedResource) {
1062   scoped_ptr<TextureLayerImpl> impl_layer;
1063   impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1064   ASSERT_TRUE(impl_layer);
1065
1066   EXPECT_CALL(test_data_.mock_callback_,
1067               Release(test_data_.mailbox_name1_, _, false))
1068       .Times(1);
1069   impl_layer->SetTextureMailbox(
1070       test_data_.mailbox1_,
1071       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1072   impl_layer->SetDrawsContent(true);
1073   impl_layer->DidBecomeActive();
1074   EXPECT_TRUE(impl_layer->WillDraw(
1075       DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1076   impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1077   impl_layer->SetTextureMailbox(TextureMailbox(),
1078                                 scoped_ptr<SingleReleaseCallback>());
1079 }
1080
1081 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1082   ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1083   ResourceProvider::ResourceId id =
1084       provider->CreateResourceFromTextureMailbox(
1085           test_data_.mailbox1_,
1086           SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1087   provider->AllocateForTesting(id);
1088
1089   // Transfer some resources to the parent.
1090   ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1091   resource_ids_to_transfer.push_back(id);
1092   TransferableResourceArray list;
1093   provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1094   EXPECT_TRUE(provider->InUseByConsumer(id));
1095   EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1096   provider->DeleteResource(id);
1097   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1098   EXPECT_CALL(test_data_.mock_callback_,
1099               Release(test_data_.mailbox_name1_, _, false))
1100       .Times(1);
1101   ReturnedResourceArray returned;
1102   TransferableResource::ReturnResources(list, &returned);
1103   provider->ReceiveReturnsFromParent(returned);
1104 }
1105
1106 // Checks that TextureLayer::Update does not cause an extra commit when setting
1107 // the texture mailbox.
1108 class TextureLayerNoExtraCommitForMailboxTest
1109     : public LayerTreeTest,
1110       public TextureLayerClient {
1111  public:
1112   // TextureLayerClient implementation.
1113   virtual bool PrepareTextureMailbox(
1114       TextureMailbox* texture_mailbox,
1115       scoped_ptr<SingleReleaseCallback>* release_callback,
1116       bool use_shared_memory) OVERRIDE {
1117     if (layer_tree_host()->source_frame_number() == 1) {
1118       *texture_mailbox = TextureMailbox();
1119       return true;
1120     }
1121
1122     *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1123     *release_callback = SingleReleaseCallback::Create(
1124         base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1125                    base::Unretained(this)));
1126     return true;
1127   }
1128
1129   void MailboxReleased(uint32 sync_point, bool lost_resource) {
1130     EXPECT_EQ(2, layer_tree_host()->source_frame_number());
1131     EndTest();
1132   }
1133
1134   virtual void SetupTree() OVERRIDE {
1135     scoped_refptr<Layer> root = Layer::Create();
1136     root->SetBounds(gfx::Size(10, 10));
1137     root->SetAnchorPoint(gfx::PointF());
1138     root->SetIsDrawable(true);
1139
1140     texture_layer_ = TextureLayer::CreateForMailbox(this);
1141     texture_layer_->SetBounds(gfx::Size(10, 10));
1142     texture_layer_->SetAnchorPoint(gfx::PointF());
1143     texture_layer_->SetIsDrawable(true);
1144     root->AddChild(texture_layer_);
1145
1146     layer_tree_host()->SetRootLayer(root);
1147     LayerTreeTest::SetupTree();
1148   }
1149
1150   virtual void BeginTest() OVERRIDE {
1151     PostSetNeedsCommitToMainThread();
1152   }
1153
1154   virtual void DidCommitAndDrawFrame() OVERRIDE {
1155     switch (layer_tree_host()->source_frame_number()) {
1156       case 1:
1157         EXPECT_FALSE(proxy()->CommitPendingForTesting());
1158         // Invalidate the texture layer to clear the mailbox before
1159         // ending the test.
1160         texture_layer_->SetNeedsDisplay();
1161         break;
1162       case 2:
1163         break;
1164       default:
1165         NOTREACHED();
1166         break;
1167     }
1168   }
1169
1170   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1171                                    bool result) OVERRIDE {
1172     ASSERT_TRUE(result);
1173     DelegatedFrameData* delegated_frame_data =
1174         output_surface()->last_sent_frame().delegated_frame_data.get();
1175     if (!delegated_frame_data)
1176       return;
1177
1178     // Return all resources immediately.
1179     TransferableResourceArray resources_to_return =
1180         output_surface()->resources_held_by_parent();
1181
1182     CompositorFrameAck ack;
1183     for (size_t i = 0; i < resources_to_return.size(); ++i)
1184       output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1185     host_impl->ReclaimResources(&ack);
1186   }
1187
1188   virtual void AfterTest() OVERRIDE {}
1189
1190  private:
1191   scoped_refptr<TextureLayer> texture_layer_;
1192 };
1193
1194 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1195
1196 // Checks that changing a mailbox in the client for a TextureLayer that's
1197 // invisible correctly works and uses the new mailbox as soon as the layer
1198 // becomes visible (and returns the old one).
1199 class TextureLayerChangeInvisibleMailboxTest
1200     : public LayerTreeTest,
1201       public TextureLayerClient {
1202  public:
1203   TextureLayerChangeInvisibleMailboxTest()
1204       : mailbox_changed_(true),
1205         mailbox_returned_(0),
1206         prepare_called_(0),
1207         commit_count_(0) {
1208     mailbox_ = MakeMailbox('1');
1209   }
1210
1211   // TextureLayerClient implementation.
1212   virtual bool PrepareTextureMailbox(
1213       TextureMailbox* mailbox,
1214       scoped_ptr<SingleReleaseCallback>* release_callback,
1215       bool use_shared_memory) OVERRIDE {
1216     ++prepare_called_;
1217     if (!mailbox_changed_)
1218       return false;
1219     *mailbox = mailbox_;
1220     *release_callback = SingleReleaseCallback::Create(
1221         base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1222                    base::Unretained(this)));
1223     return true;
1224   }
1225
1226   TextureMailbox MakeMailbox(char name) {
1227     return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0);
1228   }
1229
1230   void MailboxReleased(uint32 sync_point, bool lost_resource) {
1231     ++mailbox_returned_;
1232   }
1233
1234   virtual void SetupTree() OVERRIDE {
1235     scoped_refptr<Layer> root = Layer::Create();
1236     root->SetBounds(gfx::Size(10, 10));
1237     root->SetAnchorPoint(gfx::PointF());
1238     root->SetIsDrawable(true);
1239
1240     solid_layer_ = SolidColorLayer::Create();
1241     solid_layer_->SetBounds(gfx::Size(10, 10));
1242     solid_layer_->SetIsDrawable(true);
1243     solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1244     root->AddChild(solid_layer_);
1245
1246     parent_layer_ = Layer::Create();
1247     parent_layer_->SetBounds(gfx::Size(10, 10));
1248     parent_layer_->SetIsDrawable(true);
1249     root->AddChild(parent_layer_);
1250
1251     texture_layer_ = TextureLayer::CreateForMailbox(this);
1252     texture_layer_->SetBounds(gfx::Size(10, 10));
1253     texture_layer_->SetAnchorPoint(gfx::PointF());
1254     texture_layer_->SetIsDrawable(true);
1255     parent_layer_->AddChild(texture_layer_);
1256
1257     layer_tree_host()->SetRootLayer(root);
1258     LayerTreeTest::SetupTree();
1259   }
1260
1261   virtual void BeginTest() OVERRIDE {
1262     PostSetNeedsCommitToMainThread();
1263   }
1264
1265   virtual void DidCommitAndDrawFrame() OVERRIDE {
1266     ++commit_count_;
1267     switch (commit_count_) {
1268       case 1:
1269         // We should have updated the layer, committing the texture.
1270         EXPECT_EQ(1, prepare_called_);
1271         // Make layer invisible.
1272         parent_layer_->SetOpacity(0.f);
1273         break;
1274       case 2:
1275         // Layer shouldn't have been updated.
1276         EXPECT_EQ(1, prepare_called_);
1277         // Change the texture.
1278         mailbox_ = MakeMailbox('2');
1279         mailbox_changed_ = true;
1280         texture_layer_->SetNeedsDisplay();
1281         // Force a change to make sure we draw a frame.
1282         solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1283         break;
1284       case 3:
1285         // Layer shouldn't have been updated.
1286         EXPECT_EQ(1, prepare_called_);
1287         // So the old mailbox isn't returned yet.
1288         EXPECT_EQ(0, mailbox_returned_);
1289         // Make layer visible again.
1290         parent_layer_->SetOpacity(1.f);
1291         break;
1292       case 4:
1293         // Layer should have been updated.
1294         EXPECT_EQ(2, prepare_called_);
1295         // So the old mailbox should have been returned already.
1296         EXPECT_EQ(1, mailbox_returned_);
1297         texture_layer_->ClearClient();
1298         break;
1299       case 5:
1300         EXPECT_EQ(2, mailbox_returned_);
1301         EndTest();
1302         break;
1303       default:
1304         NOTREACHED();
1305         break;
1306     }
1307   }
1308
1309   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1310                                    bool result) OVERRIDE {
1311     ASSERT_TRUE(result);
1312     DelegatedFrameData* delegated_frame_data =
1313         output_surface()->last_sent_frame().delegated_frame_data.get();
1314     if (!delegated_frame_data)
1315       return;
1316
1317     // Return all resources immediately.
1318     TransferableResourceArray resources_to_return =
1319         output_surface()->resources_held_by_parent();
1320
1321     CompositorFrameAck ack;
1322     for (size_t i = 0; i < resources_to_return.size(); ++i)
1323       output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1324     host_impl->ReclaimResources(&ack);
1325   }
1326
1327   virtual void AfterTest() OVERRIDE {}
1328
1329  private:
1330   scoped_refptr<SolidColorLayer> solid_layer_;
1331   scoped_refptr<Layer> parent_layer_;
1332   scoped_refptr<TextureLayer> texture_layer_;
1333
1334   // Used on the main thread.
1335   bool mailbox_changed_;
1336   TextureMailbox mailbox_;
1337   int mailbox_returned_;
1338   int prepare_called_;
1339   int commit_count_;
1340 };
1341
1342 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1343
1344 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1345 // the mailbox back to TextureLayerClient.
1346 class TextureLayerReleaseResourcesBase
1347     : public LayerTreeTest,
1348       public TextureLayerClient {
1349  public:
1350   // TextureLayerClient implementation.
1351   virtual bool PrepareTextureMailbox(
1352       TextureMailbox* mailbox,
1353       scoped_ptr<SingleReleaseCallback>* release_callback,
1354       bool use_shared_memory) OVERRIDE {
1355     *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1356     *release_callback = SingleReleaseCallback::Create(
1357         base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1358                    base::Unretained(this)));
1359     return true;
1360   }
1361
1362   void MailboxReleased(unsigned sync_point, bool lost_resource) {
1363     mailbox_released_ = true;
1364   }
1365
1366   virtual void SetupTree() OVERRIDE {
1367     LayerTreeTest::SetupTree();
1368
1369     scoped_refptr<TextureLayer> texture_layer =
1370         TextureLayer::CreateForMailbox(this);
1371     texture_layer->SetBounds(gfx::Size(10, 10));
1372     texture_layer->SetAnchorPoint(gfx::PointF());
1373     texture_layer->SetIsDrawable(true);
1374
1375     layer_tree_host()->root_layer()->AddChild(texture_layer);
1376   }
1377
1378   virtual void BeginTest() OVERRIDE {
1379     mailbox_released_ = false;
1380     PostSetNeedsCommitToMainThread();
1381   }
1382
1383   virtual void DidCommitAndDrawFrame() OVERRIDE {
1384     EndTest();
1385   }
1386
1387   virtual void AfterTest() OVERRIDE {
1388     EXPECT_TRUE(mailbox_released_);
1389   }
1390
1391  private:
1392   bool mailbox_released_;
1393 };
1394
1395 class TextureLayerReleaseResourcesAfterCommit
1396     : public TextureLayerReleaseResourcesBase {
1397  public:
1398   virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1399     LayerTreeImpl* tree = NULL;
1400     if (host_impl->settings().impl_side_painting)
1401       tree = host_impl->pending_tree();
1402     else
1403       tree = host_impl->active_tree();
1404     tree->root_layer()->children()[0]->ReleaseResources();
1405   }
1406 };
1407
1408 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1409
1410 class TextureLayerReleaseResourcesAfterActivate
1411     : public TextureLayerReleaseResourcesBase {
1412  public:
1413   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1414     host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
1415   }
1416 };
1417
1418 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
1419
1420 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
1421  public:
1422   void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1423     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1424     EXPECT_FALSE(lost_resource);
1425     ++callback_count_;
1426     EndTest();
1427   }
1428
1429   void SetMailbox(char mailbox_char) {
1430     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1431     scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1432         base::Bind(
1433             &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
1434             base::Unretained(this)));
1435     layer_->SetTextureMailbox(
1436         TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1437         callback.Pass());
1438   }
1439
1440   virtual void SetupTree() OVERRIDE {
1441     gfx::Size bounds(100, 100);
1442     root_ = Layer::Create();
1443     root_->SetAnchorPoint(gfx::PointF());
1444     root_->SetBounds(bounds);
1445
1446     layer_ = TextureLayer::CreateForMailbox(NULL);
1447     layer_->SetIsDrawable(true);
1448     layer_->SetAnchorPoint(gfx::PointF());
1449     layer_->SetBounds(bounds);
1450
1451     root_->AddChild(layer_);
1452     layer_tree_host()->SetRootLayer(root_);
1453     layer_tree_host()->SetViewportSize(bounds);
1454   }
1455
1456   virtual void BeginTest() OVERRIDE {
1457     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1458
1459     callback_count_ = 0;
1460
1461     // Set the mailbox on the main thread.
1462     SetMailbox('1');
1463     EXPECT_EQ(0, callback_count_);
1464
1465     PostSetNeedsCommitToMainThread();
1466   }
1467
1468   virtual void DidCommitAndDrawFrame() OVERRIDE {
1469     switch (layer_tree_host()->source_frame_number()) {
1470       case 1:
1471         // Delete the TextureLayer on the main thread while the mailbox is in
1472         // the impl tree.
1473         layer_->RemoveFromParent();
1474         layer_ = NULL;
1475         break;
1476     }
1477   }
1478
1479   virtual void AfterTest() OVERRIDE {
1480     EXPECT_EQ(1, callback_count_);
1481   }
1482
1483  private:
1484   base::ThreadChecker main_thread_;
1485   int callback_count_;
1486   scoped_refptr<Layer> root_;
1487   scoped_refptr<TextureLayer> layer_;
1488 };
1489
1490 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1491     TextureLayerWithMailboxMainThreadDeleted);
1492
1493 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
1494  public:
1495   void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1496     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1497     EXPECT_FALSE(lost_resource);
1498     ++callback_count_;
1499     EndTest();
1500   }
1501
1502   void SetMailbox(char mailbox_char) {
1503     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1504     scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1505         base::Bind(
1506             &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
1507             base::Unretained(this)));
1508     layer_->SetTextureMailbox(
1509         TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1510         callback.Pass());
1511   }
1512
1513   virtual void SetupTree() OVERRIDE {
1514     gfx::Size bounds(100, 100);
1515     root_ = Layer::Create();
1516     root_->SetAnchorPoint(gfx::PointF());
1517     root_->SetBounds(bounds);
1518
1519     layer_ = TextureLayer::CreateForMailbox(NULL);
1520     layer_->SetIsDrawable(true);
1521     layer_->SetAnchorPoint(gfx::PointF());
1522     layer_->SetBounds(bounds);
1523
1524     root_->AddChild(layer_);
1525     layer_tree_host()->SetRootLayer(root_);
1526     layer_tree_host()->SetViewportSize(bounds);
1527   }
1528
1529   virtual void BeginTest() OVERRIDE {
1530     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1531
1532     callback_count_ = 0;
1533
1534     // Set the mailbox on the main thread.
1535     SetMailbox('1');
1536     EXPECT_EQ(0, callback_count_);
1537
1538     PostSetNeedsCommitToMainThread();
1539   }
1540
1541   virtual void DidCommitAndDrawFrame() OVERRIDE {
1542     switch (layer_tree_host()->source_frame_number()) {
1543       case 1:
1544         // Remove the TextureLayer on the main thread while the mailbox is in
1545         // the impl tree, but don't delete the TextureLayer until after the impl
1546         // tree side is deleted.
1547         layer_->RemoveFromParent();
1548         break;
1549       case 2:
1550         layer_ = NULL;
1551         break;
1552     }
1553   }
1554
1555   virtual void AfterTest() OVERRIDE {
1556     EXPECT_EQ(1, callback_count_);
1557   }
1558
1559  private:
1560   base::ThreadChecker main_thread_;
1561   int callback_count_;
1562   scoped_refptr<Layer> root_;
1563   scoped_refptr<TextureLayer> layer_;
1564 };
1565
1566 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1567     TextureLayerWithMailboxImplThreadDeleted);
1568
1569 }  // namespace
1570 }  // namespace cc