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