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
36using ::testing::Mock;
37using ::testing::_;
38using ::testing::AtLeast;
39using ::testing::AnyNumber;
40using ::testing::InvokeWithoutArgs;
41
42namespace cc {
43namespace {
44
45gpu::Mailbox MailboxFromChar(char value) {
46  gpu::Mailbox mailbox;
47  memset(mailbox.name, value, sizeof(mailbox.name));
48  return mailbox;
49}
50
51class MockLayerTreeHost : public LayerTreeHost {
52 public:
53  explicit MockLayerTreeHost(FakeLayerTreeHostClient* client)
54      : LayerTreeHost(client, NULL, LayerTreeSettings()) {
55    InitializeSingleThreaded(client);
56  }
57
58  MOCK_METHOD0(SetNeedsCommit, void());
59  MOCK_METHOD0(SetNeedsUpdateLayers, void());
60  MOCK_METHOD0(StartRateLimiter, void());
61  MOCK_METHOD0(StopRateLimiter, void());
62};
63
64class 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
95class 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
107struct 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
146class 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
176TEST_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
191TEST_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
218TEST_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
268class TestMailboxHolder : public TextureLayer::TextureMailboxHolder {
269 public:
270  using TextureLayer::TextureMailboxHolder::Create;
271
272 protected:
273  virtual ~TestMailboxHolder() {}
274};
275
276class 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
290TEST_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
351TEST_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
375class 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
422TEST_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
477TEST_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
533TEST_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
589TEST_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
668class 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
798SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
799    TextureLayerImplWithMailboxThreadedCallback);
800
801
802class 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 2: {
860        // The activate for the 2nd mailbox should have happened before now.
861        EXPECT_EQ(2, activate_count_);
862        break;
863      }
864      case 3: {
865        // The activate to remove the layer should have happened before now.
866        EXPECT_EQ(3, activate_count_);
867        break;
868      }
869    }
870  }
871
872
873  virtual void AfterTest() OVERRIDE {}
874
875  int activate_count_;
876  scoped_refptr<Layer> root_;
877  scoped_refptr<TextureLayer> layer_;
878};
879
880SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
881    TextureLayerMailboxIsActivatedDuringCommit);
882
883class TextureLayerImplWithMailboxTest : public TextureLayerTest {
884 protected:
885  TextureLayerImplWithMailboxTest()
886      : fake_client_(
887          FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
888
889  virtual void SetUp() {
890    TextureLayerTest::SetUp();
891    layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
892    EXPECT_TRUE(host_impl_.InitializeRenderer(
893        FakeOutputSurface::Create3d().PassAs<OutputSurface>()));
894  }
895
896  bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
897    bool will_draw = layer->WillDraw(
898        mode, host_impl_.active_tree()->resource_provider());
899    if (will_draw)
900      layer->DidDraw(host_impl_.active_tree()->resource_provider());
901    return will_draw;
902  }
903
904  CommonMailboxObjects test_data_;
905  FakeLayerTreeHostClient fake_client_;
906};
907
908// Test conditions for results of TextureLayerImpl::WillDraw under
909// different configurations of different mailbox, texture_id, and draw_mode.
910TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
911  EXPECT_CALL(test_data_.mock_callback_,
912              Release(test_data_.mailbox_name1_,
913                      test_data_.sync_point1_,
914                      false))
915      .Times(AnyNumber());
916  EXPECT_CALL(test_data_.mock_callback_,
917              Release2(test_data_.shared_memory_.get(), 0, false))
918      .Times(AnyNumber());
919  // Hardware mode.
920  {
921    scoped_ptr<TextureLayerImpl> impl_layer =
922        TextureLayerImpl::Create(host_impl_.active_tree(), 1);
923    impl_layer->SetTextureMailbox(
924        test_data_.mailbox1_,
925        SingleReleaseCallback::Create(test_data_.release_mailbox1_));
926    EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
927  }
928
929  {
930    scoped_ptr<TextureLayerImpl> impl_layer =
931        TextureLayerImpl::Create(host_impl_.active_tree(), 1);
932    impl_layer->SetTextureMailbox(TextureMailbox(),
933                                  scoped_ptr<SingleReleaseCallback>());
934    EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
935  }
936
937  {
938    // Software resource.
939    scoped_ptr<TextureLayerImpl> impl_layer =
940        TextureLayerImpl::Create(host_impl_.active_tree(), 1);
941    impl_layer->SetTextureMailbox(
942        test_data_.mailbox3_,
943        SingleReleaseCallback::Create(test_data_.release_mailbox3_));
944    EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
945  }
946
947  // Software mode.
948  {
949    scoped_ptr<TextureLayerImpl> impl_layer =
950        TextureLayerImpl::Create(host_impl_.active_tree(), 1);
951    impl_layer->SetTextureMailbox(
952        test_data_.mailbox1_,
953        SingleReleaseCallback::Create(test_data_.release_mailbox1_));
954    EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
955  }
956
957  {
958    scoped_ptr<TextureLayerImpl> impl_layer =
959        TextureLayerImpl::Create(host_impl_.active_tree(), 1);
960    impl_layer->SetTextureMailbox(TextureMailbox(),
961                                  scoped_ptr<SingleReleaseCallback>());
962    EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
963  }
964
965  {
966    // Software resource.
967    scoped_ptr<TextureLayerImpl> impl_layer =
968        TextureLayerImpl::Create(host_impl_.active_tree(), 1);
969    impl_layer->SetTextureMailbox(
970        test_data_.mailbox3_,
971        SingleReleaseCallback::Create(test_data_.release_mailbox3_));
972    EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
973  }
974
975  // Resourceless software mode.
976  {
977    scoped_ptr<TextureLayerImpl> impl_layer =
978        TextureLayerImpl::Create(host_impl_.active_tree(), 1);
979    impl_layer->SetTextureMailbox(
980        test_data_.mailbox1_,
981        SingleReleaseCallback::Create(test_data_.release_mailbox1_));
982    EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
983  }
984}
985
986TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
987  host_impl_.CreatePendingTree();
988  scoped_ptr<TextureLayerImpl> pending_layer;
989  pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1);
990  ASSERT_TRUE(pending_layer);
991
992  scoped_ptr<LayerImpl> active_layer(
993      pending_layer->CreateLayerImpl(host_impl_.active_tree()));
994  ASSERT_TRUE(active_layer);
995
996  pending_layer->SetTextureMailbox(
997      test_data_.mailbox1_,
998      SingleReleaseCallback::Create(test_data_.release_mailbox1_));
999
1000  // Test multiple commits without an activation.
1001  EXPECT_CALL(test_data_.mock_callback_,
1002              Release(test_data_.mailbox_name1_,
1003                      test_data_.sync_point1_,
1004                      false))
1005      .Times(1);
1006  pending_layer->SetTextureMailbox(
1007      test_data_.mailbox2_,
1008      SingleReleaseCallback::Create(test_data_.release_mailbox2_));
1009  Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1010
1011  // Test callback after activation.
1012  pending_layer->PushPropertiesTo(active_layer.get());
1013  active_layer->DidBecomeActive();
1014
1015  EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1016  pending_layer->SetTextureMailbox(
1017      test_data_.mailbox1_,
1018      SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1019  Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1020
1021  EXPECT_CALL(test_data_.mock_callback_,
1022              Release(test_data_.mailbox_name2_, _, false))
1023      .Times(1);
1024  pending_layer->PushPropertiesTo(active_layer.get());
1025  active_layer->DidBecomeActive();
1026  Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1027
1028  // Test resetting the mailbox.
1029  EXPECT_CALL(test_data_.mock_callback_,
1030              Release(test_data_.mailbox_name1_, _, false))
1031      .Times(1);
1032  pending_layer->SetTextureMailbox(TextureMailbox(),
1033                                   scoped_ptr<SingleReleaseCallback>());
1034  pending_layer->PushPropertiesTo(active_layer.get());
1035  active_layer->DidBecomeActive();
1036  Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1037
1038  // Test destructor.
1039  EXPECT_CALL(test_data_.mock_callback_,
1040              Release(test_data_.mailbox_name1_,
1041                      test_data_.sync_point1_,
1042                      false))
1043      .Times(1);
1044  pending_layer->SetTextureMailbox(
1045      test_data_.mailbox1_,
1046      SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1047}
1048
1049TEST_F(TextureLayerImplWithMailboxTest,
1050       TestDestructorCallbackOnCreatedResource) {
1051  scoped_ptr<TextureLayerImpl> impl_layer;
1052  impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1);
1053  ASSERT_TRUE(impl_layer);
1054
1055  EXPECT_CALL(test_data_.mock_callback_,
1056              Release(test_data_.mailbox_name1_, _, false))
1057      .Times(1);
1058  impl_layer->SetTextureMailbox(
1059      test_data_.mailbox1_,
1060      SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1061  impl_layer->DidBecomeActive();
1062  EXPECT_TRUE(impl_layer->WillDraw(
1063      DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1064  impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1065  impl_layer->SetTextureMailbox(TextureMailbox(),
1066                                scoped_ptr<SingleReleaseCallback>());
1067}
1068
1069TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1070  ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1071  ResourceProvider::ResourceId id =
1072      provider->CreateResourceFromTextureMailbox(
1073          test_data_.mailbox1_,
1074          SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1075  provider->AllocateForTesting(id);
1076
1077  // Transfer some resources to the parent.
1078  ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1079  resource_ids_to_transfer.push_back(id);
1080  TransferableResourceArray list;
1081  provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1082  EXPECT_TRUE(provider->InUseByConsumer(id));
1083  EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1084  provider->DeleteResource(id);
1085  Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1086  EXPECT_CALL(test_data_.mock_callback_,
1087              Release(test_data_.mailbox_name1_, _, false))
1088      .Times(1);
1089  ReturnedResourceArray returned;
1090  TransferableResource::ReturnResources(list, &returned);
1091  provider->ReceiveReturnsFromParent(returned);
1092}
1093
1094// Checks that TextureLayer::Update does not cause an extra commit when setting
1095// the texture mailbox.
1096class TextureLayerNoExtraCommitForMailboxTest
1097    : public LayerTreeTest,
1098      public TextureLayerClient {
1099 public:
1100  // TextureLayerClient implementation.
1101  virtual bool PrepareTextureMailbox(
1102      TextureMailbox* texture_mailbox,
1103      scoped_ptr<SingleReleaseCallback>* release_callback,
1104      bool use_shared_memory) OVERRIDE {
1105    if (layer_tree_host()->source_frame_number() == 1) {
1106      // Once this has been committed, the mailbox will be released.
1107      *texture_mailbox = TextureMailbox();
1108      return true;
1109    }
1110
1111    *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1112    *release_callback = SingleReleaseCallback::Create(
1113        base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1114                   base::Unretained(this)));
1115    return true;
1116  }
1117
1118  void MailboxReleased(uint32 sync_point, bool lost_resource) {
1119    // Source frame number during callback is the same as the source frame
1120    // on which it was released.
1121    EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1122    EndTest();
1123  }
1124
1125  virtual void SetupTree() OVERRIDE {
1126    scoped_refptr<Layer> root = Layer::Create();
1127    root->SetBounds(gfx::Size(10, 10));
1128    root->SetIsDrawable(true);
1129
1130    texture_layer_ = TextureLayer::CreateForMailbox(this);
1131    texture_layer_->SetBounds(gfx::Size(10, 10));
1132    texture_layer_->SetIsDrawable(true);
1133    root->AddChild(texture_layer_);
1134
1135    layer_tree_host()->SetRootLayer(root);
1136    LayerTreeTest::SetupTree();
1137  }
1138
1139  virtual void BeginTest() OVERRIDE {
1140    PostSetNeedsCommitToMainThread();
1141  }
1142
1143  virtual void DidCommitAndDrawFrame() OVERRIDE {
1144    switch (layer_tree_host()->source_frame_number()) {
1145      case 1:
1146        EXPECT_FALSE(proxy()->CommitPendingForTesting());
1147        // Invalidate the texture layer to clear the mailbox before
1148        // ending the test.
1149        texture_layer_->SetNeedsDisplay();
1150        break;
1151      case 2:
1152        break;
1153      default:
1154        NOTREACHED();
1155        break;
1156    }
1157  }
1158
1159  virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1160                                   bool result) OVERRIDE {
1161    ASSERT_TRUE(result);
1162    DelegatedFrameData* delegated_frame_data =
1163        output_surface()->last_sent_frame().delegated_frame_data.get();
1164    if (!delegated_frame_data)
1165      return;
1166
1167    // Return all resources immediately.
1168    TransferableResourceArray resources_to_return =
1169        output_surface()->resources_held_by_parent();
1170
1171    CompositorFrameAck ack;
1172    for (size_t i = 0; i < resources_to_return.size(); ++i)
1173      output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1174    host_impl->ReclaimResources(&ack);
1175  }
1176
1177  virtual void AfterTest() OVERRIDE {}
1178
1179 private:
1180  scoped_refptr<TextureLayer> texture_layer_;
1181};
1182
1183SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1184
1185// Checks that changing a mailbox in the client for a TextureLayer that's
1186// invisible correctly works and uses the new mailbox as soon as the layer
1187// becomes visible (and returns the old one).
1188class TextureLayerChangeInvisibleMailboxTest
1189    : public LayerTreeTest,
1190      public TextureLayerClient {
1191 public:
1192  TextureLayerChangeInvisibleMailboxTest()
1193      : mailbox_changed_(true),
1194        mailbox_returned_(0),
1195        prepare_called_(0),
1196        commit_count_(0) {
1197    mailbox_ = MakeMailbox('1');
1198  }
1199
1200  // TextureLayerClient implementation.
1201  virtual bool PrepareTextureMailbox(
1202      TextureMailbox* mailbox,
1203      scoped_ptr<SingleReleaseCallback>* release_callback,
1204      bool use_shared_memory) OVERRIDE {
1205    ++prepare_called_;
1206    if (!mailbox_changed_)
1207      return false;
1208    *mailbox = mailbox_;
1209    *release_callback = SingleReleaseCallback::Create(
1210        base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1211                   base::Unretained(this)));
1212    return true;
1213  }
1214
1215  TextureMailbox MakeMailbox(char name) {
1216    return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0);
1217  }
1218
1219  void MailboxReleased(uint32 sync_point, bool lost_resource) {
1220    ++mailbox_returned_;
1221  }
1222
1223  virtual void SetupTree() OVERRIDE {
1224    scoped_refptr<Layer> root = Layer::Create();
1225    root->SetBounds(gfx::Size(10, 10));
1226    root->SetIsDrawable(true);
1227
1228    solid_layer_ = SolidColorLayer::Create();
1229    solid_layer_->SetBounds(gfx::Size(10, 10));
1230    solid_layer_->SetIsDrawable(true);
1231    solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1232    root->AddChild(solid_layer_);
1233
1234    parent_layer_ = Layer::Create();
1235    parent_layer_->SetBounds(gfx::Size(10, 10));
1236    parent_layer_->SetIsDrawable(true);
1237    root->AddChild(parent_layer_);
1238
1239    texture_layer_ = TextureLayer::CreateForMailbox(this);
1240    texture_layer_->SetBounds(gfx::Size(10, 10));
1241    texture_layer_->SetIsDrawable(true);
1242    parent_layer_->AddChild(texture_layer_);
1243
1244    layer_tree_host()->SetRootLayer(root);
1245    LayerTreeTest::SetupTree();
1246  }
1247
1248  virtual void BeginTest() OVERRIDE {
1249    PostSetNeedsCommitToMainThread();
1250  }
1251
1252  virtual void DidCommitAndDrawFrame() OVERRIDE {
1253    ++commit_count_;
1254    switch (commit_count_) {
1255      case 1:
1256        // We should have updated the layer, committing the texture.
1257        EXPECT_EQ(1, prepare_called_);
1258        // Make layer invisible.
1259        parent_layer_->SetOpacity(0.f);
1260        break;
1261      case 2:
1262        // Layer shouldn't have been updated.
1263        EXPECT_EQ(1, prepare_called_);
1264        // Change the texture.
1265        mailbox_ = MakeMailbox('2');
1266        mailbox_changed_ = true;
1267        texture_layer_->SetNeedsDisplay();
1268        // Force a change to make sure we draw a frame.
1269        solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1270        break;
1271      case 3:
1272        // Layer shouldn't have been updated.
1273        EXPECT_EQ(1, prepare_called_);
1274        // So the old mailbox isn't returned yet.
1275        EXPECT_EQ(0, mailbox_returned_);
1276        // Make layer visible again.
1277        parent_layer_->SetOpacity(1.f);
1278        break;
1279      case 4:
1280        // Layer should have been updated.
1281        EXPECT_EQ(2, prepare_called_);
1282        // So the old mailbox should have been returned already.
1283        EXPECT_EQ(1, mailbox_returned_);
1284        texture_layer_->ClearClient();
1285        break;
1286      case 5:
1287        EXPECT_EQ(2, mailbox_returned_);
1288        EndTest();
1289        break;
1290      default:
1291        NOTREACHED();
1292        break;
1293    }
1294  }
1295
1296  virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1297                                   bool result) OVERRIDE {
1298    ASSERT_TRUE(result);
1299    DelegatedFrameData* delegated_frame_data =
1300        output_surface()->last_sent_frame().delegated_frame_data.get();
1301    if (!delegated_frame_data)
1302      return;
1303
1304    // Return all resources immediately.
1305    TransferableResourceArray resources_to_return =
1306        output_surface()->resources_held_by_parent();
1307
1308    CompositorFrameAck ack;
1309    for (size_t i = 0; i < resources_to_return.size(); ++i)
1310      output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1311    host_impl->ReclaimResources(&ack);
1312  }
1313
1314  virtual void AfterTest() OVERRIDE {}
1315
1316 private:
1317  scoped_refptr<SolidColorLayer> solid_layer_;
1318  scoped_refptr<Layer> parent_layer_;
1319  scoped_refptr<TextureLayer> texture_layer_;
1320
1321  // Used on the main thread.
1322  bool mailbox_changed_;
1323  TextureMailbox mailbox_;
1324  int mailbox_returned_;
1325  int prepare_called_;
1326  int commit_count_;
1327};
1328
1329SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1330
1331// Test that TextureLayerImpl::ReleaseResources can be called which releases
1332// the mailbox back to TextureLayerClient.
1333class TextureLayerReleaseResourcesBase
1334    : public LayerTreeTest,
1335      public TextureLayerClient {
1336 public:
1337  // TextureLayerClient implementation.
1338  virtual bool PrepareTextureMailbox(
1339      TextureMailbox* mailbox,
1340      scoped_ptr<SingleReleaseCallback>* release_callback,
1341      bool use_shared_memory) OVERRIDE {
1342    *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1343    *release_callback = SingleReleaseCallback::Create(
1344        base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1345                   base::Unretained(this)));
1346    return true;
1347  }
1348
1349  void MailboxReleased(unsigned sync_point, bool lost_resource) {
1350    mailbox_released_ = true;
1351  }
1352
1353  virtual void SetupTree() OVERRIDE {
1354    LayerTreeTest::SetupTree();
1355
1356    scoped_refptr<TextureLayer> texture_layer =
1357        TextureLayer::CreateForMailbox(this);
1358    texture_layer->SetBounds(gfx::Size(10, 10));
1359    texture_layer->SetIsDrawable(true);
1360
1361    layer_tree_host()->root_layer()->AddChild(texture_layer);
1362  }
1363
1364  virtual void BeginTest() OVERRIDE {
1365    mailbox_released_ = false;
1366    PostSetNeedsCommitToMainThread();
1367  }
1368
1369  virtual void DidCommitAndDrawFrame() OVERRIDE {
1370    EndTest();
1371  }
1372
1373  virtual void AfterTest() OVERRIDE {
1374    EXPECT_TRUE(mailbox_released_);
1375  }
1376
1377 private:
1378  bool mailbox_released_;
1379};
1380
1381class TextureLayerReleaseResourcesAfterCommit
1382    : public TextureLayerReleaseResourcesBase {
1383 public:
1384  virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1385    LayerTreeImpl* tree = NULL;
1386    if (host_impl->settings().impl_side_painting)
1387      tree = host_impl->pending_tree();
1388    else
1389      tree = host_impl->active_tree();
1390    tree->root_layer()->children()[0]->ReleaseResources();
1391  }
1392};
1393
1394SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1395
1396class TextureLayerReleaseResourcesAfterActivate
1397    : public TextureLayerReleaseResourcesBase {
1398 public:
1399  virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1400    host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
1401  }
1402};
1403
1404SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
1405
1406class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
1407 public:
1408  void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1409    EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1410    EXPECT_FALSE(lost_resource);
1411    ++callback_count_;
1412    EndTest();
1413  }
1414
1415  void SetMailbox(char mailbox_char) {
1416    EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1417    scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1418        base::Bind(
1419            &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
1420            base::Unretained(this)));
1421    layer_->SetTextureMailbox(
1422        TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1423        callback.Pass());
1424  }
1425
1426  virtual void SetupTree() OVERRIDE {
1427    gfx::Size bounds(100, 100);
1428    root_ = Layer::Create();
1429    root_->SetBounds(bounds);
1430
1431    layer_ = TextureLayer::CreateForMailbox(NULL);
1432    layer_->SetIsDrawable(true);
1433    layer_->SetBounds(bounds);
1434
1435    root_->AddChild(layer_);
1436    layer_tree_host()->SetRootLayer(root_);
1437    layer_tree_host()->SetViewportSize(bounds);
1438  }
1439
1440  virtual void BeginTest() OVERRIDE {
1441    EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1442
1443    callback_count_ = 0;
1444
1445    // Set the mailbox on the main thread.
1446    SetMailbox('1');
1447    EXPECT_EQ(0, callback_count_);
1448
1449    PostSetNeedsCommitToMainThread();
1450  }
1451
1452  virtual void DidCommitAndDrawFrame() OVERRIDE {
1453    switch (layer_tree_host()->source_frame_number()) {
1454      case 1:
1455        // Delete the TextureLayer on the main thread while the mailbox is in
1456        // the impl tree.
1457        layer_->RemoveFromParent();
1458        layer_ = NULL;
1459        break;
1460    }
1461  }
1462
1463  virtual void AfterTest() OVERRIDE {
1464    EXPECT_EQ(1, callback_count_);
1465  }
1466
1467 private:
1468  base::ThreadChecker main_thread_;
1469  int callback_count_;
1470  scoped_refptr<Layer> root_;
1471  scoped_refptr<TextureLayer> layer_;
1472};
1473
1474SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1475    TextureLayerWithMailboxMainThreadDeleted);
1476
1477class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
1478 public:
1479  void ReleaseCallback(uint32 sync_point, bool lost_resource) {
1480    EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1481    EXPECT_FALSE(lost_resource);
1482    ++callback_count_;
1483    EndTest();
1484  }
1485
1486  void SetMailbox(char mailbox_char) {
1487    EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1488    scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1489        base::Bind(
1490            &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
1491            base::Unretained(this)));
1492    layer_->SetTextureMailbox(
1493        TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1494        callback.Pass());
1495  }
1496
1497  virtual void SetupTree() OVERRIDE {
1498    gfx::Size bounds(100, 100);
1499    root_ = Layer::Create();
1500    root_->SetBounds(bounds);
1501
1502    layer_ = TextureLayer::CreateForMailbox(NULL);
1503    layer_->SetIsDrawable(true);
1504    layer_->SetBounds(bounds);
1505
1506    root_->AddChild(layer_);
1507    layer_tree_host()->SetRootLayer(root_);
1508    layer_tree_host()->SetViewportSize(bounds);
1509  }
1510
1511  virtual void BeginTest() OVERRIDE {
1512    EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1513
1514    callback_count_ = 0;
1515
1516    // Set the mailbox on the main thread.
1517    SetMailbox('1');
1518    EXPECT_EQ(0, callback_count_);
1519
1520    PostSetNeedsCommitToMainThread();
1521  }
1522
1523  virtual void DidCommitAndDrawFrame() OVERRIDE {
1524    switch (layer_tree_host()->source_frame_number()) {
1525      case 1:
1526        // Remove the TextureLayer on the main thread while the mailbox is in
1527        // the impl tree, but don't delete the TextureLayer until after the impl
1528        // tree side is deleted.
1529        layer_->RemoveFromParent();
1530        break;
1531      case 2:
1532        layer_ = NULL;
1533        break;
1534    }
1535  }
1536
1537  virtual void AfterTest() OVERRIDE {
1538    EXPECT_EQ(1, callback_count_);
1539  }
1540
1541 private:
1542  base::ThreadChecker main_thread_;
1543  int callback_count_;
1544  scoped_refptr<Layer> root_;
1545  scoped_refptr<TextureLayer> layer_;
1546};
1547
1548SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1549    TextureLayerWithMailboxImplThreadDeleted);
1550
1551}  // namespace
1552}  // namespace cc
1553