Upstream version 9.38.198.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, NULL, 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   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_->SetBounds(bounds);
698
699     layer_ = TextureLayer::CreateForMailbox(NULL);
700     layer_->SetIsDrawable(true);
701     layer_->SetBounds(bounds);
702
703     root_->AddChild(layer_);
704     layer_tree_host()->SetRootLayer(root_);
705     layer_tree_host()->SetViewportSize(bounds);
706     SetMailbox('1');
707     EXPECT_EQ(0, callback_count_);
708
709     // Case #1: change mailbox before the commit. The old mailbox should be
710     // released immediately.
711     SetMailbox('2');
712     EXPECT_EQ(1, callback_count_);
713     PostSetNeedsCommitToMainThread();
714   }
715
716   virtual void DidCommit() OVERRIDE {
717     ++commit_count_;
718     switch (commit_count_) {
719       case 1:
720         // Case #2: change mailbox after the commit (and draw), where the
721         // layer draws. The old mailbox should be released during the next
722         // commit.
723         SetMailbox('3');
724         EXPECT_EQ(1, callback_count_);
725         break;
726       case 2:
727         EXPECT_EQ(2, callback_count_);
728         // Case #3: change mailbox when the layer doesn't draw. The old
729         // mailbox should be released during the next commit.
730         layer_->SetBounds(gfx::Size());
731         SetMailbox('4');
732         break;
733       case 3:
734         EXPECT_EQ(3, callback_count_);
735         // Case #4: release mailbox that was committed but never drawn. The
736         // old mailbox should be released during the next commit.
737         layer_->SetTextureMailbox(TextureMailbox(),
738                                   scoped_ptr<SingleReleaseCallback>());
739         break;
740       case 4:
741         if (layer_tree_host()->settings().impl_side_painting) {
742           // With impl painting, the texture mailbox will still be on the impl
743           // thread when the commit finishes, because the layer is not drawble
744           // when it has no texture mailbox, and thus does not block the commit
745           // on activation. So, we wait for activation.
746           // TODO(danakj): fix this. crbug.com/277953
747           layer_tree_host()->SetNeedsCommit();
748           break;
749         } else {
750           ++commit_count_;
751         }
752       case 5:
753         EXPECT_EQ(4, callback_count_);
754         // Restore a mailbox for the next step.
755         SetMailbox('5');
756         break;
757       case 6:
758         // Case #5: remove layer from tree. Callback should *not* be called, the
759         // mailbox is returned to the main thread.
760         EXPECT_EQ(4, callback_count_);
761         layer_->RemoveFromParent();
762         break;
763       case 7:
764         if (layer_tree_host()->settings().impl_side_painting) {
765           // With impl painting, the texture mailbox will still be on the impl
766           // thread when the commit finishes, because the layer is not around to
767           // block the commit on activation anymore. So, we wait for activation.
768           // TODO(danakj): fix this. crbug.com/277953
769           layer_tree_host()->SetNeedsCommit();
770           break;
771         } else {
772           ++commit_count_;
773         }
774       case 8:
775         EXPECT_EQ(4, callback_count_);
776         // Resetting the mailbox will call the callback now.
777         layer_->SetTextureMailbox(TextureMailbox(),
778                                   scoped_ptr<SingleReleaseCallback>());
779         EXPECT_EQ(5, callback_count_);
780         EndTest();
781         break;
782       default:
783         NOTREACHED();
784         break;
785     }
786   }
787
788   virtual void AfterTest() OVERRIDE {}
789
790  private:
791   base::ThreadChecker main_thread_;
792   int callback_count_;
793   int commit_count_;
794   scoped_refptr<Layer> root_;
795   scoped_refptr<TextureLayer> layer_;
796 };
797
798 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
799     TextureLayerImplWithMailboxThreadedCallback);
800
801
802 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
803  protected:
804   TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
805
806   static void ReleaseCallback(uint32 sync_point, bool lost_resource) {}
807
808   void SetMailbox(char mailbox_char) {
809     scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
810         base::Bind(
811             &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
812     layer_->SetTextureMailbox(
813         TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
814         callback.Pass());
815   }
816
817   virtual void BeginTest() OVERRIDE {
818     gfx::Size bounds(100, 100);
819     root_ = Layer::Create();
820     root_->SetBounds(bounds);
821
822     layer_ = TextureLayer::CreateForMailbox(NULL);
823     layer_->SetIsDrawable(true);
824     layer_->SetBounds(bounds);
825
826     root_->AddChild(layer_);
827     layer_tree_host()->SetRootLayer(root_);
828     layer_tree_host()->SetViewportSize(bounds);
829     SetMailbox('1');
830
831     PostSetNeedsCommitToMainThread();
832   }
833
834   virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
835     ++activate_count_;
836   }
837
838   virtual void DidCommit() OVERRIDE {
839     switch (layer_tree_host()->source_frame_number()) {
840       case 1:
841         // The first mailbox has been activated. Set a new mailbox, and
842         // expect the next commit to finish *after* it is activated.
843         SetMailbox('2');
844         break;
845       case 2:
846         // The second mailbox has been activated. Remove the layer from
847         // the tree to cause another commit/activation. The commit should
848         // finish *after* the layer is removed from the active tree.
849         layer_->RemoveFromParent();
850         break;
851       case 3:
852         EndTest();
853         break;
854     }
855   }
856
857   virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
858     switch (host_impl->active_tree()->source_frame_number()) {
859       case 0: {
860         // The activate for the 1st mailbox should have happened before now.
861         EXPECT_EQ(1, activate_count_);
862         break;
863       }
864       case 1: {
865         // The activate for the 2nd mailbox should have happened before now.
866         EXPECT_EQ(2, activate_count_);
867         break;
868       }
869       case 2: {
870         // The activate to remove the layer should have happened before now.
871         EXPECT_EQ(3, activate_count_);
872         break;
873       }
874       case 3: {
875         NOTREACHED();
876         break;
877       }
878     }
879   }
880
881
882   virtual void AfterTest() OVERRIDE {}
883
884   int activate_count_;
885   scoped_refptr<Layer> root_;
886   scoped_refptr<TextureLayer> layer_;
887 };
888
889 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
890     TextureLayerMailboxIsActivatedDuringCommit);
891
892 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
893  protected:
894   TextureLayerImplWithMailboxTest()
895       : fake_client_(
896           FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
897
898   virtual void SetUp() {
899     TextureLayerTest::SetUp();
900     layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
901     EXPECT_TRUE(host_impl_.InitializeRenderer(
902         FakeOutputSurface::Create3d().PassAs<OutputSurface>()));
903   }
904
905   bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
906     bool will_draw = layer->WillDraw(
907         mode, host_impl_.active_tree()->resource_provider());
908     if (will_draw)
909       layer->DidDraw(host_impl_.active_tree()->resource_provider());
910     return will_draw;
911   }
912
913   CommonMailboxObjects test_data_;
914   FakeLayerTreeHostClient fake_client_;
915 };
916
917 // Test conditions for results of TextureLayerImpl::WillDraw under
918 // different configurations of different mailbox, texture_id, and draw_mode.
919 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
920   EXPECT_CALL(test_data_.mock_callback_,
921               Release(test_data_.mailbox_name1_,
922                       test_data_.sync_point1_,
923                       false))
924       .Times(AnyNumber());
925   EXPECT_CALL(test_data_.mock_callback_,
926               Release2(test_data_.shared_memory_.get(), 0, false))
927       .Times(AnyNumber());
928   // Hardware mode.
929   {
930     scoped_ptr<TextureLayerImpl> impl_layer =
931         TextureLayerImpl::Create(host_impl_.active_tree(), 1);
932     impl_layer->SetTextureMailbox(
933         test_data_.mailbox1_,
934         SingleReleaseCallback::Create(test_data_.release_mailbox1_));
935     EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
936   }
937
938   {
939     scoped_ptr<TextureLayerImpl> impl_layer =
940         TextureLayerImpl::Create(host_impl_.active_tree(), 1);
941     impl_layer->SetTextureMailbox(TextureMailbox(),
942                                   scoped_ptr<SingleReleaseCallback>());
943     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
944   }
945
946   {
947     // Software resource.
948     scoped_ptr<TextureLayerImpl> impl_layer =
949         TextureLayerImpl::Create(host_impl_.active_tree(), 1);
950     impl_layer->SetTextureMailbox(
951         test_data_.mailbox3_,
952         SingleReleaseCallback::Create(test_data_.release_mailbox3_));
953     EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
954   }
955
956   // Software mode.
957   {
958     scoped_ptr<TextureLayerImpl> impl_layer =
959         TextureLayerImpl::Create(host_impl_.active_tree(), 1);
960     impl_layer->SetTextureMailbox(
961         test_data_.mailbox1_,
962         SingleReleaseCallback::Create(test_data_.release_mailbox1_));
963     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
964   }
965
966   {
967     scoped_ptr<TextureLayerImpl> impl_layer =
968         TextureLayerImpl::Create(host_impl_.active_tree(), 1);
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->SetTextureMailbox(
979         test_data_.mailbox3_,
980         SingleReleaseCallback::Create(test_data_.release_mailbox3_));
981     EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
982   }
983
984   // Resourceless software mode.
985   {
986     scoped_ptr<TextureLayerImpl> impl_layer =
987         TextureLayerImpl::Create(host_impl_.active_tree(), 1);
988     impl_layer->SetTextureMailbox(
989         test_data_.mailbox1_,
990         SingleReleaseCallback::Create(test_data_.release_mailbox1_));
991     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
992   }
993 }
994
995 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
996   host_impl_.CreatePendingTree();
997   scoped_ptr<TextureLayerImpl> pending_layer;
998   pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1);
999   ASSERT_TRUE(pending_layer);
1000
1001   scoped_ptr<LayerImpl> active_layer(
1002       pending_layer->CreateLayerImpl(host_impl_.active_tree()));
1003   ASSERT_TRUE(active_layer);
1004
1005   pending_layer->SetTextureMailbox(
1006       test_data_.mailbox1_,
1007       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1008
1009   // Test multiple commits without an activation.
1010   EXPECT_CALL(test_data_.mock_callback_,
1011               Release(test_data_.mailbox_name1_,
1012                       test_data_.sync_point1_,
1013                       false))
1014       .Times(1);
1015   pending_layer->SetTextureMailbox(
1016       test_data_.mailbox2_,
1017       SingleReleaseCallback::Create(test_data_.release_mailbox2_));
1018   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1019
1020   // Test callback after activation.
1021   pending_layer->PushPropertiesTo(active_layer.get());
1022   active_layer->DidBecomeActive();
1023
1024   EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1025   pending_layer->SetTextureMailbox(
1026       test_data_.mailbox1_,
1027       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1028   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1029
1030   EXPECT_CALL(test_data_.mock_callback_,
1031               Release(test_data_.mailbox_name2_, _, false))
1032       .Times(1);
1033   pending_layer->PushPropertiesTo(active_layer.get());
1034   active_layer->DidBecomeActive();
1035   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1036
1037   // Test resetting the mailbox.
1038   EXPECT_CALL(test_data_.mock_callback_,
1039               Release(test_data_.mailbox_name1_, _, false))
1040       .Times(1);
1041   pending_layer->SetTextureMailbox(TextureMailbox(),
1042                                    scoped_ptr<SingleReleaseCallback>());
1043   pending_layer->PushPropertiesTo(active_layer.get());
1044   active_layer->DidBecomeActive();
1045   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1046
1047   // Test destructor.
1048   EXPECT_CALL(test_data_.mock_callback_,
1049               Release(test_data_.mailbox_name1_,
1050                       test_data_.sync_point1_,
1051                       false))
1052       .Times(1);
1053   pending_layer->SetTextureMailbox(
1054       test_data_.mailbox1_,
1055       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1056 }
1057
1058 TEST_F(TextureLayerImplWithMailboxTest,
1059        TestDestructorCallbackOnCreatedResource) {
1060   scoped_ptr<TextureLayerImpl> impl_layer;
1061   impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1062   ASSERT_TRUE(impl_layer);
1063
1064   EXPECT_CALL(test_data_.mock_callback_,
1065               Release(test_data_.mailbox_name1_, _, false))
1066       .Times(1);
1067   impl_layer->SetTextureMailbox(
1068       test_data_.mailbox1_,
1069       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1070   impl_layer->DidBecomeActive();
1071   EXPECT_TRUE(impl_layer->WillDraw(
1072       DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1073   impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1074   impl_layer->SetTextureMailbox(TextureMailbox(),
1075                                 scoped_ptr<SingleReleaseCallback>());
1076 }
1077
1078 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1079   ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1080   ResourceProvider::ResourceId id =
1081       provider->CreateResourceFromTextureMailbox(
1082           test_data_.mailbox1_,
1083           SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1084   provider->AllocateForTesting(id);
1085
1086   // Transfer some resources to the parent.
1087   ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1088   resource_ids_to_transfer.push_back(id);
1089   TransferableResourceArray list;
1090   provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1091   EXPECT_TRUE(provider->InUseByConsumer(id));
1092   EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1093   provider->DeleteResource(id);
1094   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1095   EXPECT_CALL(test_data_.mock_callback_,
1096               Release(test_data_.mailbox_name1_, _, false))
1097       .Times(1);
1098   ReturnedResourceArray returned;
1099   TransferableResource::ReturnResources(list, &returned);
1100   provider->ReceiveReturnsFromParent(returned);
1101 }
1102
1103 // Checks that TextureLayer::Update does not cause an extra commit when setting
1104 // the texture mailbox.
1105 class TextureLayerNoExtraCommitForMailboxTest
1106     : public LayerTreeTest,
1107       public TextureLayerClient {
1108  public:
1109   // TextureLayerClient implementation.
1110   virtual bool PrepareTextureMailbox(
1111       TextureMailbox* texture_mailbox,
1112       scoped_ptr<SingleReleaseCallback>* release_callback,
1113       bool use_shared_memory) OVERRIDE {
1114     if (layer_tree_host()->source_frame_number() == 1) {
1115       // Once this has been committed, the mailbox will be released.
1116       *texture_mailbox = TextureMailbox();
1117       return true;
1118     }
1119
1120     *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1121     *release_callback = SingleReleaseCallback::Create(
1122         base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1123                    base::Unretained(this)));
1124     return true;
1125   }
1126
1127   void MailboxReleased(uint32 sync_point, bool lost_resource) {
1128     // Source frame number during callback is the same as the source frame
1129     // on which it was released.
1130     EXPECT_EQ(1, 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->SetIsDrawable(true);
1138
1139     texture_layer_ = TextureLayer::CreateForMailbox(this);
1140     texture_layer_->SetBounds(gfx::Size(10, 10));
1141     texture_layer_->SetIsDrawable(true);
1142     root->AddChild(texture_layer_);
1143
1144     layer_tree_host()->SetRootLayer(root);
1145     LayerTreeTest::SetupTree();
1146   }
1147
1148   virtual void BeginTest() OVERRIDE {
1149     PostSetNeedsCommitToMainThread();
1150   }
1151
1152   virtual void DidCommitAndDrawFrame() OVERRIDE {
1153     switch (layer_tree_host()->source_frame_number()) {
1154       case 1:
1155         EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting());
1156         // Invalidate the texture layer to clear the mailbox before
1157         // ending the test.
1158         texture_layer_->SetNeedsDisplay();
1159         break;
1160       case 2:
1161         break;
1162       default:
1163         NOTREACHED();
1164         break;
1165     }
1166   }
1167
1168   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1169                                    bool result) OVERRIDE {
1170     ASSERT_TRUE(result);
1171     DelegatedFrameData* delegated_frame_data =
1172         output_surface()->last_sent_frame().delegated_frame_data.get();
1173     if (!delegated_frame_data)
1174       return;
1175
1176     // Return all resources immediately.
1177     TransferableResourceArray resources_to_return =
1178         output_surface()->resources_held_by_parent();
1179
1180     CompositorFrameAck ack;
1181     for (size_t i = 0; i < resources_to_return.size(); ++i)
1182       output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1183     host_impl->ReclaimResources(&ack);
1184   }
1185
1186   virtual void AfterTest() OVERRIDE {}
1187
1188  private:
1189   scoped_refptr<TextureLayer> texture_layer_;
1190 };
1191
1192 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1193
1194 // Checks that changing a mailbox in the client for a TextureLayer that's
1195 // invisible correctly works and uses the new mailbox as soon as the layer
1196 // becomes visible (and returns the old one).
1197 class TextureLayerChangeInvisibleMailboxTest
1198     : public LayerTreeTest,
1199       public TextureLayerClient {
1200  public:
1201   TextureLayerChangeInvisibleMailboxTest()
1202       : mailbox_changed_(true),
1203         mailbox_returned_(0),
1204         prepare_called_(0),
1205         commit_count_(0) {
1206     mailbox_ = MakeMailbox('1');
1207   }
1208
1209   // TextureLayerClient implementation.
1210   virtual bool PrepareTextureMailbox(
1211       TextureMailbox* mailbox,
1212       scoped_ptr<SingleReleaseCallback>* release_callback,
1213       bool use_shared_memory) OVERRIDE {
1214     ++prepare_called_;
1215     if (!mailbox_changed_)
1216       return false;
1217     *mailbox = mailbox_;
1218     *release_callback = SingleReleaseCallback::Create(
1219         base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1220                    base::Unretained(this)));
1221     return true;
1222   }
1223
1224   TextureMailbox MakeMailbox(char name) {
1225     return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0);
1226   }
1227
1228   void MailboxReleased(uint32 sync_point, bool lost_resource) {
1229     ++mailbox_returned_;
1230   }
1231
1232   virtual void SetupTree() OVERRIDE {
1233     scoped_refptr<Layer> root = Layer::Create();
1234     root->SetBounds(gfx::Size(10, 10));
1235     root->SetIsDrawable(true);
1236
1237     solid_layer_ = SolidColorLayer::Create();
1238     solid_layer_->SetBounds(gfx::Size(10, 10));
1239     solid_layer_->SetIsDrawable(true);
1240     solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1241     root->AddChild(solid_layer_);
1242
1243     parent_layer_ = Layer::Create();
1244     parent_layer_->SetBounds(gfx::Size(10, 10));
1245     parent_layer_->SetIsDrawable(true);
1246     root->AddChild(parent_layer_);
1247
1248     texture_layer_ = TextureLayer::CreateForMailbox(this);
1249     texture_layer_->SetBounds(gfx::Size(10, 10));
1250     texture_layer_->SetIsDrawable(true);
1251     parent_layer_->AddChild(texture_layer_);
1252
1253     layer_tree_host()->SetRootLayer(root);
1254     LayerTreeTest::SetupTree();
1255   }
1256
1257   virtual void BeginTest() OVERRIDE {
1258     PostSetNeedsCommitToMainThread();
1259   }
1260
1261   virtual void DidCommitAndDrawFrame() OVERRIDE {
1262     ++commit_count_;
1263     switch (commit_count_) {
1264       case 1:
1265         // We should have updated the layer, committing the texture.
1266         EXPECT_EQ(1, prepare_called_);
1267         // Make layer invisible.
1268         parent_layer_->SetOpacity(0.f);
1269         break;
1270       case 2:
1271         // Layer shouldn't have been updated.
1272         EXPECT_EQ(1, prepare_called_);
1273         // Change the texture.
1274         mailbox_ = MakeMailbox('2');
1275         mailbox_changed_ = true;
1276         texture_layer_->SetNeedsDisplay();
1277         // Force a change to make sure we draw a frame.
1278         solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1279         break;
1280       case 3:
1281         // Layer shouldn't have been updated.
1282         EXPECT_EQ(1, prepare_called_);
1283         // So the old mailbox isn't returned yet.
1284         EXPECT_EQ(0, mailbox_returned_);
1285         // Make layer visible again.
1286         parent_layer_->SetOpacity(1.f);
1287         break;
1288       case 4:
1289         // Layer should have been updated.
1290         EXPECT_EQ(2, prepare_called_);
1291         // So the old mailbox should have been returned already.
1292         EXPECT_EQ(1, mailbox_returned_);
1293         texture_layer_->ClearClient();
1294         break;
1295       case 5:
1296         EXPECT_EQ(2, mailbox_returned_);
1297         EndTest();
1298         break;
1299       default:
1300         NOTREACHED();
1301         break;
1302     }
1303   }
1304
1305   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1306                                    bool result) OVERRIDE {
1307     ASSERT_TRUE(result);
1308     DelegatedFrameData* delegated_frame_data =
1309         output_surface()->last_sent_frame().delegated_frame_data.get();
1310     if (!delegated_frame_data)
1311       return;
1312
1313     // Return all resources immediately.
1314     TransferableResourceArray resources_to_return =
1315         output_surface()->resources_held_by_parent();
1316
1317     CompositorFrameAck ack;
1318     for (size_t i = 0; i < resources_to_return.size(); ++i)
1319       output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1320     host_impl->ReclaimResources(&ack);
1321   }
1322
1323   virtual void AfterTest() OVERRIDE {}
1324
1325  private:
1326   scoped_refptr<SolidColorLayer> solid_layer_;
1327   scoped_refptr<Layer> parent_layer_;
1328   scoped_refptr<TextureLayer> texture_layer_;
1329
1330   // Used on the main thread.
1331   bool mailbox_changed_;
1332   TextureMailbox mailbox_;
1333   int mailbox_returned_;
1334   int prepare_called_;
1335   int commit_count_;
1336 };
1337
1338 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1339
1340 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1341 // the mailbox back to TextureLayerClient.
1342 class TextureLayerReleaseResourcesBase
1343     : public LayerTreeTest,
1344       public TextureLayerClient {
1345  public:
1346   // TextureLayerClient implementation.
1347   virtual bool PrepareTextureMailbox(
1348       TextureMailbox* mailbox,
1349       scoped_ptr<SingleReleaseCallback>* release_callback,
1350       bool use_shared_memory) OVERRIDE {
1351     *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1352     *release_callback = SingleReleaseCallback::Create(
1353         base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1354                    base::Unretained(this)));
1355     return true;
1356   }
1357
1358   void MailboxReleased(unsigned sync_point, bool lost_resource) {
1359     mailbox_released_ = true;
1360   }
1361
1362   virtual void SetupTree() OVERRIDE {
1363     LayerTreeTest::SetupTree();
1364
1365     scoped_refptr<TextureLayer> texture_layer =
1366         TextureLayer::CreateForMailbox(this);
1367     texture_layer->SetBounds(gfx::Size(10, 10));
1368     texture_layer->SetIsDrawable(true);
1369
1370     layer_tree_host()->root_layer()->AddChild(texture_layer);
1371   }
1372
1373   virtual void BeginTest() OVERRIDE {
1374     mailbox_released_ = false;
1375     PostSetNeedsCommitToMainThread();
1376   }
1377
1378   virtual void DidCommitAndDrawFrame() OVERRIDE {
1379     EndTest();
1380   }
1381
1382   virtual void AfterTest() OVERRIDE {
1383     EXPECT_TRUE(mailbox_released_);
1384   }
1385
1386  private:
1387   bool mailbox_released_;
1388 };
1389
1390 class TextureLayerReleaseResourcesAfterCommit
1391     : public TextureLayerReleaseResourcesBase {
1392  public:
1393   virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1394     LayerTreeImpl* tree = NULL;
1395     if (host_impl->settings().impl_side_painting)
1396       tree = host_impl->pending_tree();
1397     else
1398       tree = host_impl->active_tree();
1399     tree->root_layer()->children()[0]->ReleaseResources();
1400   }
1401 };
1402
1403 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1404
1405 class TextureLayerReleaseResourcesAfterActivate
1406     : public TextureLayerReleaseResourcesBase {
1407  public:
1408   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1409     host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
1410   }
1411 };
1412
1413 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
1414
1415 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
1416  public:
1417   void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1418     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1419     EXPECT_FALSE(lost_resource);
1420     ++callback_count_;
1421     EndTest();
1422   }
1423
1424   void SetMailbox(char mailbox_char) {
1425     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1426     scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1427         base::Bind(
1428             &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
1429             base::Unretained(this)));
1430     layer_->SetTextureMailbox(
1431         TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1432         callback.Pass());
1433   }
1434
1435   virtual void SetupTree() OVERRIDE {
1436     gfx::Size bounds(100, 100);
1437     root_ = Layer::Create();
1438     root_->SetBounds(bounds);
1439
1440     layer_ = TextureLayer::CreateForMailbox(NULL);
1441     layer_->SetIsDrawable(true);
1442     layer_->SetBounds(bounds);
1443
1444     root_->AddChild(layer_);
1445     layer_tree_host()->SetRootLayer(root_);
1446     layer_tree_host()->SetViewportSize(bounds);
1447   }
1448
1449   virtual void BeginTest() OVERRIDE {
1450     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1451
1452     callback_count_ = 0;
1453
1454     // Set the mailbox on the main thread.
1455     SetMailbox('1');
1456     EXPECT_EQ(0, callback_count_);
1457
1458     PostSetNeedsCommitToMainThread();
1459   }
1460
1461   virtual void DidCommitAndDrawFrame() OVERRIDE {
1462     switch (layer_tree_host()->source_frame_number()) {
1463       case 1:
1464         // Delete the TextureLayer on the main thread while the mailbox is in
1465         // the impl tree.
1466         layer_->RemoveFromParent();
1467         layer_ = NULL;
1468         break;
1469     }
1470   }
1471
1472   virtual void AfterTest() OVERRIDE {
1473     EXPECT_EQ(1, callback_count_);
1474   }
1475
1476  private:
1477   base::ThreadChecker main_thread_;
1478   int callback_count_;
1479   scoped_refptr<Layer> root_;
1480   scoped_refptr<TextureLayer> layer_;
1481 };
1482
1483 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1484     TextureLayerWithMailboxMainThreadDeleted);
1485
1486 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
1487  public:
1488   void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1489     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1490     EXPECT_FALSE(lost_resource);
1491     ++callback_count_;
1492     EndTest();
1493   }
1494
1495   void SetMailbox(char mailbox_char) {
1496     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1497     scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1498         base::Bind(
1499             &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
1500             base::Unretained(this)));
1501     layer_->SetTextureMailbox(
1502         TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1503         callback.Pass());
1504   }
1505
1506   virtual void SetupTree() OVERRIDE {
1507     gfx::Size bounds(100, 100);
1508     root_ = Layer::Create();
1509     root_->SetBounds(bounds);
1510
1511     layer_ = TextureLayer::CreateForMailbox(NULL);
1512     layer_->SetIsDrawable(true);
1513     layer_->SetBounds(bounds);
1514
1515     root_->AddChild(layer_);
1516     layer_tree_host()->SetRootLayer(root_);
1517     layer_tree_host()->SetViewportSize(bounds);
1518   }
1519
1520   virtual void BeginTest() OVERRIDE {
1521     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1522
1523     callback_count_ = 0;
1524
1525     // Set the mailbox on the main thread.
1526     SetMailbox('1');
1527     EXPECT_EQ(0, callback_count_);
1528
1529     PostSetNeedsCommitToMainThread();
1530   }
1531
1532   virtual void DidCommitAndDrawFrame() OVERRIDE {
1533     switch (layer_tree_host()->source_frame_number()) {
1534       case 1:
1535         // Remove the TextureLayer on the main thread while the mailbox is in
1536         // the impl tree, but don't delete the TextureLayer until after the impl
1537         // tree side is deleted.
1538         layer_->RemoveFromParent();
1539         break;
1540       case 2:
1541         layer_ = NULL;
1542         break;
1543     }
1544   }
1545
1546   virtual void AfterTest() OVERRIDE {
1547     EXPECT_EQ(1, callback_count_);
1548   }
1549
1550  private:
1551   base::ThreadChecker main_thread_;
1552   int callback_count_;
1553   scoped_refptr<Layer> root_;
1554   scoped_refptr<TextureLayer> layer_;
1555 };
1556
1557 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1558     TextureLayerWithMailboxImplThreadDeleted);
1559
1560 }  // namespace
1561 }  // namespace cc