Home | History | Annotate | Download | only in trees
      1 // Copyright 2013 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/output/copy_output_request.h"
      6 #include "cc/output/copy_output_result.h"
      7 #include "cc/test/fake_content_layer.h"
      8 #include "cc/test/fake_content_layer_client.h"
      9 #include "cc/test/fake_output_surface.h"
     10 #include "cc/test/layer_tree_test.h"
     11 #include "cc/trees/layer_tree_impl.h"
     12 #include "gpu/GLES2/gl2extchromium.h"
     13 
     14 namespace cc {
     15 namespace {
     16 
     17 // These tests only use direct rendering, as there is no output to copy for
     18 // delegated renderers.
     19 class LayerTreeHostCopyRequestTest : public LayerTreeTest {};
     20 
     21 class LayerTreeHostCopyRequestTestMultipleRequests
     22     : public LayerTreeHostCopyRequestTest {
     23  protected:
     24   virtual void SetupTree() OVERRIDE {
     25     root = FakeContentLayer::Create(&client_);
     26     root->SetBounds(gfx::Size(20, 20));
     27 
     28     child = FakeContentLayer::Create(&client_);
     29     child->SetBounds(gfx::Size(10, 10));
     30     root->AddChild(child);
     31 
     32     layer_tree_host()->SetRootLayer(root);
     33     LayerTreeHostCopyRequestTest::SetupTree();
     34   }
     35 
     36   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
     37 
     38   virtual void DidCommitAndDrawFrame() OVERRIDE { WaitForCallback(); }
     39 
     40   void WaitForCallback() {
     41     base::MessageLoop::current()->PostTask(
     42         FROM_HERE,
     43         base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::NextStep,
     44                    base::Unretained(this)));
     45   }
     46 
     47   void NextStep() {
     48     int frame = layer_tree_host()->source_frame_number();
     49     switch (frame) {
     50       case 1:
     51         child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
     52             base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
     53                             CopyOutputCallback,
     54                        base::Unretained(this))));
     55         EXPECT_EQ(0u, callbacks_.size());
     56         break;
     57       case 2:
     58         if (callbacks_.size() < 1u) {
     59           WaitForCallback();
     60           return;
     61         }
     62         EXPECT_EQ(1u, callbacks_.size());
     63         EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[0].ToString());
     64 
     65         child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
     66             base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
     67                             CopyOutputCallback,
     68                        base::Unretained(this))));
     69         root->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
     70             base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
     71                             CopyOutputCallback,
     72                        base::Unretained(this))));
     73         child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
     74             base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
     75                             CopyOutputCallback,
     76                        base::Unretained(this))));
     77         EXPECT_EQ(1u, callbacks_.size());
     78         break;
     79       case 3:
     80         if (callbacks_.size() < 4u) {
     81           WaitForCallback();
     82           return;
     83         }
     84         EXPECT_EQ(4u, callbacks_.size());
     85         // The child was copied to a bitmap and passed back twice.
     86         EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[1].ToString());
     87         EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[2].ToString());
     88         // The root was copied to a bitmap and passed back also.
     89         EXPECT_EQ(gfx::Size(20, 20).ToString(), callbacks_[3].ToString());
     90         EndTest();
     91         break;
     92     }
     93   }
     94 
     95   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
     96     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
     97     EXPECT_TRUE(result->HasBitmap());
     98     scoped_ptr<SkBitmap> bitmap = result->TakeBitmap().Pass();
     99     EXPECT_EQ(result->size().ToString(),
    100               gfx::Size(bitmap->width(), bitmap->height()).ToString());
    101     callbacks_.push_back(result->size());
    102   }
    103 
    104   virtual void AfterTest() OVERRIDE { EXPECT_EQ(4u, callbacks_.size()); }
    105 
    106   virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
    107       OVERRIDE {
    108     if (use_gl_renderer_)
    109       return FakeOutputSurface::Create3d();
    110     return FakeOutputSurface::CreateSoftware(
    111         make_scoped_ptr(new SoftwareOutputDevice));
    112   }
    113 
    114   bool use_gl_renderer_;
    115   std::vector<gfx::Size> callbacks_;
    116   FakeContentLayerClient client_;
    117   scoped_refptr<FakeContentLayer> root;
    118   scoped_refptr<FakeContentLayer> child;
    119 };
    120 
    121 // Readback can't be done with a delegating renderer.
    122 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
    123        GLRenderer_RunSingleThread) {
    124   use_gl_renderer_ = true;
    125   RunTest(false, false, false);
    126 }
    127 
    128 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
    129        GLRenderer_RunMultiThread_MainThreadPainting) {
    130   use_gl_renderer_ = true;
    131   RunTest(true, false, false);
    132 }
    133 
    134 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
    135        SoftwareRenderer_RunSingleThread) {
    136   use_gl_renderer_ = false;
    137   RunTest(false, false, false);
    138 }
    139 
    140 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
    141        SoftwareRenderer_RunMultiThread_MainThreadPainting) {
    142   use_gl_renderer_ = false;
    143   RunTest(true, false, false);
    144 }
    145 
    146 class LayerTreeHostCopyRequestTestLayerDestroyed
    147     : public LayerTreeHostCopyRequestTest {
    148  protected:
    149   virtual void SetupTree() OVERRIDE {
    150     root_ = FakeContentLayer::Create(&client_);
    151     root_->SetBounds(gfx::Size(20, 20));
    152 
    153     main_destroyed_ = FakeContentLayer::Create(&client_);
    154     main_destroyed_->SetBounds(gfx::Size(15, 15));
    155     root_->AddChild(main_destroyed_);
    156 
    157     impl_destroyed_ = FakeContentLayer::Create(&client_);
    158     impl_destroyed_->SetBounds(gfx::Size(10, 10));
    159     root_->AddChild(impl_destroyed_);
    160 
    161     layer_tree_host()->SetRootLayer(root_);
    162     LayerTreeHostCopyRequestTest::SetupTree();
    163   }
    164 
    165   virtual void BeginTest() OVERRIDE {
    166     callback_count_ = 0;
    167     PostSetNeedsCommitToMainThread();
    168   }
    169 
    170   virtual void DidCommit() OVERRIDE {
    171     int frame = layer_tree_host()->source_frame_number();
    172     switch (frame) {
    173       case 1:
    174         main_destroyed_->RequestCopyOfOutput(
    175             CopyOutputRequest::CreateBitmapRequest(base::Bind(
    176                 &LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback,
    177                 base::Unretained(this))));
    178         impl_destroyed_->RequestCopyOfOutput(
    179             CopyOutputRequest::CreateBitmapRequest(base::Bind(
    180                 &LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback,
    181                 base::Unretained(this))));
    182         EXPECT_EQ(0, callback_count_);
    183 
    184         // Destroy the main thread layer right away.
    185         main_destroyed_->RemoveFromParent();
    186         main_destroyed_ = NULL;
    187 
    188         // Should callback with a NULL bitmap.
    189         EXPECT_EQ(1, callback_count_);
    190 
    191         // Prevent drawing so we can't make a copy of the impl_destroyed layer.
    192         layer_tree_host()->SetViewportSize(gfx::Size());
    193         break;
    194       case 2:
    195         // Flush the message loops and make sure the callbacks run.
    196         layer_tree_host()->SetNeedsCommit();
    197         break;
    198       case 3:
    199         // No drawing means no readback yet.
    200         EXPECT_EQ(1, callback_count_);
    201 
    202         // Destroy the impl thread layer.
    203         impl_destroyed_->RemoveFromParent();
    204         impl_destroyed_ = NULL;
    205 
    206         // No callback yet because it's on the impl side.
    207         EXPECT_EQ(1, callback_count_);
    208         break;
    209       case 4:
    210         // Flush the message loops and make sure the callbacks run.
    211         layer_tree_host()->SetNeedsCommit();
    212         break;
    213       case 5:
    214         // We should get another callback with a NULL bitmap.
    215         EXPECT_EQ(2, callback_count_);
    216         EndTest();
    217         break;
    218     }
    219   }
    220 
    221   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
    222     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
    223     EXPECT_TRUE(result->IsEmpty());
    224     ++callback_count_;
    225   }
    226 
    227   virtual void AfterTest() OVERRIDE {}
    228 
    229   int callback_count_;
    230   FakeContentLayerClient client_;
    231   scoped_refptr<FakeContentLayer> root_;
    232   scoped_refptr<FakeContentLayer> main_destroyed_;
    233   scoped_refptr<FakeContentLayer> impl_destroyed_;
    234 };
    235 
    236 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestLayerDestroyed);
    237 
    238 class LayerTreeHostCopyRequestTestInHiddenSubtree
    239     : public LayerTreeHostCopyRequestTest {
    240  protected:
    241   virtual void SetupTree() OVERRIDE {
    242     root_ = FakeContentLayer::Create(&client_);
    243     root_->SetBounds(gfx::Size(20, 20));
    244 
    245     grand_parent_layer_ = FakeContentLayer::Create(&client_);
    246     grand_parent_layer_->SetBounds(gfx::Size(15, 15));
    247     root_->AddChild(grand_parent_layer_);
    248 
    249     // parent_layer_ owns a render surface.
    250     parent_layer_ = FakeContentLayer::Create(&client_);
    251     parent_layer_->SetBounds(gfx::Size(15, 15));
    252     parent_layer_->SetForceRenderSurface(true);
    253     grand_parent_layer_->AddChild(parent_layer_);
    254 
    255     copy_layer_ = FakeContentLayer::Create(&client_);
    256     copy_layer_->SetBounds(gfx::Size(10, 10));
    257     parent_layer_->AddChild(copy_layer_);
    258 
    259     layer_tree_host()->SetRootLayer(root_);
    260     LayerTreeHostCopyRequestTest::SetupTree();
    261   }
    262 
    263   void AddCopyRequest(Layer* layer) {
    264     layer->RequestCopyOfOutput(
    265         CopyOutputRequest::CreateBitmapRequest(base::Bind(
    266             &LayerTreeHostCopyRequestTestInHiddenSubtree::CopyOutputCallback,
    267             base::Unretained(this))));
    268   }
    269 
    270   virtual void BeginTest() OVERRIDE {
    271     callback_count_ = 0;
    272     PostSetNeedsCommitToMainThread();
    273 
    274     AddCopyRequest(copy_layer_.get());
    275   }
    276 
    277   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
    278     ++callback_count_;
    279     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
    280     EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString())
    281         << callback_count_;
    282     switch (callback_count_) {
    283       case 1:
    284         // Hide the copy request layer.
    285         grand_parent_layer_->SetHideLayerAndSubtree(false);
    286         parent_layer_->SetHideLayerAndSubtree(false);
    287         copy_layer_->SetHideLayerAndSubtree(true);
    288         AddCopyRequest(copy_layer_.get());
    289         break;
    290       case 2:
    291         // Hide the copy request layer's parent only.
    292         grand_parent_layer_->SetHideLayerAndSubtree(false);
    293         parent_layer_->SetHideLayerAndSubtree(true);
    294         copy_layer_->SetHideLayerAndSubtree(false);
    295         AddCopyRequest(copy_layer_.get());
    296         break;
    297       case 3:
    298         // Hide the copy request layer's grand parent only.
    299         grand_parent_layer_->SetHideLayerAndSubtree(true);
    300         parent_layer_->SetHideLayerAndSubtree(false);
    301         copy_layer_->SetHideLayerAndSubtree(false);
    302         AddCopyRequest(copy_layer_.get());
    303         break;
    304       case 4:
    305         // Hide the copy request layer's parent and grandparent.
    306         grand_parent_layer_->SetHideLayerAndSubtree(true);
    307         parent_layer_->SetHideLayerAndSubtree(true);
    308         copy_layer_->SetHideLayerAndSubtree(false);
    309         AddCopyRequest(copy_layer_.get());
    310         break;
    311       case 5:
    312         // Hide the copy request layer as well as its parent and grandparent.
    313         grand_parent_layer_->SetHideLayerAndSubtree(true);
    314         parent_layer_->SetHideLayerAndSubtree(true);
    315         copy_layer_->SetHideLayerAndSubtree(true);
    316         AddCopyRequest(copy_layer_.get());
    317         break;
    318       case 6:
    319         EndTest();
    320         break;
    321     }
    322   }
    323 
    324   virtual void AfterTest() OVERRIDE {}
    325 
    326   int callback_count_;
    327   FakeContentLayerClient client_;
    328   scoped_refptr<FakeContentLayer> root_;
    329   scoped_refptr<FakeContentLayer> grand_parent_layer_;
    330   scoped_refptr<FakeContentLayer> parent_layer_;
    331   scoped_refptr<FakeContentLayer> copy_layer_;
    332 };
    333 
    334 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
    335     LayerTreeHostCopyRequestTestInHiddenSubtree);
    336 
    337 class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest
    338     : public LayerTreeHostCopyRequestTest {
    339  protected:
    340   virtual void SetupTree() OVERRIDE {
    341     root_ = FakeContentLayer::Create(&client_);
    342     root_->SetBounds(gfx::Size(20, 20));
    343 
    344     grand_parent_layer_ = FakeContentLayer::Create(&client_);
    345     grand_parent_layer_->SetBounds(gfx::Size(15, 15));
    346     grand_parent_layer_->SetHideLayerAndSubtree(true);
    347     root_->AddChild(grand_parent_layer_);
    348 
    349     // parent_layer_ owns a render surface.
    350     parent_layer_ = FakeContentLayer::Create(&client_);
    351     parent_layer_->SetBounds(gfx::Size(15, 15));
    352     parent_layer_->SetForceRenderSurface(true);
    353     grand_parent_layer_->AddChild(parent_layer_);
    354 
    355     copy_layer_ = FakeContentLayer::Create(&client_);
    356     copy_layer_->SetBounds(gfx::Size(10, 10));
    357     parent_layer_->AddChild(copy_layer_);
    358 
    359     layer_tree_host()->SetRootLayer(root_);
    360     LayerTreeHostCopyRequestTest::SetupTree();
    361   }
    362 
    363   virtual void BeginTest() OVERRIDE {
    364     did_draw_ = false;
    365     PostSetNeedsCommitToMainThread();
    366 
    367     copy_layer_->RequestCopyOfOutput(
    368         CopyOutputRequest::CreateBitmapRequest(base::Bind(
    369             &LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest::
    370                  CopyOutputCallback,
    371             base::Unretained(this))));
    372   }
    373 
    374   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
    375     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
    376     EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString());
    377     EndTest();
    378   }
    379 
    380   virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
    381     Renderer* renderer = host_impl->renderer();
    382 
    383     LayerImpl* root = host_impl->active_tree()->root_layer();
    384     LayerImpl* grand_parent = root->children()[0];
    385     LayerImpl* parent = grand_parent->children()[0];
    386     LayerImpl* copy_layer = parent->children()[0];
    387 
    388     // |parent| owns a surface, but it was hidden and not part of the copy
    389     // request so it should not allocate any resource.
    390     EXPECT_FALSE(renderer->HasAllocatedResourcesForTesting(
    391         parent->render_surface()->RenderPassId()));
    392 
    393     // |copy_layer| should have been rendered to a texture since it was needed
    394     // for a copy request.
    395     EXPECT_TRUE(renderer->HasAllocatedResourcesForTesting(
    396         copy_layer->render_surface()->RenderPassId()));
    397 
    398     did_draw_ = true;
    399   }
    400 
    401   virtual void AfterTest() OVERRIDE { EXPECT_TRUE(did_draw_); }
    402 
    403   FakeContentLayerClient client_;
    404   bool did_draw_;
    405   scoped_refptr<FakeContentLayer> root_;
    406   scoped_refptr<FakeContentLayer> grand_parent_layer_;
    407   scoped_refptr<FakeContentLayer> parent_layer_;
    408   scoped_refptr<FakeContentLayer> copy_layer_;
    409 };
    410 
    411 // No output to copy for delegated renderers.
    412 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
    413     LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest);
    414 
    415 class LayerTreeHostCopyRequestTestClippedOut
    416     : public LayerTreeHostCopyRequestTest {
    417  protected:
    418   virtual void SetupTree() OVERRIDE {
    419     root_ = FakeContentLayer::Create(&client_);
    420     root_->SetBounds(gfx::Size(20, 20));
    421 
    422     parent_layer_ = FakeContentLayer::Create(&client_);
    423     parent_layer_->SetBounds(gfx::Size(15, 15));
    424     parent_layer_->SetMasksToBounds(true);
    425     root_->AddChild(parent_layer_);
    426 
    427     copy_layer_ = FakeContentLayer::Create(&client_);
    428     copy_layer_->SetPosition(gfx::Point(15, 15));
    429     copy_layer_->SetBounds(gfx::Size(10, 10));
    430     parent_layer_->AddChild(copy_layer_);
    431 
    432     layer_tree_host()->SetRootLayer(root_);
    433     LayerTreeHostCopyRequestTest::SetupTree();
    434   }
    435 
    436   virtual void BeginTest() OVERRIDE {
    437     PostSetNeedsCommitToMainThread();
    438 
    439     copy_layer_->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
    440         base::Bind(&LayerTreeHostCopyRequestTestClippedOut::CopyOutputCallback,
    441                    base::Unretained(this))));
    442   }
    443 
    444   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
    445     // We should still get a callback with no output if the copy requested layer
    446     // was completely clipped away.
    447     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
    448     EXPECT_EQ(gfx::Size().ToString(), result->size().ToString());
    449     EndTest();
    450   }
    451 
    452   virtual void AfterTest() OVERRIDE {}
    453 
    454   FakeContentLayerClient client_;
    455   scoped_refptr<FakeContentLayer> root_;
    456   scoped_refptr<FakeContentLayer> parent_layer_;
    457   scoped_refptr<FakeContentLayer> copy_layer_;
    458 };
    459 
    460 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
    461     LayerTreeHostCopyRequestTestClippedOut);
    462 
    463 class LayerTreeHostTestAsyncTwoReadbacksWithoutDraw
    464     : public LayerTreeHostCopyRequestTest {
    465  protected:
    466   virtual void SetupTree() OVERRIDE {
    467     root_ = FakeContentLayer::Create(&client_);
    468     root_->SetBounds(gfx::Size(20, 20));
    469 
    470     copy_layer_ = FakeContentLayer::Create(&client_);
    471     copy_layer_->SetBounds(gfx::Size(10, 10));
    472     root_->AddChild(copy_layer_);
    473 
    474     layer_tree_host()->SetRootLayer(root_);
    475     LayerTreeHostCopyRequestTest::SetupTree();
    476   }
    477 
    478   void AddCopyRequest(Layer* layer) {
    479     layer->RequestCopyOfOutput(
    480         CopyOutputRequest::CreateBitmapRequest(base::Bind(
    481             &LayerTreeHostTestAsyncTwoReadbacksWithoutDraw::CopyOutputCallback,
    482             base::Unretained(this))));
    483   }
    484 
    485   virtual void BeginTest() OVERRIDE {
    486     saw_copy_request_ = false;
    487     callback_count_ = 0;
    488     PostSetNeedsCommitToMainThread();
    489 
    490     // Prevent drawing.
    491     layer_tree_host()->SetViewportSize(gfx::Size(0, 0));
    492 
    493     AddCopyRequest(copy_layer_.get());
    494   }
    495 
    496   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
    497     if (impl->active_tree()->source_frame_number() == 0) {
    498       LayerImpl* root = impl->active_tree()->root_layer();
    499       EXPECT_TRUE(root->children()[0]->HasCopyRequest());
    500       saw_copy_request_ = true;
    501     }
    502   }
    503 
    504   virtual void DidCommit() OVERRIDE {
    505     if (layer_tree_host()->source_frame_number() == 1) {
    506       // Allow drawing.
    507       layer_tree_host()->SetViewportSize(gfx::Size(root_->bounds()));
    508 
    509       AddCopyRequest(copy_layer_.get());
    510     }
    511   }
    512 
    513   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
    514     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
    515     EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString());
    516     ++callback_count_;
    517 
    518     if (callback_count_ == 2)
    519       EndTest();
    520   }
    521 
    522   virtual void AfterTest() OVERRIDE { EXPECT_TRUE(saw_copy_request_); }
    523 
    524   bool saw_copy_request_;
    525   int callback_count_;
    526   FakeContentLayerClient client_;
    527   scoped_refptr<FakeContentLayer> root_;
    528   scoped_refptr<FakeContentLayer> copy_layer_;
    529 };
    530 
    531 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
    532     LayerTreeHostTestAsyncTwoReadbacksWithoutDraw);
    533 
    534 class LayerTreeHostCopyRequestTestLostOutputSurface
    535     : public LayerTreeHostCopyRequestTest {
    536  protected:
    537   virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
    538       OVERRIDE {
    539     if (!first_context_provider_.get()) {
    540       first_context_provider_ = TestContextProvider::Create();
    541       return FakeOutputSurface::Create3d(first_context_provider_);
    542     }
    543 
    544     EXPECT_FALSE(second_context_provider_.get());
    545     second_context_provider_ = TestContextProvider::Create();
    546     return FakeOutputSurface::Create3d(second_context_provider_);
    547   }
    548 
    549   virtual void SetupTree() OVERRIDE {
    550     root_ = FakeContentLayer::Create(&client_);
    551     root_->SetBounds(gfx::Size(20, 20));
    552 
    553     copy_layer_ = FakeContentLayer::Create(&client_);
    554     copy_layer_->SetBounds(gfx::Size(10, 10));
    555     root_->AddChild(copy_layer_);
    556 
    557     layer_tree_host()->SetRootLayer(root_);
    558     LayerTreeHostCopyRequestTest::SetupTree();
    559   }
    560 
    561   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
    562 
    563   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
    564     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
    565     EXPECT_EQ(gfx::Size(10, 10).ToString(), result->size().ToString());
    566     EXPECT_TRUE(result->HasTexture());
    567 
    568     // Save the result for later.
    569     EXPECT_FALSE(result_);
    570     result_ = result.Pass();
    571 
    572     // Post a commit to lose the output surface.
    573     layer_tree_host()->SetNeedsCommit();
    574   }
    575 
    576   virtual void DidCommitAndDrawFrame() OVERRIDE {
    577     switch (layer_tree_host()->source_frame_number()) {
    578       case 1:
    579         // The layers have been pushed to the impl side. The layer textures have
    580         // been allocated.
    581 
    582         // Request a copy of the layer. This will use another texture.
    583         copy_layer_->RequestCopyOfOutput(CopyOutputRequest::CreateRequest(
    584             base::Bind(&LayerTreeHostCopyRequestTestLostOutputSurface::
    585                             CopyOutputCallback,
    586                        base::Unretained(this))));
    587         break;
    588       case 4:
    589       // With SingleThreadProxy it takes two commits to finally swap after a
    590       // context loss.
    591       case 5:
    592         // Now destroy the CopyOutputResult, releasing the texture inside back
    593         // to the compositor.
    594         EXPECT_TRUE(result_);
    595         result_.reset();
    596 
    597         // Check that it is released.
    598         ImplThreadTaskRunner()->PostTask(
    599             FROM_HERE,
    600             base::Bind(&LayerTreeHostCopyRequestTestLostOutputSurface::
    601                             CheckNumTextures,
    602                        base::Unretained(this),
    603                        num_textures_after_loss_ - 1));
    604         break;
    605     }
    606   }
    607 
    608   virtual void SwapBuffersOnThread(LayerTreeHostImpl* impl,
    609                                    bool result) OVERRIDE {
    610     switch (impl->active_tree()->source_frame_number()) {
    611       case 0:
    612         // The layers have been drawn, so their textures have been allocated.
    613         EXPECT_FALSE(result_);
    614         num_textures_without_readback_ =
    615             first_context_provider_->TestContext3d()->NumTextures();
    616         break;
    617       case 1:
    618         // We did a readback, so there will be a readback texture around now.
    619         EXPECT_LT(num_textures_without_readback_,
    620                   first_context_provider_->TestContext3d()->NumTextures());
    621         break;
    622       case 2:
    623         // The readback texture is collected.
    624         EXPECT_TRUE(result_);
    625 
    626         // Lose the output surface.
    627         first_context_provider_->TestContext3d()->loseContextCHROMIUM(
    628             GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
    629         break;
    630       case 3:
    631       // With SingleThreadProxy it takes two commits to finally swap after a
    632       // context loss.
    633       case 4:
    634         // The output surface has been recreated.
    635         EXPECT_TRUE(second_context_provider_.get());
    636 
    637         num_textures_after_loss_ =
    638             first_context_provider_->TestContext3d()->NumTextures();
    639         break;
    640     }
    641   }
    642 
    643   void CheckNumTextures(size_t expected_num_textures) {
    644     EXPECT_EQ(expected_num_textures,
    645               first_context_provider_->TestContext3d()->NumTextures());
    646     EndTest();
    647   }
    648 
    649   virtual void AfterTest() OVERRIDE {}
    650 
    651   scoped_refptr<TestContextProvider> first_context_provider_;
    652   scoped_refptr<TestContextProvider> second_context_provider_;
    653   size_t num_textures_without_readback_;
    654   size_t num_textures_after_loss_;
    655   FakeContentLayerClient client_;
    656   scoped_refptr<FakeContentLayer> root_;
    657   scoped_refptr<FakeContentLayer> copy_layer_;
    658   scoped_ptr<CopyOutputResult> result_;
    659 };
    660 
    661 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
    662     LayerTreeHostCopyRequestTestLostOutputSurface);
    663 
    664 class LayerTreeHostCopyRequestTestCountTextures
    665     : public LayerTreeHostCopyRequestTest {
    666  protected:
    667   virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
    668       OVERRIDE {
    669     context_provider_ = TestContextProvider::Create();
    670     return FakeOutputSurface::Create3d(context_provider_);
    671   }
    672 
    673   virtual void SetupTree() OVERRIDE {
    674     root_ = FakeContentLayer::Create(&client_);
    675     root_->SetBounds(gfx::Size(20, 20));
    676 
    677     copy_layer_ = FakeContentLayer::Create(&client_);
    678     copy_layer_->SetBounds(gfx::Size(10, 10));
    679     root_->AddChild(copy_layer_);
    680 
    681     layer_tree_host()->SetRootLayer(root_);
    682     LayerTreeHostCopyRequestTest::SetupTree();
    683   }
    684 
    685   virtual void BeginTest() OVERRIDE {
    686     num_textures_without_readback_ = 0;
    687     num_textures_with_readback_ = 0;
    688     waited_sync_point_after_readback_ = 0;
    689     PostSetNeedsCommitToMainThread();
    690   }
    691 
    692   virtual void RequestCopy(Layer* layer) = 0;
    693 
    694   virtual void DidCommitAndDrawFrame() OVERRIDE {
    695     switch (layer_tree_host()->source_frame_number()) {
    696       case 1:
    697         // The layers have been pushed to the impl side. The layer textures have
    698         // been allocated.
    699         RequestCopy(copy_layer_.get());
    700         break;
    701     }
    702   }
    703 
    704   virtual void SwapBuffersOnThread(LayerTreeHostImpl* impl,
    705                                    bool result) OVERRIDE {
    706     switch (impl->active_tree()->source_frame_number()) {
    707       case 0:
    708         // The layers have been drawn, so their textures have been allocated.
    709         num_textures_without_readback_ =
    710             context_provider_->TestContext3d()->NumTextures();
    711         break;
    712       case 1:
    713         // We did a readback, so there will be a readback texture around now.
    714         num_textures_with_readback_ =
    715             context_provider_->TestContext3d()->NumTextures();
    716         waited_sync_point_after_readback_ =
    717             context_provider_->TestContext3d()->last_waited_sync_point();
    718 
    719         MainThreadTaskRunner()->PostTask(
    720             FROM_HERE,
    721             base::Bind(&LayerTreeHostCopyRequestTestCountTextures::DoEndTest,
    722                        base::Unretained(this)));
    723         break;
    724     }
    725   }
    726 
    727   virtual void DoEndTest() { EndTest(); }
    728 
    729   scoped_refptr<TestContextProvider> context_provider_;
    730   size_t num_textures_without_readback_;
    731   size_t num_textures_with_readback_;
    732   unsigned waited_sync_point_after_readback_;
    733   FakeContentLayerClient client_;
    734   scoped_refptr<FakeContentLayer> root_;
    735   scoped_refptr<FakeContentLayer> copy_layer_;
    736 };
    737 
    738 class LayerTreeHostCopyRequestTestCreatesTexture
    739     : public LayerTreeHostCopyRequestTestCountTextures {
    740  protected:
    741   virtual void RequestCopy(Layer* layer) OVERRIDE {
    742     // Request a normal texture copy. This should create a new texture.
    743     copy_layer_->RequestCopyOfOutput(
    744         CopyOutputRequest::CreateRequest(base::Bind(
    745             &LayerTreeHostCopyRequestTestCreatesTexture::CopyOutputCallback,
    746             base::Unretained(this))));
    747   }
    748 
    749   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
    750     EXPECT_FALSE(result->IsEmpty());
    751     EXPECT_TRUE(result->HasTexture());
    752 
    753     TextureMailbox mailbox;
    754     scoped_ptr<SingleReleaseCallback> release;
    755     result->TakeTexture(&mailbox, &release);
    756     EXPECT_TRUE(release);
    757 
    758     release->Run(0, false);
    759   }
    760 
    761   virtual void AfterTest() OVERRIDE {
    762     // No sync point was needed.
    763     EXPECT_EQ(0u, waited_sync_point_after_readback_);
    764     // Except the copy to have made another texture.
    765     EXPECT_EQ(num_textures_without_readback_ + 1, num_textures_with_readback_);
    766   }
    767 };
    768 
    769 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
    770     LayerTreeHostCopyRequestTestCreatesTexture);
    771 
    772 class LayerTreeHostCopyRequestTestProvideTexture
    773     : public LayerTreeHostCopyRequestTestCountTextures {
    774  protected:
    775   virtual void BeginTest() OVERRIDE {
    776     external_context_provider_ = TestContextProvider::Create();
    777     EXPECT_TRUE(external_context_provider_->BindToCurrentThread());
    778     LayerTreeHostCopyRequestTestCountTextures::BeginTest();
    779   }
    780 
    781   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
    782     EXPECT_FALSE(result->IsEmpty());
    783     EXPECT_TRUE(result->HasTexture());
    784 
    785     TextureMailbox mailbox;
    786     scoped_ptr<SingleReleaseCallback> release;
    787     result->TakeTexture(&mailbox, &release);
    788     EXPECT_FALSE(release);
    789   }
    790 
    791   virtual void RequestCopy(Layer* layer) OVERRIDE {
    792     // Request a copy to a provided texture. This should not create a new
    793     // texture.
    794     scoped_ptr<CopyOutputRequest> request =
    795         CopyOutputRequest::CreateRequest(base::Bind(
    796             &LayerTreeHostCopyRequestTestProvideTexture::CopyOutputCallback,
    797             base::Unretained(this)));
    798 
    799     gpu::gles2::GLES2Interface* gl = external_context_provider_->ContextGL();
    800     gpu::Mailbox mailbox;
    801     gl->GenMailboxCHROMIUM(mailbox.name);
    802     sync_point_ = gl->InsertSyncPointCHROMIUM();
    803     request->SetTextureMailbox(
    804         TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point_));
    805     EXPECT_TRUE(request->has_texture_mailbox());
    806 
    807     copy_layer_->RequestCopyOfOutput(request.Pass());
    808   }
    809 
    810   virtual void AfterTest() OVERRIDE {
    811     // Expect the compositor to have waited for the sync point in the provided
    812     // TextureMailbox.
    813     EXPECT_EQ(sync_point_, waited_sync_point_after_readback_);
    814     // Except the copy to have *not* made another texture.
    815     EXPECT_EQ(num_textures_without_readback_, num_textures_with_readback_);
    816   }
    817 
    818   scoped_refptr<TestContextProvider> external_context_provider_;
    819   unsigned sync_point_;
    820 };
    821 
    822 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
    823     LayerTreeHostCopyRequestTestProvideTexture);
    824 
    825 class LayerTreeHostCopyRequestTestDestroyBeforeCopy
    826     : public LayerTreeHostCopyRequestTest {
    827  protected:
    828   virtual void SetupTree() OVERRIDE {
    829     root_ = FakeContentLayer::Create(&client_);
    830     root_->SetBounds(gfx::Size(20, 20));
    831 
    832     copy_layer_ = FakeContentLayer::Create(&client_);
    833     copy_layer_->SetBounds(gfx::Size(10, 10));
    834     root_->AddChild(copy_layer_);
    835 
    836     layer_tree_host()->SetRootLayer(root_);
    837     LayerTreeHostCopyRequestTest::SetupTree();
    838   }
    839 
    840   virtual void BeginTest() OVERRIDE {
    841     callback_count_ = 0;
    842     PostSetNeedsCommitToMainThread();
    843   }
    844 
    845   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
    846     EXPECT_TRUE(result->IsEmpty());
    847     ++callback_count_;
    848   }
    849 
    850   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
    851     MainThreadTaskRunner()->PostTask(
    852         FROM_HERE,
    853         base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::DidActivate,
    854                    base::Unretained(this)));
    855   }
    856 
    857   void DidActivate() {
    858     switch (layer_tree_host()->source_frame_number()) {
    859       case 1: {
    860         EXPECT_EQ(0, callback_count_);
    861         // Put a copy request on the layer, but then don't allow any
    862         // drawing to take place.
    863         scoped_ptr<CopyOutputRequest> request =
    864             CopyOutputRequest::CreateRequest(
    865                 base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::
    866                                 CopyOutputCallback,
    867                            base::Unretained(this)));
    868         copy_layer_->RequestCopyOfOutput(request.Pass());
    869 
    870         layer_tree_host()->SetViewportSize(gfx::Size());
    871         break;
    872       }
    873       case 2:
    874         EXPECT_EQ(0, callback_count_);
    875         // Remove the copy layer before we were able to draw.
    876         copy_layer_->RemoveFromParent();
    877         break;
    878       case 3:
    879         EXPECT_EQ(1, callback_count_);
    880         // Allow us to draw now.
    881         layer_tree_host()->SetViewportSize(
    882             layer_tree_host()->root_layer()->bounds());
    883         break;
    884       case 4:
    885         EXPECT_EQ(1, callback_count_);
    886         // We should not have crashed.
    887         EndTest();
    888     }
    889   }
    890 
    891   virtual void AfterTest() OVERRIDE {}
    892 
    893   int callback_count_;
    894   FakeContentLayerClient client_;
    895   scoped_refptr<FakeContentLayer> root_;
    896   scoped_refptr<FakeContentLayer> copy_layer_;
    897 };
    898 
    899 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
    900     LayerTreeHostCopyRequestTestDestroyBeforeCopy);
    901 
    902 class LayerTreeHostCopyRequestTestShutdownBeforeCopy
    903     : public LayerTreeHostCopyRequestTest {
    904  protected:
    905   virtual void SetupTree() OVERRIDE {
    906     root_ = FakeContentLayer::Create(&client_);
    907     root_->SetBounds(gfx::Size(20, 20));
    908 
    909     copy_layer_ = FakeContentLayer::Create(&client_);
    910     copy_layer_->SetBounds(gfx::Size(10, 10));
    911     root_->AddChild(copy_layer_);
    912 
    913     layer_tree_host()->SetRootLayer(root_);
    914     LayerTreeHostCopyRequestTest::SetupTree();
    915   }
    916 
    917   virtual void BeginTest() OVERRIDE {
    918     callback_count_ = 0;
    919     PostSetNeedsCommitToMainThread();
    920   }
    921 
    922   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
    923     EXPECT_TRUE(result->IsEmpty());
    924     ++callback_count_;
    925   }
    926 
    927   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
    928     MainThreadTaskRunner()->PostTask(
    929         FROM_HERE,
    930         base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::DidActivate,
    931                    base::Unretained(this)));
    932   }
    933 
    934   void DidActivate() {
    935     switch (layer_tree_host()->source_frame_number()) {
    936       case 1: {
    937         EXPECT_EQ(0, callback_count_);
    938         // Put a copy request on the layer, but then don't allow any
    939         // drawing to take place.
    940         scoped_ptr<CopyOutputRequest> request =
    941             CopyOutputRequest::CreateRequest(
    942                 base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::
    943                                 CopyOutputCallback,
    944                            base::Unretained(this)));
    945         copy_layer_->RequestCopyOfOutput(request.Pass());
    946 
    947         layer_tree_host()->SetViewportSize(gfx::Size());
    948         break;
    949       }
    950       case 2:
    951         DestroyLayerTreeHost();
    952         // End the test after the copy result has had a chance to get back to
    953         // the main thread.
    954         MainThreadTaskRunner()->PostTask(
    955             FROM_HERE,
    956             base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::EndTest,
    957                        base::Unretained(this)));
    958         break;
    959     }
    960   }
    961 
    962   virtual void AfterTest() OVERRIDE { EXPECT_EQ(1, callback_count_); }
    963 
    964   int callback_count_;
    965   FakeContentLayerClient client_;
    966   scoped_refptr<FakeContentLayer> root_;
    967   scoped_refptr<FakeContentLayer> copy_layer_;
    968 };
    969 
    970 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
    971     LayerTreeHostCopyRequestTestShutdownBeforeCopy);
    972 
    973 }  // namespace
    974 }  // namespace cc
    975