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