Home | History | Annotate | Download | only in layers
      1 // Copyright 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "cc/layers/texture_layer.h"
      6 
      7 #include <algorithm>
      8 #include <string>
      9 
     10 #include "base/bind.h"
     11 #include "base/callback.h"
     12 #include "base/synchronization/waitable_event.h"
     13 #include "base/threading/thread.h"
     14 #include "base/time/time.h"
     15 #include "cc/layers/solid_color_layer.h"
     16 #include "cc/layers/texture_layer_client.h"
     17 #include "cc/layers/texture_layer_impl.h"
     18 #include "cc/output/compositor_frame_ack.h"
     19 #include "cc/output/context_provider.h"
     20 #include "cc/resources/returned_resource.h"
     21 #include "cc/test/fake_impl_proxy.h"
     22 #include "cc/test/fake_layer_tree_host_client.h"
     23 #include "cc/test/fake_layer_tree_host_impl.h"
     24 #include "cc/test/fake_output_surface.h"
     25 #include "cc/test/layer_test_common.h"
     26 #include "cc/test/layer_tree_test.h"
     27 #include "cc/test/test_web_graphics_context_3d.h"
     28 #include "cc/trees/blocking_task_runner.h"
     29 #include "cc/trees/layer_tree_host.h"
     30 #include "cc/trees/layer_tree_impl.h"
     31 #include "cc/trees/single_thread_proxy.h"
     32 #include "gpu/GLES2/gl2extchromium.h"
     33 #include "testing/gmock/include/gmock/gmock.h"
     34 #include "testing/gtest/include/gtest/gtest.h"
     35 
     36 using ::testing::Mock;
     37 using ::testing::_;
     38 using ::testing::AtLeast;
     39 using ::testing::AnyNumber;
     40 using ::testing::InvokeWithoutArgs;
     41 
     42 namespace cc {
     43 namespace {
     44 
     45 gpu::Mailbox MailboxFromChar(char value) {
     46   gpu::Mailbox mailbox;
     47   memset(mailbox.name, value, sizeof(mailbox.name));
     48   return mailbox;
     49 }
     50 
     51 class MockLayerTreeHost : public LayerTreeHost {
     52  public:
     53   explicit MockLayerTreeHost(FakeLayerTreeHostClient* client)
     54       : LayerTreeHost(client, NULL, LayerTreeSettings()) {
     55     InitializeSingleThreaded(client);
     56   }
     57 
     58   MOCK_METHOD0(SetNeedsCommit, void());
     59   MOCK_METHOD0(SetNeedsUpdateLayers, void());
     60   MOCK_METHOD0(StartRateLimiter, void());
     61   MOCK_METHOD0(StopRateLimiter, void());
     62 };
     63 
     64 class FakeTextureLayerClient : public TextureLayerClient {
     65  public:
     66   FakeTextureLayerClient() : mailbox_changed_(true) {}
     67 
     68   virtual bool PrepareTextureMailbox(
     69       TextureMailbox* mailbox,
     70       scoped_ptr<SingleReleaseCallback>* release_callback,
     71       bool use_shared_memory) OVERRIDE {
     72     if (!mailbox_changed_)
     73       return false;
     74 
     75     *mailbox = mailbox_;
     76     *release_callback = release_callback_.Pass();
     77     mailbox_changed_ = false;
     78     return true;
     79   }
     80 
     81   void set_mailbox(const TextureMailbox& mailbox,
     82                    scoped_ptr<SingleReleaseCallback> release_callback) {
     83     mailbox_ = mailbox;
     84     release_callback_ = release_callback.Pass();
     85     mailbox_changed_ = true;
     86   }
     87 
     88  private:
     89   TextureMailbox mailbox_;
     90   scoped_ptr<SingleReleaseCallback> release_callback_;
     91   bool mailbox_changed_;
     92   DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient);
     93 };
     94 
     95 class MockMailboxCallback {
     96  public:
     97   MOCK_METHOD3(Release,
     98                void(const gpu::Mailbox& mailbox,
     99                     uint32 sync_point,
    100                     bool lost_resource));
    101   MOCK_METHOD3(Release2,
    102                void(base::SharedMemory* shared_memory,
    103                     uint32 sync_point,
    104                     bool lost_resource));
    105 };
    106 
    107 struct CommonMailboxObjects {
    108   CommonMailboxObjects()
    109       : mailbox_name1_(MailboxFromChar('1')),
    110         mailbox_name2_(MailboxFromChar('2')),
    111         sync_point1_(1),
    112         sync_point2_(2),
    113         shared_memory_(new base::SharedMemory) {
    114     release_mailbox1_ = base::Bind(&MockMailboxCallback::Release,
    115                                    base::Unretained(&mock_callback_),
    116                                    mailbox_name1_);
    117     release_mailbox2_ = base::Bind(&MockMailboxCallback::Release,
    118                                    base::Unretained(&mock_callback_),
    119                                    mailbox_name2_);
    120     const uint32 arbitrary_target1 = GL_TEXTURE_2D;
    121     const uint32 arbitrary_target2 = GL_TEXTURE_EXTERNAL_OES;
    122     mailbox1_ = TextureMailbox(mailbox_name1_, arbitrary_target1, sync_point1_);
    123     mailbox2_ = TextureMailbox(mailbox_name2_, arbitrary_target2, sync_point2_);
    124     gfx::Size size(128, 128);
    125     EXPECT_TRUE(shared_memory_->CreateAndMapAnonymous(4 * size.GetArea()));
    126     release_mailbox3_ = base::Bind(&MockMailboxCallback::Release2,
    127                                    base::Unretained(&mock_callback_),
    128                                    shared_memory_.get());
    129     mailbox3_ = TextureMailbox(shared_memory_.get(), size);
    130   }
    131 
    132   gpu::Mailbox mailbox_name1_;
    133   gpu::Mailbox mailbox_name2_;
    134   MockMailboxCallback mock_callback_;
    135   ReleaseCallback release_mailbox1_;
    136   ReleaseCallback release_mailbox2_;
    137   ReleaseCallback release_mailbox3_;
    138   TextureMailbox mailbox1_;
    139   TextureMailbox mailbox2_;
    140   TextureMailbox mailbox3_;
    141   uint32 sync_point1_;
    142   uint32 sync_point2_;
    143   scoped_ptr<base::SharedMemory> shared_memory_;
    144 };
    145 
    146 class TextureLayerTest : public testing::Test {
    147  public:
    148   TextureLayerTest()
    149       : fake_client_(
    150             FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
    151         host_impl_(&proxy_, &shared_bitmap_manager_) {}
    152 
    153  protected:
    154   virtual void SetUp() {
    155     layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
    156     EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
    157     layer_tree_host_->SetViewportSize(gfx::Size(10, 10));
    158     Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    159   }
    160 
    161   virtual void TearDown() {
    162     Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    163     EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
    164 
    165     layer_tree_host_->SetRootLayer(NULL);
    166     layer_tree_host_.reset();
    167   }
    168 
    169   scoped_ptr<MockLayerTreeHost> layer_tree_host_;
    170   FakeImplProxy proxy_;
    171   FakeLayerTreeHostClient fake_client_;
    172   TestSharedBitmapManager shared_bitmap_manager_;
    173   FakeLayerTreeHostImpl host_impl_;
    174 };
    175 
    176 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) {
    177   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
    178   EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer));
    179 
    180   // Test properties that should call SetNeedsCommit.  All properties need to
    181   // be set to new values in order for SetNeedsCommit to be called.
    182   EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false));
    183   EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV(
    184       gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f)));
    185   EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity(
    186       0.5f, 0.5f, 0.5f, 0.5f));
    187   EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false));
    188   EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true));
    189 }
    190 
    191 TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) {
    192   const gfx::Size layer_bounds(100, 100);
    193   const gfx::Rect layer_rect(layer_bounds);
    194   const Region layer_region(layer_rect);
    195 
    196   scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(NULL);
    197   layer->SetBounds(layer_bounds);
    198   layer->draw_properties().visible_content_rect = layer_rect;
    199   layer->SetBlendBackgroundColor(true);
    200 
    201   // Verify initial conditions.
    202   EXPECT_FALSE(layer->contents_opaque());
    203   EXPECT_EQ(0u, layer->background_color());
    204   EXPECT_EQ(Region().ToString(),
    205             layer->VisibleContentOpaqueRegion().ToString());
    206 
    207   // Opaque background.
    208   layer->SetBackgroundColor(SK_ColorWHITE);
    209   EXPECT_EQ(layer_region.ToString(),
    210             layer->VisibleContentOpaqueRegion().ToString());
    211 
    212   // Transparent background.
    213   layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
    214   EXPECT_EQ(Region().ToString(),
    215             layer->VisibleContentOpaqueRegion().ToString());
    216 }
    217 
    218 TEST_F(TextureLayerTest, RateLimiter) {
    219   FakeTextureLayerClient client;
    220   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(
    221       &client);
    222   test_layer->SetIsDrawable(true);
    223   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
    224   layer_tree_host_->SetRootLayer(test_layer);
    225 
    226   // Don't rate limit until we invalidate.
    227   EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
    228   test_layer->SetRateLimitContext(true);
    229   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    230 
    231   // Do rate limit after we invalidate.
    232   EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
    233   test_layer->SetNeedsDisplay();
    234   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    235 
    236   // Stop rate limiter when we don't want it any more.
    237   EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
    238   test_layer->SetRateLimitContext(false);
    239   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    240 
    241   // Or we clear the client.
    242   test_layer->SetRateLimitContext(true);
    243   EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
    244   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
    245   test_layer->ClearClient();
    246   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    247 
    248   // Reset to a layer with a client, that started the rate limiter.
    249   test_layer = TextureLayer::CreateForMailbox(
    250       &client);
    251   test_layer->SetIsDrawable(true);
    252   test_layer->SetRateLimitContext(true);
    253   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
    254   layer_tree_host_->SetRootLayer(test_layer);
    255   EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
    256   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    257   EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
    258   test_layer->SetNeedsDisplay();
    259   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    260 
    261   // Stop rate limiter when we're removed from the tree.
    262   EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
    263   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
    264   layer_tree_host_->SetRootLayer(NULL);
    265   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    266 }
    267 
    268 class TestMailboxHolder : public TextureLayer::TextureMailboxHolder {
    269  public:
    270   using TextureLayer::TextureMailboxHolder::Create;
    271 
    272  protected:
    273   virtual ~TestMailboxHolder() {}
    274 };
    275 
    276 class TextureLayerWithMailboxTest : public TextureLayerTest {
    277  protected:
    278   virtual void TearDown() {
    279     Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    280     EXPECT_CALL(test_data_.mock_callback_,
    281                 Release(test_data_.mailbox_name1_,
    282                         test_data_.sync_point1_,
    283                         false)).Times(1);
    284     TextureLayerTest::TearDown();
    285   }
    286 
    287   CommonMailboxObjects test_data_;
    288 };
    289 
    290 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
    291   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
    292   ASSERT_TRUE(test_layer.get());
    293 
    294   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
    295   layer_tree_host_->SetRootLayer(test_layer);
    296   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    297 
    298   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
    299   test_layer->SetTextureMailbox(
    300       test_data_.mailbox1_,
    301       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
    302   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    303 
    304   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
    305   EXPECT_CALL(test_data_.mock_callback_,
    306               Release(test_data_.mailbox_name1_,
    307                       test_data_.sync_point1_,
    308                       false))
    309       .Times(1);
    310   test_layer->SetTextureMailbox(
    311       test_data_.mailbox2_,
    312       SingleReleaseCallback::Create(test_data_.release_mailbox2_));
    313   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    314   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    315 
    316   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
    317   EXPECT_CALL(test_data_.mock_callback_,
    318               Release(test_data_.mailbox_name2_,
    319                       test_data_.sync_point2_,
    320                       false))
    321       .Times(1);
    322   test_layer->SetTextureMailbox(TextureMailbox(),
    323                                 scoped_ptr<SingleReleaseCallback>());
    324   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    325   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    326 
    327   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
    328   test_layer->SetTextureMailbox(
    329       test_data_.mailbox3_,
    330       SingleReleaseCallback::Create(test_data_.release_mailbox3_));
    331   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    332   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    333 
    334   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
    335   EXPECT_CALL(test_data_.mock_callback_,
    336               Release2(test_data_.shared_memory_.get(),
    337                        0, false))
    338       .Times(1);
    339   test_layer->SetTextureMailbox(TextureMailbox(),
    340                                 scoped_ptr<SingleReleaseCallback>());
    341   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    342   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    343 
    344   // Test destructor.
    345   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
    346   test_layer->SetTextureMailbox(
    347       test_data_.mailbox1_,
    348       SingleReleaseCallback::Create(test_data_.release_mailbox1_));
    349 }
    350 
    351 TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) {
    352   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
    353   ASSERT_TRUE(test_layer.get());
    354 
    355   // These use the same gpu::Mailbox, but different sync points.
    356   TextureMailbox mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D, 1);
    357   TextureMailbox mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D, 2);
    358 
    359   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
    360   layer_tree_host_->SetRootLayer(test_layer);
    361   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    362 
    363   // Set the mailbox the first time. It should cause a commit.
    364   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
    365   test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox1);
    366   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    367 
    368   // Set the mailbox again with a new sync point, as the backing texture has
    369   // been updated. It should cause a new commit.
    370   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
    371   test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox2);
    372   Mock::VerifyAndClearExpectations(layer_tree_host_.get());
    373 }
    374 
    375 class TextureLayerMailboxHolderTest : public TextureLayerTest {
    376  public:
    377   TextureLayerMailboxHolderTest()
    378       : main_thread_("MAIN") {
    379     main_thread_.Start();
    380   }
    381 
    382   void Wait(const base::Thread& thread) {
    383     bool manual_reset = false;
    384     bool initially_signaled = false;
    385     base::WaitableEvent event(manual_reset, initially_signaled);
    386     thread.message_loop()->PostTask(
    387         FROM_HERE,
    388         base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
    389     event.Wait();
    390   }
    391 
    392   void CreateMainRef() {
    393     main_ref_ = TestMailboxHolder::Create(
    394         test_data_.mailbox1_,
    395         SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass();
    396   }
    397 
    398   void ReleaseMainRef() {
    399     main_ref_.reset();
    400   }
    401 
    402   void CreateImplRef(scoped_ptr<SingleReleaseCallback>* impl_ref) {
    403     *impl_ref = main_ref_->holder()->GetCallbackForImplThread();
    404   }
    405 
    406   void CapturePostTasksAndWait(base::WaitableEvent* begin_capture,
    407                                base::WaitableEvent* wait_for_capture,
    408                                base::WaitableEvent* stop_capture) {
    409     begin_capture->Wait();
    410     BlockingTaskRunner::CapturePostTasks capture;
    411     wait_for_capture->Signal();
    412     stop_capture->Wait();
    413   }
    414 
    415  protected:
    416   scoped_ptr<TestMailboxHolder::MainThreadReference>
    417       main_ref_;
    418   base::Thread main_thread_;
    419   CommonMailboxObjects test_data_;
    420 };
    421 
    422 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) {
    423   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
    424   ASSERT_TRUE(test_layer.get());
    425 
    426   main_thread_.message_loop()->PostTask(
    427       FROM_HERE,
    428       base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
    429                  base::Unretained(this)));
    430 
    431   Wait(main_thread_);
    432 
    433   // The texture layer is attached to compositor1, and passes a reference to its
    434   // impl tree.
    435   scoped_ptr<SingleReleaseCallback> compositor1;
    436   main_thread_.message_loop()->PostTask(
    437       FROM_HERE,
    438       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
    439                  base::Unretained(this),
    440                  &compositor1));
    441 
    442   // Then the texture layer is removed and attached to compositor2, and passes a
    443   // reference to its impl tree.
    444   scoped_ptr<SingleReleaseCallback> compositor2;
    445   main_thread_.message_loop()->PostTask(
    446       FROM_HERE,
    447       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
    448                  base::Unretained(this),
    449                  &compositor2));
    450 
    451   Wait(main_thread_);
    452   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    453 
    454   // The compositors both destroy their impl trees before the main thread layer
    455   // is destroyed.
    456   compositor1->Run(100, false);
    457   compositor2->Run(200, false);
    458 
    459   Wait(main_thread_);
    460 
    461   EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
    462   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    463 
    464   // The main thread ref is the last one, so the mailbox is released back to the
    465   // embedder, with the last sync point provided by the impl trees.
    466   EXPECT_CALL(test_data_.mock_callback_,
    467               Release(test_data_.mailbox_name1_, 200, false)).Times(1);
    468 
    469   main_thread_.message_loop()->PostTask(
    470       FROM_HERE,
    471       base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
    472                  base::Unretained(this)));
    473   Wait(main_thread_);
    474   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    475 }
    476 
    477 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) {
    478   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
    479   ASSERT_TRUE(test_layer.get());
    480 
    481   main_thread_.message_loop()->PostTask(
    482       FROM_HERE,
    483       base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
    484                  base::Unretained(this)));
    485 
    486   Wait(main_thread_);
    487 
    488   // The texture layer is attached to compositor1, and passes a reference to its
    489   // impl tree.
    490   scoped_ptr<SingleReleaseCallback> compositor1;
    491   main_thread_.message_loop()->PostTask(
    492       FROM_HERE,
    493       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
    494                  base::Unretained(this),
    495                  &compositor1));
    496 
    497   // Then the texture layer is removed and attached to compositor2, and passes a
    498   // reference to its impl tree.
    499   scoped_ptr<SingleReleaseCallback> compositor2;
    500   main_thread_.message_loop()->PostTask(
    501       FROM_HERE,
    502       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
    503                  base::Unretained(this),
    504                  &compositor2));
    505 
    506   Wait(main_thread_);
    507   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    508 
    509   // One compositor destroys their impl tree.
    510   compositor1->Run(100, false);
    511 
    512   // Then the main thread reference is destroyed.
    513   main_thread_.message_loop()->PostTask(
    514       FROM_HERE,
    515       base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
    516                  base::Unretained(this)));
    517 
    518   Wait(main_thread_);
    519 
    520   EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
    521   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    522 
    523   // The second impl reference is destroyed last, causing the mailbox to be
    524   // released back to the embedder with the last sync point from the impl tree.
    525   EXPECT_CALL(test_data_.mock_callback_,
    526               Release(test_data_.mailbox_name1_, 200, true)).Times(1);
    527 
    528   compositor2->Run(200, true);
    529   Wait(main_thread_);
    530   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    531 }
    532 
    533 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) {
    534   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
    535   ASSERT_TRUE(test_layer.get());
    536 
    537   main_thread_.message_loop()->PostTask(
    538       FROM_HERE,
    539       base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
    540                  base::Unretained(this)));
    541 
    542   Wait(main_thread_);
    543 
    544   // The texture layer is attached to compositor1, and passes a reference to its
    545   // impl tree.
    546   scoped_ptr<SingleReleaseCallback> compositor1;
    547   main_thread_.message_loop()->PostTask(
    548       FROM_HERE,
    549       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
    550                  base::Unretained(this),
    551                  &compositor1));
    552 
    553   // Then the texture layer is removed and attached to compositor2, and passes a
    554   // reference to its impl tree.
    555   scoped_ptr<SingleReleaseCallback> compositor2;
    556   main_thread_.message_loop()->PostTask(
    557       FROM_HERE,
    558       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
    559                  base::Unretained(this),
    560                  &compositor2));
    561 
    562   Wait(main_thread_);
    563   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    564 
    565   // The main thread reference is destroyed first.
    566   main_thread_.message_loop()->PostTask(
    567       FROM_HERE,
    568       base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
    569                  base::Unretained(this)));
    570 
    571   // One compositor destroys their impl tree.
    572   compositor2->Run(200, false);
    573 
    574   Wait(main_thread_);
    575 
    576   EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
    577   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    578 
    579   // The second impl reference is destroyed last, causing the mailbox to be
    580   // released back to the embedder with the last sync point from the impl tree.
    581   EXPECT_CALL(test_data_.mock_callback_,
    582               Release(test_data_.mailbox_name1_, 100, true)).Times(1);
    583 
    584   compositor1->Run(100, true);
    585   Wait(main_thread_);
    586   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    587 }
    588 
    589 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) {
    590   scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
    591   ASSERT_TRUE(test_layer.get());
    592 
    593   main_thread_.message_loop()->PostTask(
    594       FROM_HERE,
    595       base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
    596                  base::Unretained(this)));
    597 
    598   Wait(main_thread_);
    599 
    600   // The texture layer is attached to compositor1, and passes a reference to its
    601   // impl tree.
    602   scoped_ptr<SingleReleaseCallback> compositor1;
    603   main_thread_.message_loop()->PostTask(
    604       FROM_HERE,
    605       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
    606                  base::Unretained(this),
    607                  &compositor1));
    608 
    609   // Then the texture layer is removed and attached to compositor2, and passes a
    610   // reference to its impl tree.
    611   scoped_ptr<SingleReleaseCallback> compositor2;
    612   main_thread_.message_loop()->PostTask(
    613       FROM_HERE,
    614       base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
    615                  base::Unretained(this),
    616                  &compositor2));
    617 
    618   Wait(main_thread_);
    619   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    620 
    621   // The main thread reference is destroyed first.
    622   main_thread_.message_loop()->PostTask(
    623       FROM_HERE,
    624       base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
    625                  base::Unretained(this)));
    626 
    627   EXPECT_CALL(test_data_.mock_callback_,
    628               Release(test_data_.mailbox_name1_, 200, true)).Times(1);
    629 
    630   bool manual_reset = false;
    631   bool initially_signaled = false;
    632   base::WaitableEvent begin_capture(manual_reset, initially_signaled);
    633   base::WaitableEvent wait_for_capture(manual_reset, initially_signaled);
    634   base::WaitableEvent stop_capture(manual_reset, initially_signaled);
    635 
    636   // Post a task to start capturing tasks on the main thread. This will block
    637   // the main thread until we signal the |stop_capture| event.
    638   main_thread_.message_loop()->PostTask(
    639       FROM_HERE,
    640       base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait,
    641                  base::Unretained(this),
    642                  &begin_capture,
    643                  &wait_for_capture,
    644                  &stop_capture));
    645 
    646   // Before the main thread capturing starts, one compositor destroys their
    647   // impl reference. Since capturing did not start, this gets post-tasked to
    648   // the main thread.
    649   compositor1->Run(100, false);
    650 
    651   // Start capturing on the main thread.
    652   begin_capture.Signal();
    653   wait_for_capture.Wait();
    654 
    655   // Meanwhile, the second compositor released its impl reference, but this task
    656   // gets shortcutted directly to the main thread. This means the reference is
    657   // released before compositor1, whose reference will be released later when
    658   // the post-task is serviced. But since it was destroyed _on the impl thread_
    659   // last, its sync point values should be used.
    660   compositor2->Run(200, true);
    661 
    662   stop_capture.Signal();
    663   Wait(main_thread_);
    664 
    665   Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
    666 }
    667 
    668 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest {
    669  public:
    670   TextureLayerImplWithMailboxThreadedCallback()
    671       : callback_count_(0),
    672         commit_count_(0) {}
    673 
    674   // Make sure callback is received on main and doesn't block the impl thread.
    675   void ReleaseCallback(uint32 sync_point, bool lost_resource) {
    676     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
    677     EXPECT_FALSE(lost_resource);
    678     ++callback_count_;
    679   }
    680 
    681   void SetMailbox(char mailbox_char) {
    682     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
    683     scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
    684         base::Bind(
    685             &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback,
    686             base::Unretained(this)));
    687     layer_->SetTextureMailbox(
    688         TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
    689         callback.Pass());
    690   }
    691 
    692   virtual void BeginTest() OVERRIDE {
    693     EXPECT_EQ(true, main_thread_.CalledOnValidThread());
    694 
    695     gfx::Size bounds(100, 100);
    696     root_ = Layer::Create();
    697     root_->SetBounds(bounds);
    698 
    699     layer_ = TextureLayer::CreateForMailbox(NULL);
    700     layer_->SetIsDrawable(true);
    701     layer_->SetBounds(bounds);
    702 
    703     root_->AddChild(layer_);
    704     layer_tree_host()->SetRootLayer(root_);
    705     layer_tree_host()->SetViewportSize(bounds);
    706     SetMailbox('1');
    707     EXPECT_EQ(0, callback_count_);
    708 
    709     // Case #1: change mailbox before the commit. The old mailbox should be
    710     // released immediately.
    711     SetMailbox('2');
    712     EXPECT_EQ(1, callback_count_);
    713     PostSetNeedsCommitToMainThread();
    714   }
    715 
    716   virtual void DidCommit() OVERRIDE {
    717     ++commit_count_;
    718     switch (commit_count_) {
    719       case 1:
    720         // Case #2: change mailbox after the commit (and draw), where the
    721         // layer draws. The old mailbox should be released during the next
    722         // commit.
    723         SetMailbox('3');
    724         EXPECT_EQ(1, callback_count_);
    725         break;
    726       case 2:
    727         EXPECT_EQ(2, callback_count_);
    728         // Case #3: change mailbox when the layer doesn't draw. The old
    729         // mailbox should be released during the next commit.
    730         layer_->SetBounds(gfx::Size());
    731         SetMailbox('4');
    732         break;
    733       case 3:
    734         EXPECT_EQ(3, callback_count_);
    735         // Case #4: release mailbox that was committed but never drawn. The
    736         // old mailbox should be released during the next commit.
    737         layer_->SetTextureMailbox(TextureMailbox(),
    738                                   scoped_ptr<SingleReleaseCallback>());
    739         break;
    740       case 4:
    741         if (layer_tree_host()->settings().impl_side_painting) {
    742           // With impl painting, the texture mailbox will still be on the impl
    743           // thread when the commit finishes, because the layer is not drawble
    744           // when it has no texture mailbox, and thus does not block the commit
    745           // on activation. So, we wait for activation.
    746           // TODO(danakj): fix this. crbug.com/277953
    747           layer_tree_host()->SetNeedsCommit();
    748           break;
    749         } else {
    750           ++commit_count_;
    751         }
    752       case 5:
    753         EXPECT_EQ(4, callback_count_);
    754         // Restore a mailbox for the next step.
    755         SetMailbox('5');
    756         break;
    757       case 6:
    758         // Case #5: remove layer from tree. Callback should *not* be called, the
    759         // mailbox is returned to the main thread.
    760         EXPECT_EQ(4, callback_count_);
    761         layer_->RemoveFromParent();
    762         break;
    763       case 7:
    764         if (layer_tree_host()->settings().impl_side_painting) {
    765           // With impl painting, the texture mailbox will still be on the impl
    766           // thread when the commit finishes, because the layer is not around to
    767           // block the commit on activation anymore. So, we wait for activation.
    768           // TODO(danakj): fix this. crbug.com/277953
    769           layer_tree_host()->SetNeedsCommit();
    770           break;
    771         } else {
    772           ++commit_count_;
    773         }
    774       case 8:
    775         EXPECT_EQ(4, callback_count_);
    776         // Resetting the mailbox will call the callback now.
    777         layer_->SetTextureMailbox(TextureMailbox(),
    778                                   scoped_ptr<SingleReleaseCallback>());
    779         EXPECT_EQ(5, callback_count_);
    780         EndTest();
    781         break;
    782       default:
    783         NOTREACHED();
    784         break;
    785     }
    786   }
    787 
    788   virtual void AfterTest() OVERRIDE {}
    789 
    790  private:
    791   base::ThreadChecker main_thread_;
    792   int callback_count_;
    793   int commit_count_;
    794   scoped_refptr<Layer> root_;
    795   scoped_refptr<TextureLayer> layer_;
    796 };
    797 
    798 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
    799     TextureLayerImplWithMailboxThreadedCallback);
    800 
    801 
    802 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
    803  protected:
    804   TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
    805 
    806   static void ReleaseCallback(uint32 sync_point, bool lost_resource) {}
    807 
    808   void SetMailbox(char mailbox_char) {
    809     scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
    810         base::Bind(
    811             &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
    812     layer_->SetTextureMailbox(
    813         TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
    814         callback.Pass());
    815   }
    816 
    817   virtual void BeginTest() OVERRIDE {
    818     gfx::Size bounds(100, 100);
    819     root_ = Layer::Create();
    820     root_->SetBounds(bounds);
    821 
    822     layer_ = TextureLayer::CreateForMailbox(NULL);
    823     layer_->SetIsDrawable(true);
    824     layer_->SetBounds(bounds);
    825 
    826     root_->AddChild(layer_);
    827     layer_tree_host()->SetRootLayer(root_);
    828     layer_tree_host()->SetViewportSize(bounds);
    829     SetMailbox('1');
    830 
    831     PostSetNeedsCommitToMainThread();
    832   }
    833 
    834   virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
    835     ++activate_count_;
    836   }
    837 
    838   virtual void DidCommit() OVERRIDE {
    839     switch (layer_tree_host()->source_frame_number()) {
    840       case 1:
    841         // The first mailbox has been activated. Set a new mailbox, and
    842         // expect the next commit to finish *after* it is activated.
    843         SetMailbox('2');
    844         break;
    845       case 2:
    846         // The second mailbox has been activated. Remove the layer from
    847         // the tree to cause another commit/activation. The commit should
    848         // finish *after* the layer is removed from the active tree.
    849         layer_->RemoveFromParent();
    850         break;
    851       case 3:
    852         EndTest();
    853         break;
    854     }
    855   }
    856 
    857   virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
    858     switch (host_impl->active_tree()->source_frame_number()) {
    859       case 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 
    880 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
    881     TextureLayerMailboxIsActivatedDuringCommit);
    882 
    883 class 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.
    910 TEST_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 
    986 TEST_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 
   1049 TEST_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 
   1069 TEST_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.
   1096 class 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 
   1183 SINGLE_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).
   1188 class 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 
   1329 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
   1330 
   1331 // Test that TextureLayerImpl::ReleaseResources can be called which releases
   1332 // the mailbox back to TextureLayerClient.
   1333 class 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 
   1381 class 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 
   1394 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
   1395 
   1396 class 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 
   1404 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
   1405 
   1406 class 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 
   1474 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
   1475     TextureLayerWithMailboxMainThreadDeleted);
   1476 
   1477 class 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 
   1548 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
   1549     TextureLayerWithMailboxImplThreadDeleted);
   1550 
   1551 }  // namespace
   1552 }  // namespace cc
   1553